xref: /haiku/src/apps/glteapot/GLObject.cpp (revision 1a3518cf757c2da8006753f83962da5935bbc82b)
1 /*
2  * Copyright 2008 Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Alexandre Deckner
7  *
8  */
9 
10 /*
11  * Original Be Sample source modified to use a quaternion for the object's orientation
12  */
13 
14 /*
15 	Copyright 1999, Be Incorporated.   All Rights Reserved.
16 	This file may be used under the terms of the Be Sample Code License.
17 */
18 
19 
20 #include "GLObject.h"
21 
22 #include <Application.h>
23 #include <GL/gl.h>
24 #include <InterfaceKit.h>
25 #include <Resources.h>
26 
27 #include "glob.h"
28 
29 
30 struct material {
31 	float ambient[3], diffuse[3], specular[3];
32 };
33 
34 float *colors[] = {NULL, white, yellow, blue, red, green};
35 
36 material materials[] = {
37 	// Null
38 	{
39 		{0.1745, 0.03175, 0.03175},
40 		{0.61424, 0.10136, 0.10136},
41 		{0.727811, 0.626959, 0.626959}
42 	},
43 	// White
44 	{
45 		{0.1745, 0.1745, 0.1745},
46 		{0.61424, 0.61424, 0.61424},
47 		{0.727811, 0.727811, 0.727811}
48 	},
49 	// Yellow
50 	{
51 		{0.1745, 0.1745, 0.03175},
52 		{0.61424, 0.61424, 0.10136},
53 		{0.727811, 0.727811, 0.626959}
54 	},
55 	// Blue
56 	{
57 		{0.03175, 0.03175, 0.1745},
58 		{0.10136, 0.10136, 0.61424},
59 		{0.626959, 0.626959, 0.727811}
60 	},
61 	// Red
62 	{
63 		{0.1745, 0.03175, 0.03175},
64 		{0.61424, 0.10136, 0.10136},
65 		{0.727811, 0.626959, 0.626959}
66 	},
67 	// Green
68 	{
69 		{0.03175, 0.1745, 0.03175},
70 		{0.10136, 0.61424, 0.10136},
71 		{0.626959, 0.727811, 0.626959}
72 	},
73 };
74 
75 #define USE_QUAD_STRIPS 1
76 
77 extern long setEvent(sem_id event);
78 
79 
80 GLObject::GLObject(ObjectView* ov)
81 	:
82 	x(0),
83 	y(0),
84 	z(-2.0),
85 	fRotation(0.0f, 0.0f, 0.0f, 1.0f),
86 	spinX(2),
87 	spinY(2),
88 	solidity(0),
89 	color(4),
90 	changed(false),
91 	fObjView(ov)
92 {
93 }
94 
95 
96 GLObject::~GLObject()
97 {
98 }
99 
100 
101 void
102 GLObject::MenuInvoked(BPoint point)
103 {
104 	BPopUpMenu* m = new BPopUpMenu("Object",false,false);
105 	BMenuItem* i;
106 
107 	int c = 1;
108 	m->AddItem(i = new BMenuItem("White",NULL));
109 	if (color == c++)
110 		i->SetMarked(true);
111 	m->AddItem(i = new BMenuItem("Yellow",NULL));
112 	if (color == c++)
113 		i->SetMarked(true);
114 	m->AddItem(i = new BMenuItem("Blue",NULL));
115 	if (color == c++)
116 		i->SetMarked(true);
117 	m->AddItem(i = new BMenuItem("Red",NULL));
118 	if (color == c++)
119 		i->SetMarked(true);
120 	m->AddItem(i = new BMenuItem("Green",NULL));
121 	if (color == c++)
122 		i->SetMarked(true);
123 	m->AddSeparatorItem();
124 
125 	c = 0;
126 	m->AddItem(i = new BMenuItem("Solid",NULL));
127 	if (solidity == c++)
128 		i->SetMarked(true);
129 	m->AddItem(i = new BMenuItem("Translucent",NULL));
130 	if (solidity == c++)
131 		i->SetMarked(true);
132 	m->AddItem(i = new BMenuItem("Transparent",NULL));
133 	if (solidity == c++)
134 		i->SetMarked(true);
135 
136 	i = m->Go(point);
137 	int32 index = m->IndexOf(i);
138 	delete m;
139 
140 	if (index < 5) {
141 		color = index+1;
142 	} else if (index > 5) {
143 		solidity = index-6;
144 	}
145 	changed = true;
146 	setEvent(fObjView->drawEvent);
147 }
148 
149 
150 int
151 GLObject::Solidity() const
152 {
153 	return solidity;
154 }
155 
156 
157 
158 bool
159 GLObject::SpinIt()
160 {
161 	bool c = changed;
162 	c = c || ((spinX != 0.0f) || (spinY != 0.0f));
163 
164 	if (c)
165 		RotateWorldSpace(spinY, spinX);
166 
167 	return c;
168 }
169 
170 
171 void
172 GLObject::Spin(float rx, float ry)
173 {
174 	spinX = rx;
175 	spinY = ry;
176 }
177 
178 
179 void
180 GLObject::RotateWorldSpace(float rx, float ry)
181 {
182 	fRotation = Quaternion(Vector3(0.0f, 1.0f, 0.0f), 0.01f * rx) * fRotation;
183 	fRotation = Quaternion(Vector3(1.0f, 0.0f, 0.0f), 0.01f * ry) * fRotation;
184 	fRotation.normalize();
185 	changed = true;
186 }
187 
188 
189 void
190 GLObject::Draw(bool forID, float IDcolor[])
191 {
192 	glPushMatrix();
193 		glTranslatef(x, y, z);
194 
195 		float mat[4][4];
196 		fRotation.toOpenGLMatrix(mat);
197 		glMultMatrixf((GLfloat*)mat);
198 
199 		if (forID) {
200 			glColor3fv(IDcolor);
201 		}
202 
203 		DoDrawing(forID);
204 
205 	glPopMatrix();
206 
207 	changed = false;
208 }
209 
210 
211 TriangleObject::TriangleObject(ObjectView* ov)
212 		:
213 		GLObject(ov),
214 		fStatus(B_NO_INIT),
215 		fPoints(100, 100),
216 		fTriangles(100, 100),
217 		fQs(50, 50)
218 {
219 	BResources *res = BApplication::AppResources();
220 	if (res == NULL)
221 		return;
222 
223 	size_t size = 0;
224 	int32 *arrayOfPoints
225 					= (int32*)res->LoadResource(B_RAW_TYPE, "points", &size);
226 	if (arrayOfPoints == NULL)
227 		return;
228 
229 	float maxp = 0;
230 	size_t numPt = size / sizeof(int32);
231 	for (size_t i = 0; i < numPt; i += 6) {
232 		point p;
233 		p.x = 1e-6 * arrayOfPoints[i];
234 		p.y = 1e-6 * arrayOfPoints[i + 1];
235 		p.z = 1e-6 * arrayOfPoints[i + 2];
236 		p.nx = 1e-6 * arrayOfPoints[i + 3];
237 		p.ny = 1e-6 * arrayOfPoints[i + 4];
238 		p.nz = 1e-6 * arrayOfPoints[i + 5];
239 
240 		if (fabs(p.x) > maxp)
241 			maxp = fabs(p.x);
242 		if (fabs(p.y) > maxp)
243 			maxp = fabs(p.y);
244 		if (fabs(p.z) > maxp)
245 			maxp = fabs(p.z);
246 
247 		fPoints.add(p);
248 	}
249 
250 	for (int i = 0; i < fPoints.num_items; i++) {
251 		fPoints[i].x /= maxp;
252 		fPoints[i].y /= maxp;
253 		fPoints[i].z /= maxp;
254 	}
255 
256 	int32 *arrayOfTriangles
257 					= (int32*)res->LoadResource(B_RAW_TYPE, "triangles", &size);
258 	if (arrayOfTriangles == NULL)
259 		return;
260 
261 	size_t numTriPoints = size / sizeof(int32);
262 	for (size_t i = 0; i < numTriPoints; i += 3) {
263 		tri t;
264 		t.p1 = arrayOfTriangles[i];
265 		t.p2 = arrayOfTriangles[i + 1];
266 		t.p3 = arrayOfTriangles[i + 2];
267 		fTriangles.add(t);
268 	}
269 
270 	size_t numTri = numTriPoints / 3;
271 
272 	int qpts = 4;
273 	int qp[1024];
274 	quadStrip q;
275 	q.pts = qp;
276 	q.numpts = 4;
277 	q.pts[2] = fTriangles[0].p1;
278 	q.pts[0] = fTriangles[0].p2;
279 	q.pts[1] = fTriangles[0].p3;
280 	q.pts[3] = fTriangles[1].p3;
281 
282 	for (size_t i = 2; i < numTri; i += 2) {
283 		if ((fTriangles[i - 1].p1 == fTriangles[i].p2) &&
284 			(fTriangles[i - 1].p3 == fTriangles[i].p3)) {
285 			q.pts[q.numpts++] = fTriangles[i + 1].p1;
286 			q.pts[q.numpts++] = fTriangles[i + 1].p3;
287 			qpts+=2;
288 		} else {
289 			int *np = (int*)malloc(sizeof(int)*q.numpts);
290 			memcpy(np, qp, q.numpts * sizeof(int));
291 			quadStrip nqs;
292 			nqs.numpts = q.numpts;
293 			nqs.pts = np;
294 			fQs.add(nqs);
295 
296 			qpts += 4;
297 			q.numpts = 4;
298 			q.pts[2] = fTriangles[i].p1;
299 			q.pts[0] = fTriangles[i].p2;
300 			q.pts[1] = fTriangles[i].p3;
301 			q.pts[3] = fTriangles[i + 1].p3;
302 		}
303 	}
304 
305 	int* np = (int*)malloc(sizeof(int)*q.numpts);
306 	memcpy(np, qp, q.numpts * sizeof(int));
307 	quadStrip nqs;
308 	nqs.numpts = q.numpts;
309 	nqs.pts = np;
310 	fQs.add(nqs);
311 
312 	fStatus = B_OK;
313 }
314 
315 
316 TriangleObject::~TriangleObject()
317 {
318 	for (int i = 0; i < fQs.num_items; i++) {
319 		free(fQs[i].pts);
320 	}
321 }
322 
323 
324 status_t
325 TriangleObject::InitCheck() const
326 {
327 	return fStatus;
328 }
329 
330 
331 void
332 TriangleObject::DoDrawing(bool forID)
333 {
334 	if (!forID) {
335 		float c[3][4];
336 		c[0][0] = materials[color].ambient[0];
337 		c[0][1] = materials[color].ambient[1];
338 		c[0][2] = materials[color].ambient[2];
339 		c[1][0] = materials[color].diffuse[0];
340 		c[1][1] = materials[color].diffuse[1];
341 		c[1][2] = materials[color].diffuse[2];
342 		c[2][0] = materials[color].specular[0];
343 		c[2][1] = materials[color].specular[1];
344 		c[2][2] = materials[color].specular[2];
345 
346 		float alpha = 1;
347 		if (solidity == 0)
348 			alpha = 1.0;
349 		else if (solidity == 1)
350 			alpha = 0.95;
351 		else if (solidity == 2)
352 			alpha = 0.6;
353 		c[0][3] = c[1][3] = c[2][3] = alpha;
354 		if (solidity != 0) {
355 			glBlendFunc(GL_SRC_ALPHA,GL_ONE);
356 			glEnable(GL_BLEND);
357 			glDepthMask(GL_FALSE);
358 			glDisable(GL_CULL_FACE);
359 		} else {
360 			glDisable(GL_BLEND);
361 			glDepthMask(GL_TRUE);
362 		}
363 		glMaterialfv(GL_FRONT, GL_AMBIENT, c[0]);
364 		glMaterialfv(GL_FRONT, GL_DIFFUSE, c[1]);
365 		glMaterialfv(GL_FRONT, GL_SPECULAR, c[2]);
366 	} else {
367 		glDisable(GL_BLEND);
368 		glDepthMask(GL_TRUE);
369 	}
370 
371 #if USE_QUAD_STRIPS
372 		for (int i = 0; i < fQs.num_items; i++) {
373  			glBegin(GL_QUAD_STRIP);
374 			for (int j = 0; j < fQs[i].numpts; j++) {
375  				glNormal3f(
376 					fPoints[fQs[i].pts[j]].nx,
377 					fPoints[fQs[i].pts[j]].ny,
378 					fPoints[fQs[i].pts[j]].nz
379 				);
380  				glVertex3f(
381 					fPoints[fQs[i].pts[j]].x,
382 					fPoints[fQs[i].pts[j]].y,
383 					fPoints[fQs[i].pts[j]].z
384 				);
385 			}
386 			glEnd();
387 		}
388 #else
389  		glBegin(GL_TRIANGLES);
390 		for (int i = 0; i < fTriangles.num_items; i++) {
391 			int v3 = fTriangles[i].p1;
392 			int v1 = fTriangles[i].p2;
393 			int v2 = fTriangles[i].p3;
394  	  		glNormal3f(
395 				fPoints[v1].nx,
396 				fPoints[v1].ny,
397 				fPoints[v1].nz
398 			);
399  			glVertex3f(
400 				fPoints[v1].x,
401 				fPoints[v1].y,
402 				fPoints[v1].z
403 			);
404  			glNormal3f(
405 				fPoints[v2].nx,
406 				fPoints[v2].ny,
407 				fPoints[v2].nz
408 			);
409  			glVertex3f(
410 				fPoints[v2].x,
411 				fPoints[v2].y,
412 				fPoints[v2].z
413 			);
414  			glNormal3f(
415 				fPoints[v3].nx,
416 				fPoints[v3].ny,
417 				fPoints[v3].nz
418 			);
419 			glVertex3f(
420 				fPoints[v3].x,
421 				fPoints[v3].y,
422 				fPoints[v3].z
423 			);
424 		}
425 		glEnd();
426  #endif
427 }
428 
429