Line data Source code
1 : #include <fstream>
2 :
3 : #include "ModelGameObject.h"
4 : #include "constants.h"
5 : #include "Terrain.h"
6 : #include "api.h"
7 :
8 1 : std::map <std::string, ModelStorage*> ModelGameObject::modelHash;
9 :
10 : //------------------------------------------------------------------------------
11 18 : ModelGameObject::ModelGameObject() : Object() {
12 9 : updatedVertex = NULL;
13 9 : lightIntensity = NULL;
14 9 : modelKey_ = "";
15 18 : }
16 :
17 : //------------------------------------------------------------------------------
18 27 : ModelGameObject::~ModelGameObject() {
19 9 : unload();
20 27 : }
21 :
22 : //------------------------------------------------------------------------------
23 0 : void ModelGameObject::load(std::string modelKey) {
24 : // don't load the model if it's already loaded
25 0 : if (modelKey_ == modelKey) {
26 0 : int numVertices = modelHash[modelKey_]->numVertices;
27 :
28 : // load in vertices used for model //////
29 0 : for (int i = 0; i < numVertices; ++i) {
30 0 : for (int j = 0; j < 3; ++j) {
31 0 : updatedVertex[i][j] = modelHash[modelKey_]->baseVertex[i][j];
32 0 : }
33 0 : }
34 0 : return;
35 : }
36 :
37 : // model must have been unloaded first
38 0 : if (lightIntensity || updatedVertex)
39 0 : unload();
40 :
41 0 : modelKey_ = modelKey;
42 :
43 0 : int numVertices = modelHash[modelKey]->numVertices;
44 :
45 0 : updatedVertex = new GLfloat*[numVertices];
46 0 : lightIntensity = new GLfloat[numVertices];
47 :
48 0 : int r = 0;
49 :
50 0 : updatedVertex[r] = new GLfloat[3];
51 :
52 0 : while (updatedVertex[r] && r < numVertices - 1) {
53 0 : updatedVertex[++r] = new GLfloat[3];
54 : }
55 :
56 : // load in vertices used for model //////
57 0 : for (int i = 0; i < numVertices; ++i) {
58 0 : for (int j = 0; j < 3; ++j) {
59 0 : updatedVertex[i][j] = modelHash[modelKey]->baseVertex[i][j];
60 0 : }
61 0 : }
62 : /////////////////////////////////////////
63 :
64 : // TODO: This call was used for shadows; address when shadows are addressed
65 : //buildEdges();
66 0 : }
67 :
68 : //------------------------------------------------------------------------------
69 9 : void ModelGameObject::unload() {
70 : // delete old transforemed data /////////////
71 9 : if (updatedVertex) {
72 0 : for (int r = 0; r < modelHash[modelKey_]->numVertices; ++r) {
73 0 : delete[] updatedVertex[r];
74 0 : }
75 :
76 0 : delete[] updatedVertex;
77 0 : }
78 :
79 9 : if (lightIntensity)
80 0 : delete[] lightIntensity;
81 :
82 9 : lightIntensity = NULL;
83 9 : updatedVertex = NULL;
84 :
85 9 : modelKey_ = "";
86 9 : }
87 :
88 : //------------------------------------------------------------------------------
89 0 : void ModelGameObject::draw(Object* c) {
90 : // model must be loaded
91 0 : if (!lightIntensity || !updatedVertex)
92 0 : return;
93 :
94 0 : glPushMatrix();
95 0 : glTranslatef(position_.x, position_.y, position_.z);
96 :
97 0 : ModelStorage *m = modelHash[modelKey_];
98 0 : glBegin(GL_TRIANGLES);
99 0 : for (int i = 0; i < m->numTriangles; ++i) {
100 0 : for (int j = 0; j < 3; ++j) {
101 0 : glColor3fv(m->triangle[i].colors[j]);
102 0 : glTexCoord1f(lightIntensity[m->triangle[i].vertices[j]]);
103 0 : glVertex3fv(updatedVertex[m->triangle[i].vertices[j]]);
104 0 : }
105 0 : }
106 0 : glEnd();
107 :
108 0 : glPopMatrix();
109 :
110 0 : if (particleSystem_ != NULL)
111 0 : particleSystem_->draw();
112 0 : }
113 :
114 : //------------------------------------------------------------------------------
115 0 : void ModelGameObject::drawOutline(Object* c) {
116 : // model must first be loaded
117 0 : if (!lightIntensity || !updatedVertex)
118 0 : return;
119 :
120 0 : ModelStorage *m = modelHash[modelKey_];
121 :
122 0 : glPushMatrix();
123 0 : glTranslatef(position_.x, position_.y, position_.z);
124 :
125 0 : glColor3f(0.0f, 0.0f, 0.0f);
126 :
127 0 : glBegin(GL_TRIANGLES);
128 0 : for (int i = 0; i < m->numTriangles; ++i) {
129 0 : for (int j = 0; j < 3; ++j) {
130 0 : glVertex3fv(updatedVertex[m->triangle[i].vertices[j]]);
131 0 : }
132 0 : }
133 0 : glEnd();
134 0 : glPopMatrix();
135 0 : }
136 :
137 : //------------------------------------------------------------------------------
138 0 : void ModelGameObject::drawShadow (Vector* light) {
139 0 : Vector v1, v2;
140 :
141 0 : for (int i = 0; i < numSEdge; ++i) {
142 : //calculate the length of the vector
143 0 : v1.x = (sEdge[i].p1.x - light->x)*100;
144 0 : v1.y = (sEdge[i].p1.y - light->y)*100;
145 0 : v1.z = (sEdge[i].p1.z - light->z)*100;
146 :
147 0 : v2.x = (sEdge[i].p2.x - light->x)*100;
148 0 : v2.y = (sEdge[i].p2.y - light->y)*100;
149 0 : v2.z = (sEdge[i].p2.z - light->z)*100;
150 :
151 : //draw the polygon
152 : /*
153 : glBegin(GL_LINES);
154 : glVertex3f(sEdge[i].p1.x, sEdge[i].p1.y, sEdge[i].p1.z);
155 : glVertex3f(sEdge[i].p2.x, sEdge[i].p2.y, sEdge[i].p2.z);
156 : glEnd();
157 : */
158 :
159 0 : glBegin(GL_TRIANGLE_STRIP);
160 0 : glVertex3f(sEdge[i].p1.x, sEdge[i].p1.y, sEdge[i].p1.z);
161 0 : glVertex3f(sEdge[i].p1.x + v1.x,
162 0 : sEdge[i].p1.y + v1.y,
163 0 : sEdge[i].p1.z + v1.z);
164 :
165 0 : glVertex3f(sEdge[i].p2.x,
166 0 : sEdge[i].p2.y,
167 0 : sEdge[i].p2.z);
168 0 : glVertex3f(sEdge[i].p2.x + v2.x,
169 0 : sEdge[i].p2.y + v2.y,
170 0 : sEdge[i].p2.z + v2.z);
171 0 : glEnd();
172 0 : }
173 0 : }
174 :
175 : //------------------------------------------------------------------------------
176 0 : void ModelGameObject::handleCollision(Object* temp) {
177 : // Attempt to execute the script only if the lua state has already been
178 : // initialized with a script
179 0 : if (!L_)
180 0 : return;
181 :
182 : // Find the update function and call it
183 0 : lua_getglobal(L_, SCRIPT_CALLBACK_ON_COLLISION);
184 :
185 0 : if (lua_isfunction(L_, -1)) {
186 : // Push a pointer to the current object for use within the lua function
187 0 : returnObject(L_, this);
188 0 : returnObject(L_, temp);
189 :
190 0 : lua_call(L_, 2, 0);
191 0 : }
192 : else {
193 : PRINT_DEBUG_LVL(4, "'%s' function not defined.\n", SCRIPT_CALLBACK_ON_COLLISION);
194 0 : lua_pop(L_, 1);
195 : }
196 0 : }
197 :
198 : //------------------------------------------------------------------------------
199 0 : void ModelGameObject::update(Vector* light) {
200 : // model must first be loaded
201 0 : if (!lightIntensity || !updatedVertex)
202 0 : return;
203 :
204 0 : if (!scaleChanged_ && !rotationChanged_ &&
205 0 : lastLight_.x == light->x &&
206 0 : lastLight_.y == light->y &&
207 0 : lastLight_.z == light->z) {
208 0 : boundingSphere_.setOriginVector(position_);
209 0 : return;
210 : }
211 :
212 0 : lastLight_.x = light->x;
213 0 : lastLight_.y = light->y;
214 0 : lastLight_.z = light->z;
215 0 : scaleChanged_ = false;
216 0 : rotationChanged_ = false;
217 :
218 0 : Vector tempV;
219 : GLfloat temp;
220 0 : Matrix rotationMatrix;
221 0 : Matrix scaleMatrix;
222 0 : Matrix transform;
223 :
224 0 : GLfloat min[] = {9999.0f, 9999.0f, 9999.0f};
225 0 : GLfloat max[] = {-9999.0f, -9999.0f, -9999.0f};
226 :
227 : // setup transformation matrices ////////////
228 0 : rotation_.buildRotationMatrix(rotationMatrix);
229 0 : scaleMatrix.setScale(scale_.x, scale_.y, scale_.z);
230 :
231 : // setup the transformation matrix //////////
232 0 : transform = rotationMatrix * scaleMatrix;
233 : /////////////////////////////////////////////
234 :
235 0 : ModelStorage *m = modelHash[modelKey_];
236 :
237 0 : float radius = 0.0f;
238 :
239 0 : for (int i = 0; i < m->numVertices; ++i) {
240 : // transform vertex /////////////////////
241 0 : transform.transformVertex(m->baseVertex[i], updatedVertex[i]);
242 :
243 : // calculate light intensity ////////////
244 0 : if (isAlwaysLit_) {
245 0 : temp = 0.5f;
246 0 : }
247 : else {
248 0 : tempV.rotateVector(transform, m->normal[i]);
249 0 : tempV.normalize();
250 :
251 0 : temp = tempV.dotProduct(*light);
252 :
253 0 : if (temp == 1.0f)
254 0 : temp = 0.5f;
255 0 : else if (temp < 0.0f)
256 0 : temp = 0.0f;
257 : }
258 :
259 0 : lightIntensity[i] = temp;
260 : /////////////////////////////////////////
261 :
262 : // re-calculate collision box ///////////
263 0 : for (int j = 0; j < 3; ++j) {
264 0 : if (updatedVertex[i][j] > max[j])
265 0 : max[j] = updatedVertex[i][j];
266 :
267 0 : if (updatedVertex[i][j] < min[j])
268 0 : min[j] = updatedVertex[i][j];
269 0 : }
270 : /////////////////////////////////////////
271 :
272 0 : float x = (updatedVertex[i][0]);
273 0 : float y = (updatedVertex[i][1]);
274 0 : float z = (updatedVertex[i][2]);
275 :
276 0 : float distance = (x * x) + (y * y) + (z * z);
277 :
278 0 : if (distance > radius)
279 0 : radius = distance;
280 0 : }
281 :
282 0 : collisionBox_[0].setVector(min[0], min[1], min[2]);
283 0 : collisionBox_[1].setVector(max[0], max[1], max[2]);
284 :
285 0 : radius = sqrt(radius);
286 0 : boundingSphere_.setSphere(position_.x, position_.y, position_.z, radius);
287 :
288 0 : controlPoints_[0].setVector(max[0], min[1], min[2]);
289 0 : controlPoints_[1].setVector(max[0], min[1], max[2]);
290 0 : controlPoints_[2].setVector(min[0], min[1], (min[2] + max[2]) / 2);
291 :
292 0 : direction_.rotateVector(rotationMatrix, baseDirection_);
293 0 : direction_.normalize();
294 :
295 0 : Vector upV;
296 0 : upV.setVector(0.0f, 1.0f, 0.0f);
297 :
298 0 : up_.rotateVector(rotationMatrix, upV);
299 0 : up_.normalize();
300 :
301 0 : orth_.crossProduct(up_, direction_);
302 0 : orth_.normalize();
303 :
304 : // TODO: This code is likely from shadows; address with shadows
305 : /*
306 : Vector p1, p2, p3;
307 : Vector tempN;
308 : Vector lp;
309 : float tempD[2];
310 :
311 : numSEdge = 0;
312 :
313 : for (int i = 0; i < numEdges; i++) {
314 : for (int u = 0; u < 2; u++) {
315 :
316 : p1.setVector(updatedVertex[triangle[edges[i].triangleIndex[u]].vertices[0]][0],
317 : updatedVertex[triangle[edges[i].triangleIndex[u]].vertices[0]][1],
318 : updatedVertex[triangle[edges[i].triangleIndex[u]].vertices[0]][2]
319 : );
320 :
321 : p2.setVector(updatedVertex[triangle[edges[i].triangleIndex[u]].vertices[1]][0],
322 : updatedVertex[triangle[edges[i].triangleIndex[u]].vertices[1]][1],
323 : updatedVertex[triangle[edges[i].triangleIndex[u]].vertices[1]][2]
324 : );
325 :
326 : p3.setVector(updatedVertex[triangle[edges[i].triangleIndex[u]].vertices[2]][0],
327 : updatedVertex[triangle[edges[i].triangleIndex[u]].vertices[2]][1],
328 : updatedVertex[triangle[edges[i].triangleIndex[u]].vertices[2]][2]
329 : );
330 :
331 : tempV.rotateVector(transform, tempN);
332 : tempV.normalize();
333 :
334 : tempD[u] = tempV.dotProduct(*light);
335 : }
336 :
337 : if (tempD[0] >= 0 && tempD[1] <= 0 || tempD[0] <= 0 && tempD[1] >= 0) {
338 : p1.setVector(updatedVertex[edges[i].vertices[0]][0],
339 : updatedVertex[edges[i].vertices[0]][1],
340 : updatedVertex[edges[i].vertices[0]][2]
341 : );
342 : p2.setVector(updatedVertex[edges[i].vertices[1]][0],
343 : updatedVertex[edges[i].vertices[1]][1],
344 : updatedVertex[edges[i].vertices[1]][2]
345 : );
346 :
347 : tempV.transformVector(transform, p1);
348 : sEdge[numSEdge].p1 = tempV;
349 :
350 : tempV.transformVector(transform, p2);
351 : sEdge[numSEdge].p2 = tempV;
352 :
353 : numSEdge++;
354 : }
355 : }
356 : */
357 0 : }
358 :
359 : //------------------------------------------------------------------------------
360 0 : void ModelGameObject::animate(const float &timeElapsed, Object* c) {
361 : // determine whether or not the current object is in the camera's view
362 0 : int r = dynamic_cast<Camera*>(c)->frustum.testSphere(boundingSphere_);
363 0 : isInView_ = (r != -1);
364 :
365 0 : Object::animate(timeElapsed, c);
366 :
367 : // The particle systems might not always live here...
368 0 : if (particleSystem_ != NULL)
369 0 : particleSystem_->update(timeElapsed);
370 0 : }
371 :
372 : //------------------------------------------------------------------------------
373 0 : void ModelStorage::load(char fileName[]) {
374 : GLfloat temp;
375 :
376 0 : std::ifstream fin(fileName);
377 0 : fin >> initalScale;
378 0 : fin >> numVertices;
379 0 : baseVertex = new GLfloat* [ numVertices ];
380 0 : normal = new Vector[ numVertices ];
381 :
382 0 : int r = 0;
383 0 : baseVertex[r] = new GLfloat[3];
384 :
385 0 : while (baseVertex[ r ] != NULL && r < numVertices-1) {
386 0 : baseVertex[++r] = new GLfloat[3];
387 : }
388 :
389 : // load in vertices used for model //////
390 0 : for (int i = 0; i < numVertices; ++i) {
391 0 : for (int j = 0; j < 3; ++j) {
392 0 : fin >> temp;
393 0 : baseVertex[i][j] = temp;
394 0 : }
395 :
396 0 : fin >> normal[i].x;
397 0 : fin >> normal[i].y;
398 0 : fin >> normal[i].z;
399 0 : }
400 : /////////////////////////////////////////
401 :
402 0 : fin >> numTriangles;
403 0 : triangle = new Triangle[ numTriangles ];
404 :
405 : // load in triangles used for model /////
406 0 : for (int i = 0; i < numTriangles; ++i) {
407 0 : for (int j = 0; j < 3; ++j)
408 0 : fin >> triangle[i].vertices[j];
409 :
410 0 : for (int j = 0; j < 3; ++j)
411 0 : for (int k = 0; k < 3; ++k)
412 0 : fin >> triangle[i].colors[j][k];
413 0 : }
414 : /////////////////////////////////////////
415 0 : fin.close();
416 0 : }
417 :
418 : //------------------------------------------------------------------------------
419 0 : void ModelGameObject::buildEdges()
420 : {
421 : // TODO: This code is from shadows; address at that time
422 : /*
423 : // Allocate enough space to hold all edges
424 : edges = new Edge[numTriangles * 3];
425 : sEdge = new TransformedEdge[numTriangles * 3 ];
426 :
427 : int edgeCount = 0,
428 : i1, i2, i3;
429 :
430 : // First pass: find edges
431 : for (int a = 0; a < numTriangles; a++) {
432 : i1 = triangle[a].vertices[0];
433 : i2 = triangle[a].vertices[1];
434 : i3 = triangle[a].vertices[2];
435 :
436 : if (i1 < i2) {
437 : edges[edgeCount].vertices[0] = i1;
438 : edges[edgeCount].vertices[1] = i2;
439 : edges[edgeCount].triangleIndex[0] = a;
440 : edges[edgeCount].triangleIndex[1] = -1;
441 : edgeCount++;
442 : }
443 :
444 : if (i2 < i3) {
445 : edges[edgeCount].vertices[0] = i2;
446 : edges[edgeCount].vertices[1] = i3;
447 : edges[edgeCount].triangleIndex[0] = a;
448 : edges[edgeCount].triangleIndex[1] = -1;
449 : edgeCount++;
450 : }
451 :
452 : if (i3 < i1) {
453 : edges[edgeCount].vertices[0] = i3;
454 : edges[edgeCount].vertices[1] = i1;
455 : edges[edgeCount].triangleIndex[0] = a;
456 : edges[edgeCount].triangleIndex[1] = -1;
457 : edgeCount++;
458 : }
459 : }
460 :
461 : // Second pass: match triangles to edges
462 : for (int a = 0; a < numTriangles; a++) {
463 : i1 = triangle[a].vertices[0];
464 : i2 = triangle[a].vertices[1];
465 : i3 = triangle[a].vertices[2];
466 :
467 : if (i1 > i2) {
468 : for (int b = 0; b < edgeCount; b++) {
469 : if ((edges[b].vertices[0] == i2) &&
470 : (edges[b].vertices[1] == i1) &&
471 : (edges[b].triangleIndex[1] == -1)) {
472 : edges[b].triangleIndex[1] = a;
473 : break;
474 : }
475 : }
476 : }
477 :
478 : if (i2 > i3) {
479 : for (int b = 0; b < edgeCount; b++) {
480 : if ((edges[b].vertices[0] == i3) &&
481 : (edges[b].vertices[1] == i2) &&
482 : (edges[b].triangleIndex[1] == -1)) {
483 : edges[b].triangleIndex[1] = a;
484 : break;
485 : }
486 : }
487 : }
488 :
489 : if (i3 > i1) {
490 : for (int b = 0; b < edgeCount; b++) {
491 : if ((edges[b].vertices[0] == i1) &&
492 : (edges[b].vertices[1] == i3) &&
493 : (edges[b].triangleIndex[1] == -1)) {
494 : edges[b].triangleIndex[1] = a;
495 : break;
496 : }
497 : }
498 : }
499 : }
500 :
501 : numEdges = edgeCount;
502 : */
503 0 : }
504 :
505 : //------------------------------------------------------------------------------
506 0 : void ModelGameObject::orientOnTerrain(Terrain *temp, const Quaternion &baseRotation) {
507 0 : if (temp == NULL)
508 0 : return;
509 :
510 0 : Vector p1, p2, p3;
511 :
512 0 : p1.setVector(controlPoints_[0].x + position_.x, 0.0f, controlPoints_[0].z + position_.z);
513 0 : p2.setVector(controlPoints_[1].x + position_.x, 0.0f, controlPoints_[1].z + position_.z);
514 0 : p3.setVector(controlPoints_[2].x + position_.x, 0.0f, controlPoints_[2].z + position_.z);
515 :
516 0 : p1.y = temp->getHeight(p1.x, p1.z);
517 0 : p2.y = temp->getHeight(p2.x, p2.z);
518 0 : p3.y = temp->getHeight(p3.x, p3.z);
519 :
520 : PRINT_DEBUG_LVL(5, "p1.x=%f, p1.y=%f, p1.z=%f, p2.y=%f, p3.y=%f\n", p1.x, p1.y, p1.z, p2.y, p3.y);
521 :
522 0 : float height = calcTriangleCenter(p1.y, p2.y, p3.y);
523 :
524 : PRINT_DEBUG_LVL(5, "height =%f\n", height);
525 :
526 : //float position_height = ((Terrain*)temp)->getHeight(position_.x, position_.z);
527 :
528 : //if (position_.y < ((Terrain*)temp)->getHeight(position_.x, position_.z)) {
529 0 : Vector normal, up;
530 0 : normal.calcNorm(p1, p2, p3);
531 :
532 : PRINT_DEBUG_LVL(5, "normal x=%f, normal y=%f, normal z=%f\n", normal.x, normal.y, normal.z);
533 :
534 0 : up.setVector(0.0f, 1.0f, 0.0f);
535 0 : Vector rotationAxis; rotationAxis.crossProduct(up, normal);
536 0 : float rotationAngle = normal.dotProduct(up);
537 :
538 0 : Quaternion orientRotation; orientRotation.buildFromAxis(rotationAxis, rotationAngle);
539 0 : rotation_ = baseRotation * orientRotation;
540 :
541 : //setRotationAxis(rotationAxis,rotationAngle);
542 0 : position_.y = height;
543 0 : rotationChanged_ = true;
544 0 : }
545 :
546 : //------------------------------------------------------------------------------
547 0 : void ModelGameObject::setHeightFromTerrain(Terrain *temp, const float &offset) {
548 0 : if (temp == NULL)
549 0 : return;
550 :
551 0 : Vector p1, p2, p3;
552 :
553 0 : p1.setVector(controlPoints_[0].x + position_.x, 0.0f, controlPoints_[0].z + position_.z);
554 0 : p2.setVector(controlPoints_[1].x + position_.x, 0.0f, controlPoints_[1].z + position_.z);
555 0 : p3.setVector(controlPoints_[2].x + position_.x, 0.0f, controlPoints_[2].z + position_.z);
556 :
557 0 : p1.y = temp->getHeight(p1.x, p1.z);
558 0 : p2.y = temp->getHeight(p2.x, p2.z);
559 0 : p3.y = temp->getHeight(p3.x, p3.z);
560 :
561 : PRINT_DEBUG_LVL(5, "p1.x=%f, p1.y=%f, p1.z=%f, p2.y=%f, p3.y=%f\n", p1.x, p1.y, p1.z, p2.y, p3.y);
562 :
563 0 : float height = calcTriangleCenter(p1.y, p2.y, p3.y);
564 :
565 : PRINT_DEBUG_LVL(5, "height =%f\n", height);
566 :
567 : //float position_height = ((Terrain*)temp)->getHeight(position_.x, position_.z);
568 :
569 0 : position_.y = height + offset;
570 0 : }
|