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