xref: /haiku/src/apps/glteapot/GLObject.cpp (revision 220d04022750f40f8bac8f01fa551211e28d04f2)
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 	changed = true;
185 }
186 
187 
188 void
189 GLObject::Draw(bool forID, float IDcolor[])
190 {
191 	glPushMatrix();
192 		glTranslatef(x, y, z);
193 
194 		float mat[4][4];
195 		fRotation.toOpenGLMatrix(mat);
196 		glMultMatrixf((GLfloat*)mat);
197 
198 		if (forID) {
199 			glColor3fv(IDcolor);
200 		}
201 
202 		DoDrawing(forID);
203 
204 	glPopMatrix();
205 
206 	changed = false;
207 }
208 
209 
210 TriangleObject::TriangleObject(ObjectView* ov)
211 		:
212 		GLObject(ov),
213 		fStatus(B_NO_INIT),
214 		fPoints(100, 100),
215 		fTriangles(100, 100),
216 		fQs(50, 50)
217 {
218 	BResources *res = BApplication::AppResources();
219 	if (res == NULL)
220 		return;
221 
222 	size_t size = 0;
223 	int32 *arrayOfPoints
224 					= (int32*)res->LoadResource(B_RAW_TYPE, "points", &size);
225 	if (arrayOfPoints == NULL)
226 		return;
227 
228 	float maxp = 0;
229 	size_t numPt = size / sizeof(int32);
230 	for (size_t i = 0; i < numPt; i += 6) {
231 		point p;
232 		p.x = 1e-6 * arrayOfPoints[i];
233 		p.y = 1e-6 * arrayOfPoints[i + 1];
234 		p.z = 1e-6 * arrayOfPoints[i + 2];
235 		p.nx = 1e-6 * arrayOfPoints[i + 3];
236 		p.ny = 1e-6 * arrayOfPoints[i + 4];
237 		p.nz = 1e-6 * arrayOfPoints[i + 5];
238 
239 		if (fabs(p.x) > maxp)
240 			maxp = fabs(p.x);
241 		if (fabs(p.y) > maxp)
242 			maxp = fabs(p.y);
243 		if (fabs(p.z) > maxp)
244 			maxp = fabs(p.z);
245 
246 		fPoints.add(p);
247 	}
248 
249 	for (int i = 0; i < fPoints.num_items; i++) {
250 		fPoints[i].x /= maxp;
251 		fPoints[i].y /= maxp;
252 		fPoints[i].z /= maxp;
253 	}
254 
255 	int32 *arrayOfTriangles
256 					= (int32*)res->LoadResource(B_RAW_TYPE, "triangles", &size);
257 	if (arrayOfTriangles == NULL)
258 		return;
259 
260 	size_t numTriPoints = size / sizeof(int32);
261 	for (size_t i = 0; i < numTriPoints; i += 3) {
262 		tri t;
263 		t.p1 = arrayOfTriangles[i];
264 		t.p2 = arrayOfTriangles[i + 1];
265 		t.p3 = arrayOfTriangles[i + 2];
266 		fTriangles.add(t);
267 	}
268 
269 	size_t numTri = numTriPoints / 3;
270 
271 	int qpts = 4;
272 	int qp[1024];
273 	quadStrip q;
274 	q.pts = qp;
275 	q.numpts = 4;
276 	q.pts[2] = fTriangles[0].p1;
277 	q.pts[0] = fTriangles[0].p2;
278 	q.pts[1] = fTriangles[0].p3;
279 	q.pts[3] = fTriangles[1].p3;
280 
281 	for (size_t i = 2; i < numTri; i += 2) {
282 		if ((fTriangles[i - 1].p1 == fTriangles[i].p2) &&
283 			(fTriangles[i - 1].p3 == fTriangles[i].p3)) {
284 			q.pts[q.numpts++] = fTriangles[i + 1].p1;
285 			q.pts[q.numpts++] = fTriangles[i + 1].p3;
286 			qpts+=2;
287 		} else {
288 			int *np = (int*)malloc(sizeof(int)*q.numpts);
289 			memcpy(np, qp, q.numpts * sizeof(int));
290 			quadStrip nqs;
291 			nqs.numpts = q.numpts;
292 			nqs.pts = np;
293 			fQs.add(nqs);
294 
295 			qpts += 4;
296 			q.numpts = 4;
297 			q.pts[2] = fTriangles[i].p1;
298 			q.pts[0] = fTriangles[i].p2;
299 			q.pts[1] = fTriangles[i].p3;
300 			q.pts[3] = fTriangles[i + 1].p3;
301 		}
302 	}
303 
304 	int* np = (int*)malloc(sizeof(int)*q.numpts);
305 	memcpy(np, qp, q.numpts * sizeof(int));
306 	quadStrip nqs;
307 	nqs.numpts = q.numpts;
308 	nqs.pts = np;
309 	fQs.add(nqs);
310 
311 	fStatus = B_OK;
312 }
313 
314 
315 TriangleObject::~TriangleObject()
316 {
317 	for (int i = 0; i < fQs.num_items; i++) {
318 		free(fQs[i].pts);
319 	}
320 }
321 
322 
323 status_t
324 TriangleObject::InitCheck() const
325 {
326 	return fStatus;
327 }
328 
329 
330 void
331 TriangleObject::DoDrawing(bool forID)
332 {
333 	if (!forID) {
334 		float c[3][4];
335 		c[0][0] = materials[color].ambient[0];
336 		c[0][1] = materials[color].ambient[1];
337 		c[0][2] = materials[color].ambient[2];
338 		c[1][0] = materials[color].diffuse[0];
339 		c[1][1] = materials[color].diffuse[1];
340 		c[1][2] = materials[color].diffuse[2];
341 		c[2][0] = materials[color].specular[0];
342 		c[2][1] = materials[color].specular[1];
343 		c[2][2] = materials[color].specular[2];
344 
345 		float alpha = 1;
346 		if (solidity == 0)
347 			alpha = 1.0;
348 		else if (solidity == 1)
349 			alpha = 0.95;
350 		else if (solidity == 2)
351 			alpha = 0.6;
352 		c[0][3] = c[1][3] = c[2][3] = alpha;
353 		if (solidity != 0) {
354 			glBlendFunc(GL_SRC_ALPHA,GL_ONE);
355 			glEnable(GL_BLEND);
356 			glDepthMask(GL_FALSE);
357 			glDisable(GL_CULL_FACE);
358 		} else {
359 			glDisable(GL_BLEND);
360 			glDepthMask(GL_TRUE);
361 		}
362 		glMaterialfv(GL_FRONT, GL_AMBIENT, c[0]);
363 		glMaterialfv(GL_FRONT, GL_DIFFUSE, c[1]);
364 		glMaterialfv(GL_FRONT, GL_SPECULAR, c[2]);
365 	} else {
366 		glDisable(GL_BLEND);
367 		glDepthMask(GL_TRUE);
368 	}
369 
370 #if USE_QUAD_STRIPS
371 		for (int i = 0; i < fQs.num_items; i++) {
372  			glBegin(GL_QUAD_STRIP);
373 			for (int j = 0; j < fQs[i].numpts; j++) {
374  				glNormal3f(
375 					fPoints[fQs[i].pts[j]].nx,
376 					fPoints[fQs[i].pts[j]].ny,
377 					fPoints[fQs[i].pts[j]].nz
378 				);
379  				glVertex3f(
380 					fPoints[fQs[i].pts[j]].x,
381 					fPoints[fQs[i].pts[j]].y,
382 					fPoints[fQs[i].pts[j]].z
383 				);
384 			}
385 			glEnd();
386 		}
387 #else
388  		glBegin(GL_TRIANGLES);
389 		for (int i = 0; i < fTriangles.num_items; i++) {
390 			int v3 = fTriangles[i].p1;
391 			int v1 = fTriangles[i].p2;
392 			int v2 = fTriangles[i].p3;
393  	  		glNormal3f(
394 				fPoints[v1].nx,
395 				fPoints[v1].ny,
396 				fPoints[v1].nz
397 			);
398  			glVertex3f(
399 				fPoints[v1].x,
400 				fPoints[v1].y,
401 				fPoints[v1].z
402 			);
403  			glNormal3f(
404 				fPoints[v2].nx,
405 				fPoints[v2].ny,
406 				fPoints[v2].nz
407 			);
408  			glVertex3f(
409 				fPoints[v2].x,
410 				fPoints[v2].y,
411 				fPoints[v2].z
412 			);
413  			glNormal3f(
414 				fPoints[v3].nx,
415 				fPoints[v3].ny,
416 				fPoints[v3].nz
417 			);
418 			glVertex3f(
419 				fPoints[v3].x,
420 				fPoints[v3].y,
421 				fPoints[v3].z
422 			);
423 		}
424 		glEnd();
425  #endif
426 }
427 
428