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