xref: /haiku/src/apps/haiku3d/RenderView.cpp (revision 26d22ee8dc5db3cea88354d0536f5dd9950b6bcf)
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