Line data Source code
1 : //////////////////////////////////////////////////////////////////
2 : // Description : Functions for terrain generation and display. //
3 : //////////////////////////////////////////////////////////////////
4 : #include "Terrain.h"
5 :
6 : #include <cstdlib>
7 : #include <fstream>
8 :
9 : //------------------------------------------------------------------------------
10 18 : Terrain::Terrain() : Object() {
11 9 : vertex_ = NULL;
12 9 : lightIntensity_ = NULL;
13 9 : color_ = NULL;
14 9 : type_ = NULL;
15 9 : vertexNormal_ = NULL;
16 :
17 9 : init();
18 :
19 9 : typeId_ = 100;
20 18 : }
21 :
22 : //------------------------------------------------------------------------------
23 9 : void Terrain::init() {
24 9 : unload();
25 :
26 9 : xSize_ = 0;
27 9 : zSize_ = 0;
28 9 : scaleFactor_ = 1.0f;
29 :
30 9 : isCurveEnabled_ = true;
31 9 : curveDistance_ = 200.0f;
32 9 : curveRate_ = 0.05f;
33 :
34 9 : enableSphereTest_ = false;
35 9 : }
36 :
37 : //------------------------------------------------------------------------------
38 27 : Terrain::~Terrain() {
39 : // TODO: On linux there is an issue on unload
40 27 : }
41 :
42 : //------------------------------------------------------------------------------
43 0 : void Terrain::draw(Object* c) {
44 0 : if (!vertex_ || !lightIntensity_ || !color_ || !type_) {
45 0 : return;
46 : }
47 :
48 : int x1, x2;
49 : int z1, z2;
50 :
51 : float xStart, zStart;
52 : float xPer1, xPer2, zPer1, zPer2;
53 : float tPer;
54 : GLfloat v[3];
55 :
56 0 : xStart = zStart = 0;
57 :
58 0 : glPushMatrix();
59 0 : QuadTreeNode* n = displayList_->head;
60 :
61 0 : while (n != NULL) {
62 0 : glBegin(GL_TRIANGLE_STRIP);
63 0 : xStart = n->min[0] / scaleFactor_;
64 0 : zStart = n->min[1] / scaleFactor_;
65 :
66 0 : x1 = (int)xStart;
67 0 : x2 = ((int)xStart) + 1;
68 :
69 0 : z1 = (int)zStart;
70 0 : z2 = ((int)zStart) + 1;
71 :
72 0 : v[0] = vertex_[x1][z1][0];
73 0 : v[2] = vertex_[x1][z1][2];
74 :
75 0 : Vector cPosition = c->getPosition();
76 :
77 0 : xPer1 = (vertex_[x1][z1][0] - cPosition.x) * (vertex_[x1][z1][0] - cPosition.x);
78 0 : xPer2 = (vertex_[x2][z1][0] - cPosition.x) * (vertex_[x2][z1][0] - cPosition.x);
79 0 : zPer1 = (vertex_[x1][z1][2] - cPosition.z) * (vertex_[x1][z1][2] - cPosition.z);
80 0 : zPer2 = (vertex_[x1][z2][2] - cPosition.z) * (vertex_[x1][z2][2] - cPosition.z);
81 :
82 0 : tPer = sqrt(xPer1 + zPer1);
83 :
84 : //offset = 1000000;
85 :
86 0 : if (isCurveEnabled_ && tPer > curveDistance_) {
87 0 : tPer = tPer - curveDistance_;
88 0 : v[1] = -(curveRate_ * (tPer)) * (curveRate_ * (tPer)) + vertex_[x1][z1][1];
89 0 : }
90 : else
91 0 : v[1] = vertex_[x1][z1][1];
92 :
93 0 : glColor3fv(color_[x1][z1]);
94 0 : glTexCoord1f(lightIntensity_[x1][z1]);
95 0 : glVertex3fv(v);
96 :
97 0 : v[0] = vertex_[x2][z1][0];
98 0 : v[2] = vertex_[x2][z1][2];
99 :
100 0 : tPer = sqrt(xPer2 + zPer1);
101 :
102 0 : if (isCurveEnabled_ && tPer > curveDistance_) {
103 0 : tPer = tPer - curveDistance_;
104 0 : v[1] = -(curveRate_ * (tPer)) * (curveRate_ * (tPer)) + vertex_[x2][z1][1];
105 0 : }
106 : else
107 0 : v[1] = vertex_[x2][z1][1];
108 :
109 0 : glColor3fv(color_[x2][z1]);
110 0 : glTexCoord1f(lightIntensity_[x2][z1]);
111 0 : glVertex3fv(v);
112 :
113 0 : v[0] = vertex_[x1][z2][0];
114 0 : v[2] = vertex_[x1][z2][2];
115 :
116 0 : tPer = sqrt(xPer1 + zPer2);
117 :
118 0 : if (isCurveEnabled_ && tPer > curveDistance_) {
119 0 : tPer = tPer - curveDistance_;
120 0 : v[1] = -(curveRate_ * (tPer)) * (curveRate_ * (tPer)) + vertex_[x1][z2][1];
121 0 : }
122 : else
123 0 : v[1] = vertex_[x1][z2][1];
124 :
125 0 : glColor3fv(color_[x1][z2]);
126 0 : glTexCoord1f(lightIntensity_[x1][z2]);
127 0 : glVertex3fv(v);
128 :
129 0 : tPer = sqrt(xPer2 + zPer2);
130 :
131 0 : v[0] = vertex_[x2][z2][0];
132 0 : v[2] = vertex_[x2][z2][2];
133 :
134 0 : if (isCurveEnabled_ && tPer > curveDistance_) {
135 0 : tPer = tPer - curveDistance_;
136 0 : v[1] = -(curveRate_ * (tPer)) * (curveRate_ * (tPer) ) + vertex_[x2][z2][1];
137 0 : }
138 : else
139 0 : v[1] = vertex_[x2][z2][1];
140 :
141 0 : glColor3fv(color_[x2][z2]);
142 0 : glTexCoord1f(lightIntensity_[x2][z2]);
143 0 : glVertex3fv(v);
144 0 : glEnd();
145 :
146 0 : n = n->next;
147 : }
148 :
149 0 : glPopMatrix();
150 0 : }
151 :
152 : //------------------------------------------------------------------------------
153 0 : void Terrain::drawOutline(Object* c) {
154 0 : if (!vertex_ || !lightIntensity_ || !color_ || !type_) {
155 0 : return;
156 : }
157 :
158 : int x1, x2;
159 : int z1, z2;
160 :
161 : float xStart, zStart;
162 : float xPer1, xPer2, zPer1, zPer2 ;
163 : float tPer;
164 : GLfloat v[3];
165 :
166 0 : xStart = zStart = 0;
167 :
168 0 : glPushMatrix();
169 0 : QuadTreeNode* n = displayList_->head;
170 :
171 0 : glColor3f(0.0f, 0.0f, 0.0f);
172 :
173 0 : while (n) {
174 0 : glBegin(GL_TRIANGLES);
175 0 : xStart = n->min[0] / scaleFactor_;
176 0 : zStart = n->min[1] / scaleFactor_;
177 :
178 0 : x1 = (int)xStart;
179 0 : x2 = ((int)xStart) + 1;
180 :
181 0 : z1 = (int)zStart;
182 0 : z2 = ((int)zStart) +1;
183 :
184 0 : v[0] = vertex_[x1][z1][0];
185 0 : v[2] = vertex_[x1][z1][2];
186 :
187 0 : Vector cPosition = c->getPosition();
188 :
189 0 : xPer1 = (vertex_[x1][z1][0] - cPosition.x) * (vertex_[x1][z1][0] - cPosition.x);
190 0 : xPer2 = (vertex_[x2][z1][0] - cPosition.x) * (vertex_[x2][z1][0] - cPosition.x);
191 0 : zPer1 = (vertex_[x1][z1][2] - cPosition.z) * (vertex_[x1][z1][2] - cPosition.z);
192 0 : zPer2 = (vertex_[x1][z2][2] - cPosition.z) * (vertex_[x1][z2][2] - cPosition.z);
193 :
194 0 : tPer = sqrt(xPer1 + zPer1);
195 :
196 0 : if (isCurveEnabled_ && tPer > curveDistance_) {
197 0 : tPer = tPer - curveDistance_;
198 0 : v[1] = -(curveRate_ * (tPer)) * (curveRate_ * (tPer)) + vertex_[x1][z1][1];
199 0 : }
200 : else
201 0 : v[1] = vertex_[x1][z1][1];
202 :
203 0 : glVertex3fv( v );
204 :
205 0 : v[0] = vertex_[x2][z1][0];
206 0 : v[2] = vertex_[x2][z1][2];
207 :
208 0 : tPer = sqrt(xPer2 + zPer1);
209 :
210 0 : if (isCurveEnabled_ && tPer > curveDistance_) {
211 0 : tPer = tPer - curveDistance_;
212 0 : v[1] = -(curveRate_ * (tPer)) * (curveRate_ * (tPer)) + vertex_[x2][z1][1];
213 0 : }
214 : else
215 0 : v[1] = vertex_[x2][z1][1];
216 :
217 0 : glVertex3fv(v);
218 :
219 0 : v[0] = vertex_[x1][z2][0];
220 0 : v[2] = vertex_[x1][z2][2];
221 :
222 0 : tPer = sqrt(xPer1 + zPer2);
223 :
224 0 : if (isCurveEnabled_ && tPer > curveDistance_) {
225 0 : tPer = tPer - curveDistance_;
226 :
227 0 : v[1] = -(curveRate_ * (tPer)) * (curveRate_ * (tPer)) + vertex_[x1][z2][1];
228 0 : }
229 : else
230 0 : v[1] = vertex_[x1][z2][1];
231 :
232 0 : glVertex3fv(v);
233 :
234 0 : tPer = sqrt(xPer2 + zPer2);
235 :
236 0 : v[0] = vertex_[x2][z2][0];
237 0 : v[2] = vertex_[x2][z2][2];
238 :
239 0 : if (isCurveEnabled_ && tPer > curveDistance_) {
240 0 : tPer = tPer - curveDistance_;
241 0 : v[1] = -(curveRate_ * (tPer)) * (curveRate_ * (tPer)) + vertex_[x2][z2][1];
242 0 : }
243 : else
244 0 : v[1] = vertex_[x2][z2][1];
245 :
246 0 : glVertex3fv(v);
247 0 : glEnd();
248 :
249 0 : n = n->next;
250 : }
251 :
252 0 : glPopMatrix();
253 0 : }
254 :
255 : //------------------------------------------------------------------------------
256 0 : void Terrain::generate() {}
257 :
258 : //------------------------------------------------------------------------------
259 0 : void Terrain::calcViewableTerrainNorm() {
260 0 : if (!vertex_ || !lightIntensity_ || !color_ || !type_) {
261 0 : return;
262 : }
263 :
264 : int x1, x2;
265 : int z1, z2;
266 :
267 : float xStart, zStart;
268 :
269 0 : xStart = zStart = 0;
270 :
271 0 : Vector surfaceNormal;
272 0 : Vector temp1;
273 0 : Vector temp2;
274 : GLfloat tempLightIntensity;
275 :
276 0 : Vector temp[5];
277 :
278 0 : Matrix tempMatrix;
279 0 : tempMatrix.loadIdentity();
280 :
281 0 : QuadTreeNode* n = displayList_->head;
282 :
283 0 : while (n != NULL) {
284 0 : xStart = n->min[0] / scaleFactor_;
285 0 : zStart = n->min[1] / scaleFactor_;
286 :
287 0 : x1 = (int)xStart;
288 0 : x2 = ((int)xStart) + 1;
289 :
290 0 : z1 = (int)zStart;
291 0 : z2 = ((int)zStart) + 1;
292 :
293 : PRINT_DEBUG_LVL(5, "x1=%d, z1=%d, x2=%d, z2=%d\n", x1, z1, x2, z2);
294 :
295 0 : vertexNormal_[x1][z1].x = 0.0f;
296 0 : vertexNormal_[x1][z1].y = 0.0f;
297 0 : vertexNormal_[x1][z1].z = 0.0f;
298 :
299 0 : vertexNormal_[x1+1][z1].x = 0.0f;
300 0 : vertexNormal_[x1+1][z1].y = 0.0f;
301 0 : vertexNormal_[x1+1][z1].z = 0.0f;
302 :
303 0 : vertexNormal_[x1][z1+1].x = 0.0f;
304 0 : vertexNormal_[x1][z1+1].y = 0.0f;
305 0 : vertexNormal_[x1][z1+1].z = 0.0f;
306 :
307 0 : vertexNormal_[x1+1][z1+1].x = 0.0f;
308 0 : vertexNormal_[x1+1][z1+1].y = 0.0f;
309 0 : vertexNormal_[x1+1][z1+1].z = 0.0f;
310 :
311 0 : n = n->next;
312 : }
313 :
314 0 : n = displayList_->head;
315 :
316 0 : while (n != NULL) {
317 0 : xStart = n->min[0] / scaleFactor_;
318 0 : zStart = n->min[1] / scaleFactor_;
319 :
320 0 : x1 = (int)xStart;
321 0 : x2 = ((int)xStart) + 1;
322 :
323 0 : z1 = (int)zStart;
324 0 : z2 = ((int)zStart) + 1;
325 :
326 0 : if (x2 >= xSize_ || z2 >= zSize_) {
327 0 : continue;
328 : }
329 :
330 0 : temp[0].setVector(vertex_[x1][z1][0], vertex_[x1][z1][1], vertex_[x1][z1][2]);
331 0 : temp[1].setVector(vertex_[x1][z2][0], vertex_[x1][z2][1], vertex_[x1][z2][2]);
332 0 : temp[2].setVector(vertex_[x2][z1][0], vertex_[x2][z1][1], vertex_[x2][z1][2]);
333 0 : temp[3].setVector(vertex_[x2][z2][0], vertex_[x2][z2][1], vertex_[x2][z2][2]);
334 :
335 0 : surfaceNormal.calcNorm(temp[0], temp[2], temp[1]);
336 :
337 0 : vertexNormal_[x1][z1].x += surfaceNormal.x;
338 0 : vertexNormal_[x1][z1].y += surfaceNormal.y;
339 0 : vertexNormal_[x1][z1].z += surfaceNormal.z;
340 :
341 0 : vertexNormal_[x1][z2].x += surfaceNormal.x;
342 0 : vertexNormal_[x1][z2].y += surfaceNormal.y;
343 0 : vertexNormal_[x1][z2].z += surfaceNormal.z;
344 :
345 0 : vertexNormal_[x2][z1].x += surfaceNormal.x;
346 0 : vertexNormal_[x2][z1].y += surfaceNormal.y;
347 0 : vertexNormal_[x2][z1].z += surfaceNormal.z;
348 :
349 0 : surfaceNormal.calcNorm(temp[2], temp[3], temp[1]);
350 :
351 0 : vertexNormal_[x2][z1].x += surfaceNormal.x;
352 0 : vertexNormal_[x2][z1].y += surfaceNormal.y;
353 0 : vertexNormal_[x2][z1].z += surfaceNormal.z;
354 :
355 0 : vertexNormal_[x1][z2].x += surfaceNormal.x;
356 0 : vertexNormal_[x1][z2].y += surfaceNormal.y;
357 0 : vertexNormal_[x1][z2].z += surfaceNormal.z;
358 :
359 0 : vertexNormal_[x2][z2].x += surfaceNormal.x;
360 0 : vertexNormal_[x2][z2].y += surfaceNormal.y;
361 0 : vertexNormal_[x2][z2].z += surfaceNormal.z;
362 :
363 0 : n = n->next;
364 : }
365 :
366 : // calculate light intensity at every vertex
367 0 : n = displayList_->head;
368 :
369 0 : while (n != NULL) {
370 0 : xStart = n->min[0] / scaleFactor_;
371 0 : zStart = n->min[1] / scaleFactor_;
372 :
373 0 : x1 = (int)xStart;
374 0 : x2 = ((int)xStart) + 1;
375 :
376 0 : z1 = (int)zStart;
377 0 : z2 = ((int)zStart) + 1;
378 :
379 0 : vertexNormal_[x1][z1].normalize();
380 :
381 0 : temp2.rotateVector(tempMatrix, vertexNormal_[x1][z1]);
382 0 : temp2.normalize();
383 :
384 0 : tempLightIntensity = temp2.dotProduct(*light_);
385 :
386 : // light correction //
387 0 : if (tempLightIntensity == 1.0f)
388 0 : tempLightIntensity = 0.5f;
389 0 : else if (tempLightIntensity < 0.0f)
390 0 : tempLightIntensity = 0.0f;
391 :
392 0 : lightIntensity_[x1][z1] = tempLightIntensity;
393 :
394 0 : n = n->next;
395 : }
396 0 : }
397 :
398 : //------------------------------------------------------------------------------
399 0 : void Terrain::calcTerrainNorm(Vector* light) {
400 0 : if (!vertex_ || !lightIntensity_ || !color_ || !type_) {
401 0 : PRINT_ERROR("Could not save terrain.\n");
402 0 : return;
403 : }
404 :
405 0 : Vector surfaceNormal;
406 0 : Vector temp1;
407 0 : Vector temp2;
408 : GLfloat tempLightIntensity;
409 :
410 0 : Vector temp[5];
411 :
412 0 : Matrix tempMatrix;
413 0 : tempMatrix.loadIdentity();
414 :
415 : int x1, x2;
416 : int z1, z2;
417 :
418 : // calculate surface normal
419 0 : for (int z = 0; z < (zSize_-1); z++) {
420 0 : for (int x = 0; x < (xSize_-1); x++) {
421 0 : x1 = x;
422 0 : x2 = x+1;
423 0 : z1 = z;
424 0 : z2 = z+1;
425 :
426 0 : temp[0].setVector(vertex_[x1][z1][0], vertex_[x1][z1][1], vertex_[x1][z1][2]);
427 0 : temp[1].setVector(vertex_[x1][z2][0], vertex_[x1][z2][1], vertex_[x1][z2][2]);
428 0 : temp[2].setVector(vertex_[x2][z1][0], vertex_[x2][z1][1], vertex_[x2][z1][2]);
429 0 : temp[3].setVector(vertex_[x2][z2][0], vertex_[x2][z2][1], vertex_[x2][z2][2]);
430 :
431 0 : surfaceNormal.calcNorm(temp[0], temp[2], temp[1]);
432 :
433 0 : vertexNormal_[x1][z1].x += surfaceNormal.x;
434 0 : vertexNormal_[x1][z1].y += surfaceNormal.y;
435 0 : vertexNormal_[x1][z1].z += surfaceNormal.z;
436 :
437 0 : vertexNormal_[x1][z2].x += surfaceNormal.x;
438 0 : vertexNormal_[x1][z2].y += surfaceNormal.y;
439 0 : vertexNormal_[x1][z2].z += surfaceNormal.z;
440 :
441 0 : vertexNormal_[x2][z1].x += surfaceNormal.x;
442 0 : vertexNormal_[x2][z1].y += surfaceNormal.y;
443 0 : vertexNormal_[x2][z1].z += surfaceNormal.z;
444 :
445 0 : surfaceNormal.calcNorm(temp[2], temp[3], temp[1]);
446 :
447 0 : vertexNormal_[x2][z1].x += surfaceNormal.x;
448 0 : vertexNormal_[x2][z1].y += surfaceNormal.y;
449 0 : vertexNormal_[x2][z1].z += surfaceNormal.z;
450 :
451 0 : vertexNormal_[x1][z2].x += surfaceNormal.x;
452 0 : vertexNormal_[x1][z2].y += surfaceNormal.y;
453 0 : vertexNormal_[x1][z2].z += surfaceNormal.z;
454 :
455 0 : vertexNormal_[x2][z2].x += surfaceNormal.x;
456 0 : vertexNormal_[x2][z2].y += surfaceNormal.y;
457 0 : vertexNormal_[x2][z2].z += surfaceNormal.z;
458 0 : }
459 0 : }
460 :
461 : // calculate light intensity at every vertex
462 0 : for (int z = 0; z < zSize_; z++) {
463 0 : for (int x = 0; x < xSize_; x++) {
464 0 : vertexNormal_[x][z].normalize();
465 :
466 0 : temp2.rotateVector(tempMatrix, vertexNormal_[x][z]);
467 0 : temp2.normalize();
468 :
469 0 : tempLightIntensity = temp2.dotProduct(*light);
470 :
471 : // light correction //
472 0 : if (tempLightIntensity == 1.0f)
473 0 : tempLightIntensity = 0.5f;
474 0 : else if (tempLightIntensity < 0.0f)
475 0 : tempLightIntensity = 0.0f;
476 :
477 0 : lightIntensity_[x][z] = tempLightIntensity;
478 0 : }
479 0 : }
480 0 : }
481 :
482 : //------------------------------------------------------------------------------
483 0 : void Terrain::update(Vector* light) {
484 0 : if (vertex_ == NULL || lightIntensity_ == NULL || color_ == NULL || type_ == NULL) {
485 0 : return;
486 : }
487 :
488 0 : if (lastLight_.x != light->x || lastLight_.y != light->y || lastLight_.z != light->z) {
489 0 : calcViewableTerrainNorm();
490 0 : lastLight_.setVector(light->x, light->y, light->z);
491 0 : }
492 0 : }
493 :
494 : //------------------------------------------------------------------------------
495 0 : float Terrain::getHeight(const float &x, const float &z) {
496 0 : if (vertex_ == NULL || lightIntensity_ == NULL || color_ == NULL || type_ == NULL) {
497 0 : return 0.0f;
498 : }
499 :
500 : float terX, terZ;
501 :
502 : // x and z value in terms of the terrain
503 0 : terX = x / scaleFactor_;
504 0 : terZ = -z / scaleFactor_;
505 :
506 : // calculate cell row and column into array
507 : int row, col1, col2;
508 0 : col1 = (int)(terX);
509 0 : row = (int)(terZ);
510 0 : col2 = col1 + 1;
511 :
512 0 : if (col1 < 0 || col2 < 0 || row < 0) {
513 : PRINT_DEBUG("Error: x=%f, z=%f, row=%d, col1=%d, col2=%d\n", x, -z, row, col1, col2);
514 0 : return 0.0f;
515 : }
516 :
517 : // test to make sure still in terrain
518 0 : if (col1 >= xSize_ || col2 >= xSize_ || row >= zSize_) {
519 : // TODO: Does subtracting the xSize from col2 provide any benefit?
520 : //col2 -= xSize_;
521 : PRINT_DEBUG("Calculated coordinates outside of the terrain...\n");
522 0 : return 0.0f;
523 : }
524 :
525 : // calculate percentage into cell
526 : float perX, perZ;
527 0 : perX = fmod(terX, xSize_) - col1;
528 0 : perZ = float(terZ) - row;
529 :
530 : // get height values at all 4 corners
531 : float height1, height2, height3, height4;
532 0 : height1 = vertex_[col1][row][1];
533 0 : height2 = vertex_[col2][row][1];
534 0 : height3 = vertex_[col1][row+1][1];
535 0 : height4 = vertex_[col2][row+1][1];
536 :
537 : // calculate the final height using bilinear interpolation
538 0 : float th1 = (1 - perZ )*height1 + (perZ*height3);
539 0 : float th2 = (1 - perZ )*height2 + (perZ*height4);
540 :
541 0 : float finalHeight = (1 - perX) * th1 + (perX * th2);
542 :
543 : PRINT_DEBUG_LVL(5, "returning height=%f\n", finalHeight);
544 :
545 0 : return (finalHeight);
546 0 : }
547 :
548 : //------------------------------------------------------------------------------
549 0 : void Terrain::animate(const float &elapsedTime, Object* c) {
550 0 : if (vertex_ == NULL || lightIntensity_ == NULL || color_ == NULL || type_ == NULL) {
551 0 : return;
552 : }
553 :
554 0 : totalTime_ += elapsedTime;
555 :
556 : int x1;
557 : int z1;
558 :
559 : float xStart, zStart;
560 :
561 0 : xStart = zStart = 0;
562 :
563 0 : QuadTreeNode* n = displayList_->head;
564 :
565 : PRINT_DEBUG_LVL(5, "--------------\n");
566 :
567 0 : while (n != NULL) {
568 0 : xStart = n->min[0] / scaleFactor_;
569 0 : zStart = n->min[1] / scaleFactor_;
570 :
571 0 : x1 = (int)xStart;
572 :
573 0 : z1 = (int)zStart;
574 :
575 : PRINT_DEBUG_LVL(5, "x1=%d, z1=%d\n", x1, z1);
576 :
577 : //if (z1 < zSize_ - 1 && z1 > 3) {
578 0 : if (type_[x1][z1] == 1) {
579 0 : if (totalTime_ > 0.5f) {
580 0 : if (rand() % 100 < 20)
581 0 : type_[x1][z1] = 2;
582 0 : }
583 0 : }
584 0 : else if (type_[x1][z1] == 2) {
585 0 : vertex_[x1][z1][1] += (elapsedTime);
586 :
587 0 : if (vertex_[x1][z1][1] > 2.0f) {
588 0 : vertex_[x1][z1][1] = 2.0f;
589 0 : type_[x1][z1] = 3;
590 0 : }
591 0 : }
592 0 : else if (type_[x1][z1] == 3) {
593 0 : vertex_[x1][z1][1] -= (elapsedTime);
594 :
595 0 : if (vertex_[x1][z1][1] < 0.0f) {
596 0 : vertex_[x1][z1][1] = 0.0f;
597 0 : type_[x1][z1] = 1;
598 0 : }
599 0 : }
600 : //}
601 :
602 0 : n = n->next;
603 : }
604 :
605 0 : if (totalTime_ > 0.5f)
606 0 : totalTime_ = 0.0f;
607 :
608 0 : calcViewableTerrainNorm();
609 0 : }
610 :
611 : //------------------------------------------------------------------------------
612 0 : void Terrain::load(const char* filePath, Vector* light) {
613 0 : init();
614 :
615 0 : GLfloat min[] = { 9999.0f, 9999.0f, 9999.0f };
616 0 : GLfloat max[] = { -9999.0f, -9999.0f, -9999.0f };
617 :
618 0 : light_ = light;
619 :
620 0 : std::ifstream fin;
621 0 : fin.open(filePath);
622 0 : fin >> xSize_;
623 0 : fin >> zSize_;
624 0 : fin >> scaleFactor_;
625 :
626 0 : vertex_ = new GLfloat**[xSize_];
627 0 : lightIntensity_ = new GLfloat*[xSize_];
628 0 : color_ = new GLfloat**[xSize_];
629 0 : type_ = new GLint*[xSize_];
630 :
631 0 : for (int i = 0; i < xSize_; i++) {
632 0 : vertex_[i] = new GLfloat*[zSize_];
633 0 : lightIntensity_[i] = new GLfloat[zSize_];
634 0 : color_[i] = new GLfloat*[zSize_];
635 0 : type_[i] = new GLint[zSize_];
636 :
637 0 : for (int j = 0; j < zSize_; j++) {
638 0 : vertex_[i][j] = new GLfloat[3];
639 0 : color_[i][j] = new GLfloat[3];
640 0 : }
641 0 : }
642 :
643 0 : for (int z = 0; z < zSize_; z++) {
644 0 : for (int x = 0; x < xSize_; x++) {
645 0 : fin >> vertex_[x][z][1];
646 0 : vertex_[x][z][0] = x * scaleFactor_;
647 0 : vertex_[x][z][2] = -z * scaleFactor_;
648 0 : fin >> color_[x][z][0] >> color_[x][z][1] >> color_[x][z][2];
649 0 : fin >> type_[x][z];
650 :
651 0 : if (type_[x][z] == 1) {
652 0 : vertex_[x][z][1] = (rand() % 100 / 100.0f) * 2.0f;
653 0 : int t = rand() % 100;
654 0 : if (t < 20) {
655 0 : type_[x][z] = 2;
656 0 : }
657 0 : else if (t < 40) {
658 0 : type_[x][z] = 3;
659 0 : }
660 0 : }
661 :
662 0 : for (int i = 0; i < 3; i++) {
663 0 : if (vertex_[x][z][i] < min[i])
664 0 : min[i] = vertex_[x][z][i];
665 :
666 0 : if (vertex_[x][z][i] > max[i])
667 0 : max[i] = vertex_[x][z][i];
668 0 : }
669 0 : }
670 0 : }
671 :
672 0 : fin.close();
673 :
674 0 : vertexNormal_ = new Vector*[xSize_];
675 0 : for (int i = 0; i < xSize_; i++) {
676 0 : vertexNormal_[i] = new Vector[zSize_];
677 0 : }
678 :
679 : // calculate normals in code for now, later add static calculation to be
680 : // loaded in... only water will be dynamic
681 0 : calcTerrainNorm(light);
682 :
683 0 : collisionBox_[0].setVector( min[0], min[1], min[2] );
684 0 : collisionBox_[1].setVector( max[0], max[1], max[2] );
685 :
686 : PRINT_DEBUG("Terrain Collision Box min x=%f, y=%f, z=%f\n", collisionBox_[0].x, collisionBox_[0].y, collisionBox_[0].z);
687 : PRINT_DEBUG("Terrain Collision Box max x=%f, y=%f, z=%f\n", collisionBox_[1].x, collisionBox_[1].y, collisionBox_[1].z);
688 0 : }
689 :
690 : //------------------------------------------------------------------------------
691 9 : void Terrain::unload() {
692 9 : if (vertex_ != NULL && lightIntensity_ != NULL && color_ != NULL && type_ != NULL && vertexNormal_ != NULL) {
693 0 : for (int i = 0; i < xSize_; i++) {
694 0 : for (int j = 0; j < zSize_; j++) {
695 0 : delete[] vertex_[i][j];
696 0 : delete[] color_[i][j];
697 0 : }
698 :
699 0 : delete[] vertex_[i];
700 0 : delete[] lightIntensity_[i];
701 0 : delete[] color_[i];
702 0 : delete[] vertexNormal_[i];
703 0 : delete[] type_[i];
704 0 : }
705 :
706 0 : delete[] vertex_;
707 0 : delete[] lightIntensity_;
708 0 : delete[] color_;
709 0 : delete[] vertexNormal_;
710 0 : delete[] type_;
711 0 : }
712 :
713 9 : vertex_ = NULL;
714 9 : lightIntensity_ = NULL;
715 9 : color_ = NULL;
716 9 : vertexNormal_ = NULL;
717 9 : type_ = NULL;
718 9 : }
719 :
720 : //------------------------------------------------------------------------------
721 0 : void Terrain::drawGrid() {
722 0 : glPushMatrix();
723 : //glDepthFunc( GL_ALWAYS );
724 0 : glColor3f(1.0f, 0.0f, 0.0f);
725 0 : glBegin(GL_LINES);
726 :
727 0 : for (int x = 0; x < xSize_; x++) {
728 0 : glVertex3f(x*scaleFactor_, 10.0f, 0.0f);
729 0 : glVertex3f(x*scaleFactor_, 10.0f, -(zSize_ - 1) * scaleFactor_);
730 0 : }
731 :
732 0 : for (int z = 0; z < zSize_; z++ ) {
733 0 : glVertex3f(0.0f, 10.0f, -z * scaleFactor_);
734 0 : glVertex3f((xSize_ - 1) * scaleFactor_, 10.0f, -z * scaleFactor_);
735 0 : }
736 :
737 0 : glEnd();
738 0 : glPopMatrix();
739 0 : }
740 :
741 : //------------------------------------------------------------------------------
742 0 : void Terrain::save(const char* filePath, Vector* light) {
743 0 : if (vertex_ == NULL || lightIntensity_ == NULL || color_ == NULL || type_ == NULL) {
744 0 : PRINT_ERROR("Could not save terrain.\n");
745 0 : return;
746 : }
747 :
748 0 : std::ofstream fin;
749 0 : fin.open(filePath);
750 0 : fin << xSize_ << std::endl;
751 0 : fin << zSize_ << std::endl;
752 0 : fin << scaleFactor_ << std::endl;
753 :
754 0 : for (int z = 0; z < zSize_; z++) {
755 0 : for (int x = 0; x < xSize_; x++) {
756 0 : fin << vertex_[x][z][1] << std::endl;
757 :
758 0 : fin << color_[x][z][0] << "\t" << color_[x][z][1]<< "\t" << color_[x][z][2] << std::endl;
759 0 : int type = type_[x][z] == 0 ? 0 : 1;
760 0 : fin << type << std::endl;
761 0 : }
762 0 : }
763 :
764 0 : fin.close();
765 0 : }
766 :
767 0 : void Terrain::setVertexHeight(const int &x, const int &z, const float &height) {
768 0 : if (!vertex_)
769 0 : return;
770 :
771 0 : if ( x >= 0 && x <= xSize_ - 1 && z >= 0 && z <= zSize_ - 1) {
772 0 : vertex_[x][z][1] = height;
773 0 : }
774 0 : }
775 :
776 0 : void Terrain::setVertexType(const int &x, const int &z, const int &type) {
777 0 : if (!type_)
778 0 : return;
779 :
780 0 : if ( x >= 0 && x <= xSize_ - 1 && z >= 0 && z <= zSize_ - 1) {
781 0 : type_[x][z] = type;
782 0 : }
783 0 : }
784 :
785 0 : void Terrain::setVertexColor(const int &x, const int &z, const Vector &color) {
786 0 : if (!color_)
787 0 : return;
788 :
789 0 : if ( x >= 0 && x <= xSize_ - 1 && z >= 0 && z <= zSize_ - 1) {
790 0 : color_[x][z][0] = color.x;
791 0 : color_[x][z][1] = color.y;
792 0 : color_[x][z][2] = color.z;
793 0 : }
794 0 : }
795 :
796 : //------------------------------------------------------------------------------
797 0 : float Terrain::getVertexHeight(const int &x, const int &z) {
798 0 : if (!vertex_)
799 0 : return 0.0f;
800 :
801 0 : if ( x >= 0 && x <= xSize_ - 1 && z >= 0 && z <= zSize_ - 1) {
802 0 : return vertex_[x][z][1];
803 : }
804 :
805 0 : return 0.0f;
806 0 : }
807 :
808 : //------------------------------------------------------------------------------
809 0 : int Terrain::getVertexType(const int &x, const int &z) {
810 0 : if (!type_)
811 0 : return 0;
812 :
813 0 : if ( x >= 0 && x <= xSize_ - 1 && z >= 0 && z <= zSize_ - 1) {
814 0 : return type_[x][z];
815 : }
816 :
817 0 : return 0;
818 0 : }
819 :
820 : //------------------------------------------------------------------------------
821 0 : Vector Terrain::getVertexColor(const int &x, const int &z) {
822 0 : Vector color;
823 0 : color.setVector(0.0f, 0.0f, 0.0f);
824 :
825 0 : if (!color_)
826 0 : return color;
827 :
828 0 : if ( x >= 0 && x <= xSize_ - 1 && z >= 0 && z <= zSize_ - 1) {
829 0 : color.setVector(color_[x][z][0], color_[x][z][1], color_[x][z][2]);
830 0 : return color;
831 : }
832 :
833 0 : return color;
834 0 : }
835 :
836 0 : void Terrain::buildLuaObjectTable(lua_State *L) {
837 0 : Object::buildLuaObjectTable(L);
838 0 : }
839 :
840 0 : void Terrain::transferLuaObjectTable(lua_State *L) {
841 0 : Object::transferLuaObjectTable(L);
842 0 : }
|