xref: /haiku/src/apps/haiku3d/RenderView.cpp (revision e81a954787e50e56a7f06f72705b7859b6ab06d1)
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 	_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(unsigned long error)
261 {
262 	fprintf(stderr, "OpenGL error (%lu): %s\n", error, gluErrorString(error));
263 }
264