1 /* 2 * Copyright 2008, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Alexandre Deckner <alex@zappotek.com> 7 */ 8 9 #include "RenderView.h" 10 11 #include "BitmapTexture.h" 12 #include "Camera.h" 13 #include "MeshInstance.h" 14 #include "StaticMesh.h" 15 #include "VideoFileTexture.h" 16 17 #include <opengl/GL/gl.h> 18 #include <opengl/GL/glu.h> 19 20 #include <TranslationKit.h> 21 #include <TranslationUtils.h> 22 23 #include <stdio.h> 24 25 RenderView::RenderView(BRect frame) 26 : 27 BGLView(frame, "renderView", B_FOLLOW_ALL, B_WILL_DRAW, 28 BGL_RGB | BGL_DOUBLE | BGL_DEPTH), 29 fMainCamera(NULL), 30 fRenderThread(-1), 31 fStopRendering(false), 32 fRes(0, 0), 33 fNextRes(0, 0), 34 fLastFrameTime(0) 35 { 36 } 37 38 39 RenderView::~RenderView() 40 { 41 _StopRenderThread(); 42 _DeleteScene(); 43 } 44 45 46 void 47 RenderView::AttachedToWindow() 48 { 49 BGLView::AttachedToWindow(); 50 51 _CreateScene(); 52 _InitGL(); 53 if (_CreateRenderThread() != B_OK) 54 printf("Error trying to start the render thread!\n"); 55 } 56 57 58 uint32 59 RenderView::_CreateRenderThread() 60 { 61 fRenderThread = spawn_thread(RenderView::_RenderThreadEntry, "renderThread", 62 B_NORMAL_PRIORITY, this); 63 64 if (fRenderThread < 0) 65 return fRenderThread; 66 67 return resume_thread(fRenderThread); 68 } 69 70 71 void 72 RenderView::_StopRenderThread() 73 { 74 LockGL(); 75 fStopRendering = true; 76 UnlockGL(); 77 78 if (fRenderThread >= 0) 79 wait_for_thread(fRenderThread, NULL); 80 } 81 82 83 int32 84 RenderView::_RenderThreadEntry(void *pointer) 85 { 86 return reinterpret_cast<RenderView*>(pointer)->_RenderLoop(); 87 } 88 89 90 int32 91 RenderView::_RenderLoop() 92 { 93 fLastFrameTime = system_time(); 94 95 while (_Render()) { 96 snooze(10000); 97 } 98 return B_OK; 99 } 100 101 102 void RenderView::_InitGL(void) 103 { 104 LockGL(); 105 106 float position[] = {0.0, 3.0, 6.0, 0.0}; 107 float local_view[] = {0.0, 0.0}; 108 109 glLightfv(GL_LIGHT0, GL_POSITION, position); 110 glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view); 111 112 float white[3] = {1.0, 1.0, 1.0}; 113 114 glEnable(GL_LIGHT0); 115 glLightfv(GL_LIGHT0, GL_SPECULAR, white); 116 glLightfv(GL_LIGHT0, GL_DIFFUSE, white); 117 glLightfv(GL_LIGHT0, GL_AMBIENT, white); 118 119 glMaterialf(GL_FRONT, GL_SHININESS, 0.6 * 128.0); 120 121 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 122 glEnable(GL_CULL_FACE); 123 glEnable(GL_DEPTH_TEST); 124 glEnable(GL_LIGHTING); 125 glEnable(GL_TEXTURE_2D); 126 127 fNextRes.Set(Bounds().Width(), Bounds().Height()); 128 _UpdateViewport(); 129 130 UnlockGL(); 131 } 132 133 134 void 135 RenderView::_CreateScene() 136 { 137 Texture *texture = new BitmapTexture( 138 BTranslationUtils::GetBitmap(B_PNG_FORMAT, "texture")); 139 140 float spacing = 1.6f; 141 float timeSpacing = 5.0f; 142 float yOffset = -1.0f; 143 float zOffset = -16; 144 145 Mesh* mesh = new StaticMesh("LetterH"); 146 MeshInstance *instance = new MeshInstance(mesh, texture, 147 Vector3(-3.6 * spacing, yOffset, zOffset), 148 Quaternion(0, 0, 0, 1), 0.0f); 149 fMeshInstances.push_back(instance); 150 mesh->ReleaseReference(); 151 152 mesh = new StaticMesh("LetterA"); 153 instance = new MeshInstance(mesh, texture, 154 Vector3(-1.6 * spacing, yOffset, zOffset), 155 Quaternion(0, 0, 0, 1), 1.0f * timeSpacing); 156 fMeshInstances.push_back(instance); 157 mesh->ReleaseReference(); 158 159 mesh = new StaticMesh("LetterI"); 160 instance = new MeshInstance(mesh, texture, 161 Vector3(0 * spacing, yOffset, zOffset), 162 Quaternion(0, 0, 0, 1), 2.0f * timeSpacing); 163 fMeshInstances.push_back(instance); 164 mesh->ReleaseReference(); 165 166 mesh = new StaticMesh("LetterK"); 167 instance = new MeshInstance(mesh, texture, 168 Vector3(1.5 * spacing, yOffset, zOffset), 169 Quaternion(0, 0, 0, 1), 3.0f * timeSpacing); 170 fMeshInstances.push_back(instance); 171 mesh->ReleaseReference(); 172 173 mesh = new StaticMesh("LetterU"); 174 instance = new MeshInstance(mesh, texture, 175 Vector3(3.4 * spacing, yOffset, zOffset), 176 Quaternion(0, 0, 0, 1), 4.0f * timeSpacing); 177 fMeshInstances.push_back(instance); 178 mesh->ReleaseReference(); 179 texture->ReleaseReference(); 180 181 fMainCamera = new Camera(Vector3(0, 0, 0), Quaternion(0, 0, 0, 1), 50); 182 } 183 184 185 void 186 RenderView::_DeleteScene() 187 { 188 MeshInstanceList::iterator it = fMeshInstances.begin(); 189 for(; it != fMeshInstances.end(); it++) { 190 delete (*it); 191 } 192 fMeshInstances.clear(); 193 } 194 195 196 void 197 RenderView::_UpdateViewport() 198 { 199 if (fNextRes != fRes && fNextRes.x >= 1.0 && fNextRes.y >= 1.0) { 200 glViewport(0, 0, (GLint) fNextRes.x + 1, (GLint) fNextRes.y + 1); 201 fRes = fNextRes; 202 _UpdateCamera(); 203 } 204 } 205 206 207 void 208 RenderView::_UpdateCamera() 209 { 210 // TODO: take camera orientation into account 211 glMatrixMode(GL_PROJECTION); 212 glLoadIdentity(); 213 gluPerspective(fMainCamera->FieldOfView(), fNextRes.x / fNextRes.y, 214 fMainCamera->Near(), fMainCamera->Far()); 215 glMatrixMode(GL_MODELVIEW); 216 } 217 218 219 bool 220 RenderView::_Render() 221 { 222 LockGL(); 223 224 _UpdateViewport(); 225 226 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 227 glLoadIdentity(); 228 229 bigtime_t time = system_time(); 230 float deltaTime = 0.000001 * (float)(time - fLastFrameTime); 231 fLastFrameTime = time; 232 233 MeshInstanceList::iterator it = fMeshInstances.begin(); 234 for(; it != fMeshInstances.end(); it++) { 235 (*it)->Update(deltaTime); 236 (*it)->Render(); 237 } 238 239 if (fStopRendering) { 240 UnlockGL(); 241 return false; 242 } 243 UnlockGL(); 244 SwapBuffers(false); // true = vsync 245 return true; 246 } 247 248 249 void 250 RenderView::FrameResized(float width, float height) 251 { 252 LockGL(); 253 fNextRes.Set(width, height); 254 UnlockGL(); 255 BGLView::FrameResized(width, height); 256 } 257 258 259 void 260 RenderView::ErrorCallback(uint32 error) 261 { 262 fprintf(stderr, "OpenGL error (%li): %s\n", error, gluErrorString(error)); 263 } 264