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
GLObject(ObjectView * ov)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
~GLObject()96 GLObject::~GLObject()
97 {
98 }
99
100
101 void
MenuInvoked(BPoint point)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
Solidity() const151 GLObject::Solidity() const
152 {
153 return solidity;
154 }
155
156
157
158 bool
SpinIt()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
Spin(float rx,float ry)172 GLObject::Spin(float rx, float ry)
173 {
174 spinX = rx;
175 spinY = ry;
176 }
177
178
179 void
RotateWorldSpace(float rx,float ry)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
Draw(bool forID,float IDcolor[])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
TriangleObject(ObjectView * ov)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
~TriangleObject()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
InitCheck() const325 TriangleObject::InitCheck() const
326 {
327 return fStatus;
328 }
329
330
331 void
DoDrawing(bool forID)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