2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2016 - Lugaru contributors (see AUTHORS file)
5 This file is part of Lugaru.
7 Lugaru is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 Lugaru is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Lugaru. If not, see <http://www.gnu.org/licenses/>.
21 #include "Objects/Object.hpp"
24 extern float viewdistance;
25 extern float fadestart;
26 extern int environment;
27 extern float texscale;
29 extern float multiplier;
31 extern FRUSTUM frustum;
32 extern Terrain terrain;
35 extern float blurness;
37 extern float playerdist;
38 extern bool skyboxtexture;
40 std::vector<std::unique_ptr<Object>> Object::objects;
42 float Object::radius = 0;
43 Texture Object::boxtextureptr;
44 Texture Object::treetextureptr;
45 Texture Object::bushtextureptr;
46 Texture Object::rocktextureptr;
73 Object::Object(object_type _type, XYZ _position, float _yaw, float _pitch, float _scale) : Object()
83 model.loaddecal("Models/Box.solid");
87 model.loaddecal("Models/Cool.solid");
91 model.loaddecal("Models/Wall.solid");
95 model.loaddecal("Models/Tunnel.solid");
99 model.loaddecal("Models/Chimney.solid");
103 model.load("Models/Spike.solid");
107 model.loaddecal("Models/Weird.solid");
111 model.loaddecal("Models/Rock.solid");
119 model.load("Models/TreeTrunk.solid");
123 scale += fabs((float)(Random() % 100) / 900) * scale;
124 model.load("Models/Leaves.solid");
128 position.y = terrain.getHeight(position.x, position.z) - .3;
129 model.load("Models/Bush.solid");
132 model.loaddecal("Models/Platform.solid");
133 model.Rotate(90, 0, 0);
141 if (friction == 1.5 && fabs(pitch) > 5) {
145 if (type == boxtype || type == cooltype || type == spiketype || type == weirdtype || type == walltype || type == chimneytype || type == tunneltype || type == platformtype) {
146 model.ScaleTexCoords(scale * 1.5);
148 if (type == rocktype) {
149 model.ScaleTexCoords(scale * 3);
152 if (type == treetrunktype || type == treeleavestype || type == rocktype) {
155 model.Scale(.3 * scale, .3 * scale, .3 * scale);
156 model.Rotate(90, 1, 1);
157 model.Rotate(pitch, 0, 0);
158 if (type == rocktype) {
159 model.Rotate(yaw * 5, 0, 0);
161 model.CalculateNormals(1);
162 model.ScaleNormals(-1, -1, -1);
165 void Object::handleFire()
167 if (type == firetype) {
172 if ((type == bushtype) || (type == firetype)) {
173 flamedelay -= multiplier * 3;
174 } else if (type == treeleavestype) {
175 flamedelay -= multiplier * 4;
177 while ((flamedelay < 0) && onfire) {
179 if ((type == bushtype) || (type == firetype)) {
180 spawnpoint.x = ((float)(Random() % 100)) / 30 * scale;
181 spawnpoint.y = ((float)(Random() % 100) + 60) / 30 * scale;
183 spawnpoint = DoRotation(spawnpoint, 0, Random() % 360, 0);
184 spawnpoint += position;
185 Sprite::MakeSprite(flamesprite, spawnpoint, spawnpoint * 0, 1, 1, 1, (.6 + (float)abs(Random() % 100) / 200 - .25) * 5 * scale, 1);
186 } else if (type == treeleavestype) {
187 spawnpoint.x = ((float)(Random() % 100)) / 80 * scale;
188 spawnpoint.y = ((float)(Random() % 100) + 80) / 12 * scale;
190 spawnpoint = DoRotation(spawnpoint, 0, Random() % 360, 0);
191 spawnpoint += position;
192 Sprite::MakeSprite(flamesprite, spawnpoint, spawnpoint * 0, 1, 1, 1, (.6 + (float)abs(Random() % 100) / 200 - .25) * 6, 1);
198 void Object::doShadows(XYZ lightloc)
200 XYZ testpoint, testpoint2, terrainpoint, col;
202 if (type != treeleavestype && type != treetrunktype && type != bushtype && type != firetype) {
203 for (int j = 0; j < model.vertexNum; j++) {
204 terrainpoint = position + DoRotation(model.vertex[j] + model.normals[j] * .1, 0, yaw, 0);
206 patchx = terrainpoint.x / (terrain.size / subdivision * terrain.scale);
207 patchz = terrainpoint.z / (terrain.size / subdivision * terrain.scale);
208 if (patchx >= 0 && patchz >= 0 && patchx < subdivision && patchz < subdivision) {
209 if (terrain.patchobjectnum[patchx][patchz]) {
210 for (int k = 0; k < terrain.patchobjectnum[patchx][patchz]; k++) {
211 int l = terrain.patchobjects[patchx][patchz][k];
212 if (objects[l]->type != treetrunktype) {
213 testpoint = terrainpoint;
214 testpoint2 = terrainpoint + lightloc * 50 * (1 - shadowed);
215 if (objects[l]->model.LineCheck(&testpoint, &testpoint2, &col, &objects[l]->position, &objects[l]->yaw) != -1) {
216 shadowed = 1 - (findDistance(&terrainpoint, &col) / 50);
223 col = model.normals[j] - DoRotation(lightloc * shadowed, 0, -yaw, 0);
225 for (int k = 0; k < model.TriangleNum; k++) {
226 if (model.Triangles[k].vertex[0] == j) {
228 model.vArray[l + 2] = col.x;
229 model.vArray[l + 3] = col.y;
230 model.vArray[l + 4] = col.z;
232 if (model.Triangles[k].vertex[1] == j) {
234 model.vArray[l + 10] = col.x;
235 model.vArray[l + 11] = col.y;
236 model.vArray[l + 12] = col.z;
238 if (model.Triangles[k].vertex[2] == j) {
240 model.vArray[l + 18] = col.x;
241 model.vArray[l + 19] = col.y;
242 model.vArray[l + 20] = col.z;
253 static float distance;
254 static XYZ moved, terrainlight;
256 if (type == firetype) {
259 moved = DoRotation(model.boundingspherecenter, 0, yaw, 0);
260 if (type == tunneltype || frustum.SphereInFrustum(position.x + moved.x, position.y + moved.y, position.z + moved.z, model.boundingsphereradius)) {
261 distance = distsq(&viewer, &position);
263 hidden = !(distsqflat(&viewer, &position) > playerdist + 3 || (type != bushtype && type != treeleavestype));
266 if (detail == 2 && distance > viewdistance * viewdistance / 4 && environment == desertenvironment)
267 glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, blurness );
269 glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0 );
270 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
276 glMatrixMode(GL_MODELVIEW);
279 glEnable(GL_LIGHTING);
281 glDisable(GL_LIGHTING);
283 glTranslatef(position.x, position.y, position.z);
284 if (type == bushtype) {
285 messedwith -= multiplier;
286 if (rotxvel || rotx) {
287 if (rotx > 0) rotxvel -= multiplier * 8 * fabs(rotx);
288 if (rotx < 0) rotxvel += multiplier * 8 * fabs(rotx);
289 if (rotx > 0) rotxvel -= multiplier * 4;
290 if (rotx < 0) rotxvel += multiplier * 4;
291 if (rotxvel > 0) rotxvel -= multiplier * 4;
292 if (rotxvel < 0) rotxvel += multiplier * 4;
293 if (fabs(rotx) < multiplier * 4)
295 if (fabs(rotxvel) < multiplier * 4)
298 rotx += rotxvel * multiplier * 4;
300 if (rotyvel || roty) {
301 if (roty > 0) rotyvel -= multiplier * 8 * fabs(roty);
302 if (roty < 0) rotyvel += multiplier * 8 * fabs(roty);
303 if (roty > 0) rotyvel -= multiplier * 4;
304 if (roty < 0) rotyvel += multiplier * 4;
305 if (rotyvel > 0) rotyvel -= multiplier * 4;
306 if (rotyvel < 0) rotyvel += multiplier * 4;
307 if (fabs(roty) < multiplier * 4)
309 if (fabs(rotyvel) < multiplier * 4)
312 roty += rotyvel * multiplier * 4;
315 glRotatef(roty, 1, 0, 0);
318 glRotatef(-rotx, 0, 0, 1);
329 if (type == treetrunktype || type == treeleavestype) {
330 if (type == treetrunktype || environment == desertenvironment) {
331 messedwith -= multiplier;
332 if (rotxvel || rotx) {
333 if (rotx > 0) rotxvel -= multiplier * 8 * fabs(rotx);
334 if (rotx < 0) rotxvel += multiplier * 8 * fabs(rotx);
335 if (rotx > 0) rotxvel -= multiplier * 4;
336 if (rotx < 0) rotxvel += multiplier * 4;
337 if (rotxvel > 0) rotxvel -= multiplier * 4;
338 if (rotxvel < 0) rotxvel += multiplier * 4;
339 if (fabs(rotx) < multiplier * 4)
341 if (fabs(rotxvel) < multiplier * 4)
344 rotx += rotxvel * multiplier * 4;
346 if (rotyvel || roty) {
347 if (roty > 0) rotyvel -= multiplier * 8 * fabs(roty);
348 if (roty < 0) rotyvel += multiplier * 8 * fabs(roty);
349 if (roty > 0) rotyvel -= multiplier * 4;
350 if (roty < 0) rotyvel += multiplier * 4;
351 if (rotyvel > 0) rotyvel -= multiplier * 4;
352 if (rotyvel < 0) rotyvel += multiplier * 4;
353 if (fabs(roty) < multiplier * 4)
355 if (fabs(rotyvel) < multiplier * 4)
358 roty += rotyvel * multiplier * 4;
361 glRotatef(roty / 6, 1, 0, 0);
364 glRotatef(-rotx / 6, 0, 0, 1);
375 messedwith -= multiplier;
376 if (rotxvel || rotx) {
377 if (rotx > 0) rotxvel -= multiplier * 8 * fabs(rotx);
378 if (rotx < 0) rotxvel += multiplier * 8 * fabs(rotx);
379 if (rotx > 0) rotxvel -= multiplier * 4;
380 if (rotx < 0) rotxvel += multiplier * 4;
381 if (rotxvel > 0) rotxvel -= multiplier * 4;
382 if (rotxvel < 0) rotxvel += multiplier * 4;
383 if (fabs(rotx) < multiplier * 4)
385 if (fabs(rotxvel) < multiplier * 4)
388 rotx += rotxvel * multiplier * 4;
390 if (rotyvel || roty) {
391 if (roty > 0) rotyvel -= multiplier * 8 * fabs(roty);
392 if (roty < 0) rotyvel += multiplier * 8 * fabs(roty);
393 if (roty > 0) rotyvel -= multiplier * 4;
394 if (roty < 0) rotyvel += multiplier * 4;
395 if (rotyvel > 0) rotyvel -= multiplier * 4;
396 if (rotyvel < 0) rotyvel += multiplier * 4;
397 if (fabs(roty) < multiplier * 4)
399 if (fabs(rotyvel) < multiplier * 4)
402 roty += rotyvel * multiplier * 4;
405 glRotatef(roty / 4, 1, 0, 0);
408 glRotatef(-rotx / 4, 0, 0, 1);
421 if (/*detail==2&&*/environment == snowyenvironment) {
422 if (type == treeleavestype) {
423 glRotatef((sin(windvar + position.x * .3) + .5) * 1.5 * (sin(windvar * 2 + position.x * .3) + 1) / 2, 1, 0, 0);
425 if (type == treetrunktype) {
426 glRotatef((sin(windvar + position.x * .3) + .5)*.5 * (sin(windvar * 2 + position.x * .3) + 1) / 2, 1, 0, 0);
428 if (type == bushtype) {
429 glRotatef((sin(windvar + position.x * .3) + .5) * 4 * (sin(windvar * 2 + position.x * .3) + 1) / 2, 1, 0, 0);
432 if (/*detail==2&&*/environment == grassyenvironment) {
433 if (type == treeleavestype) {
434 glRotatef((sin(windvar + position.x * .3) + .5) * 1.5 * .5 * (sin(windvar * 2 + position.x * .3) + 1) / 2, 1, 0, 0);
436 if (type == treetrunktype) {
437 glRotatef((sin(windvar + position.x * .3) + .5)*.5 * .5 * (sin(windvar * 2 + position.x * .3) + 1) / 2, 1, 0, 0);
439 if (type == bushtype) {
440 glRotatef((sin(windvar + position.x * .3) + .5) * 4 * .5 * (sin(windvar * 2 + position.x * .3) + 1) / 2, 1, 0, 0);
443 if (/*detail==2&&*/environment == desertenvironment) {
444 if (type == bushtype) {
445 glRotatef((sin(windvar + position.x * .3) + .5) * 4 * .5 * (sin(windvar * 2 + position.x * .3) + 1) / 2, 1, 0, 0);
448 glRotatef(yaw, 0, 1, 0);
451 glColor4f((1 - shadowed) / 2 + .5, (1 - shadowed) / 2 + .5, (1 - shadowed) / 2 + .5, distance);
454 glAlphaFunc(GL_GREATER, 0.5);
458 glAlphaFunc(GL_GREATER, 0.1);
460 if (type != treetrunktype && type != treeleavestype && type != bushtype && type != rocktype) {
461 glEnable(GL_CULL_FACE);
462 glAlphaFunc(GL_GREATER, 0.0001);
463 model.drawdifftex(boxtextureptr);
464 model.drawdecals(terrain.shadowtexture, terrain.bloodtexture, terrain.bloodtexture2, terrain.breaktexture);
466 if (type == rocktype) {
467 glEnable(GL_CULL_FACE);
468 glAlphaFunc(GL_GREATER, 0.0001);
469 glColor4f((1 - shadowed) / 2 + light.ambient[0], (1 - shadowed) / 2 + light.ambient[1], (1 - shadowed) / 2 + light.ambient[2], distance);
470 model.drawdifftex(rocktextureptr);
471 model.drawdecals(terrain.shadowtexture, terrain.bloodtexture, terrain.bloodtexture2, terrain.breaktexture);
473 if (type == treeleavestype) {
474 glDisable(GL_CULL_FACE);
475 glDisable(GL_LIGHTING);
476 terrainlight = terrain.getLighting(position.x, position.z);
478 glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, distance);
480 glAlphaFunc(GL_GREATER, 0.2);
485 glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, distance / 3);
486 glAlphaFunc(GL_GREATER, 0);
488 model.drawdifftex(treetextureptr);
490 if (type == bushtype) {
491 glDisable(GL_CULL_FACE);
492 glDisable(GL_LIGHTING);
493 terrainlight = terrain.getLighting(position.x, position.z);
495 glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, distance);
497 glAlphaFunc(GL_GREATER, 0.2);
502 glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, distance / 3);
503 glAlphaFunc(GL_GREATER, 0);
505 model.drawdifftex(bushtextureptr);
507 if (type == treetrunktype) {
508 glEnable(GL_CULL_FACE);
509 terrainlight = terrain.getLighting(position.x, position.z);
510 glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, distance);
511 model.drawdifftex(treetextureptr);
520 void Object::drawSecondPass()
522 static float distance;
523 static XYZ moved, terrainlight;
525 if (type != treeleavestype && type != bushtype) {
528 moved = DoRotation(model.boundingspherecenter, 0, yaw, 0);
529 if (frustum.SphereInFrustum(position.x + moved.x, position.y + moved.y, position.z + moved.z, model.boundingsphereradius)) {
530 hidden = distsqflat(&viewer, &position) <= playerdist + 3;
533 glMatrixMode(GL_MODELVIEW);
535 glEnable(GL_LIGHTING);
537 glTranslatef(position.x, position.y, position.z);
538 if (type == bushtype) {
539 messedwith -= multiplier;
540 if (rotxvel || rotx) {
541 if (rotx > 0) rotxvel -= multiplier * 8 * fabs(rotx);
542 if (rotx < 0) rotxvel += multiplier * 8 * fabs(rotx);
543 if (rotx > 0) rotxvel -= multiplier * 4;
544 if (rotx < 0) rotxvel += multiplier * 4;
545 if (rotxvel > 0) rotxvel -= multiplier * 4;
546 if (rotxvel < 0) rotxvel += multiplier * 4;
547 if (fabs(rotx) < multiplier * 4)
549 if (fabs(rotxvel) < multiplier * 4)
552 rotx += rotxvel * multiplier * 4;
554 if (rotyvel || roty) {
555 if (roty > 0) rotyvel -= multiplier * 8 * fabs(roty);
556 if (roty < 0) rotyvel += multiplier * 8 * fabs(roty);
557 if (roty > 0) rotyvel -= multiplier * 4;
558 if (roty < 0) rotyvel += multiplier * 4;
559 if (rotyvel > 0) rotyvel -= multiplier * 4;
560 if (rotyvel < 0) rotyvel += multiplier * 4;
561 if (fabs(roty) < multiplier * 4)
563 if (fabs(rotyvel) < multiplier * 4)
566 roty += rotyvel * multiplier * 4;
569 glRotatef(roty, 1, 0, 0);
572 glRotatef(-rotx, 0, 0, 1);
583 if (type == treetrunktype || type == treeleavestype) {
584 messedwith -= multiplier;
585 if (rotxvel || rotx) {
586 if (rotx > 0) rotxvel -= multiplier * 8 * fabs(rotx);
587 if (rotx < 0) rotxvel += multiplier * 8 * fabs(rotx);
588 if (rotx > 0) rotxvel -= multiplier * 4;
589 if (rotx < 0) rotxvel += multiplier * 4;
590 if (rotxvel > 0) rotxvel -= multiplier * 4;
591 if (rotxvel < 0) rotxvel += multiplier * 4;
592 if (fabs(rotx) < multiplier * 4)
594 if (fabs(rotxvel) < multiplier * 4)
597 rotx += rotxvel * multiplier * 4;
599 if (rotyvel || roty) {
600 if (roty > 0) rotyvel -= multiplier * 8 * fabs(roty);
601 if (roty < 0) rotyvel += multiplier * 8 * fabs(roty);
602 if (roty > 0) rotyvel -= multiplier * 4;
603 if (roty < 0) rotyvel += multiplier * 4;
604 if (rotyvel > 0) rotyvel -= multiplier * 4;
605 if (rotyvel < 0) rotyvel += multiplier * 4;
606 if (fabs(roty) < multiplier * 4)
608 if (fabs(rotyvel) < multiplier * 4)
611 roty += rotyvel * multiplier * 4;
614 glRotatef(roty / 2, 1, 0, 0);
617 glRotatef(-rotx / 2, 0, 0, 1);
628 if (environment == snowyenvironment) {
629 if (type == treeleavestype) {
630 glRotatef((sin(windvar + position.x * .3) + .5) * 1.5 * (sin(windvar * 2 + position.x * .3) + 1) / 2, 1, 0, 0);
632 if (type == treetrunktype) {
633 glRotatef((sin(windvar + position.x * .3) + .5)*.5 * (sin(windvar * 2 + position.x * .3) + 1) / 2, 1, 0, 0);
635 if (type == bushtype) {
636 glRotatef((sin(windvar + position.x * .3) + .5) * 4 * (sin(windvar * 2 + position.x * .3) + 1) / 2, 1, 0, 0);
639 if (environment == grassyenvironment) {
640 if (type == treeleavestype) {
641 glRotatef((sin(windvar + position.x * .3) + .5) * 1.5 * .5 * (sin(windvar * 2 + position.x * .3) + 1) / 2, 1, 0, 0);
643 if (type == treetrunktype) {
644 glRotatef((sin(windvar + position.x * .3) + .5)*.5 * .5 * (sin(windvar * 2 + position.x * .3) + 1) / 2, 1, 0, 0);
646 if (type == bushtype) {
647 glRotatef((sin(windvar + position.x * .3) + .5) * 4 * .5 * (sin(windvar * 2 + position.x * .3) + 1) / 2, 1, 0, 0);
650 glRotatef(yaw, 0, 1, 0);
651 glColor4f(1, 1, 1, distance);
652 if (type == treeleavestype) {
653 glDisable(GL_CULL_FACE);
654 glDisable(GL_LIGHTING);
655 terrainlight = terrain.getLighting(position.x, position.z);
658 glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, .3);
659 glAlphaFunc(GL_GREATER, 0);
660 glDisable(GL_ALPHA_TEST);
661 model.drawdifftex(treetextureptr);
663 if (type == bushtype) {
664 glDisable(GL_CULL_FACE);
665 glDisable(GL_LIGHTING);
666 terrainlight = terrain.getLighting(position.x, position.z);
669 glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, .3);
670 glAlphaFunc(GL_GREATER, 0);
671 glDisable(GL_ALPHA_TEST);
672 model.drawdifftex(bushtextureptr);
679 void Object::ComputeCenter()
682 for (unsigned i = 0; i < objects.size(); i++) {
683 center += objects[i]->position;
685 center /= objects.size();
688 void Object::ComputeRadius()
690 float maxdistance = 0;
692 for (unsigned int i = 0; i < objects.size(); i++) {
693 tempdist = distsq(¢er, &objects[i]->position);
694 if (tempdist > maxdistance) {
695 maxdistance = tempdist;
698 radius = fast_sqrt(maxdistance);
701 void Object::LoadObjectsFromFile(FILE* tfile, bool skip)
706 float yaw, pitch, scale, lastscale;
707 funpackf(tfile, "Bi", &numobjects);
711 for (int i = 0; i < numobjects; i++) {
712 funpackf(tfile, "Bi Bf Bf Bf Bf Bf Bf", &type, &yaw, &pitch, &position.x, &position.y, &position.z, &scale);
714 if (type == treeleavestype) {
717 objects.emplace_back(new Object(object_type(type), position, yaw, pitch, scale));
723 void Object::addToTerrain(unsigned id)
725 if ((type != treeleavestype) && (type != bushtype) && (type != firetype)) {
726 terrain.AddObject(position + DoRotation(model.boundingspherecenter, 0, yaw, 0), model.boundingsphereradius, id);
730 if ((type == treetrunktype) && (position.y < (terrain.getHeight(position.x, position.z) + 1))) {
731 terrain.MakeDecal(shadowdecalpermanent, position, 2, .4, 0);
734 if ((type == bushtype) && (position.y < (terrain.getHeight(position.x, position.z) + 1))) {
735 terrain.MakeDecal(shadowdecalpermanent, position, 1, .4, 0);
740 void Object::AddObjectsToTerrain()
742 for (unsigned i = 0; i < objects.size(); i++) {
743 objects[i]->addToTerrain(i);
747 void Object::SphereCheckPossible(XYZ *p1, float radius)
749 int whichpatchx = p1->x / (terrain.size / subdivision * terrain.scale);
750 int whichpatchz = p1->z / (terrain.size / subdivision * terrain.scale);
752 if (whichpatchx >= 0 && whichpatchz >= 0 && whichpatchx < subdivision && whichpatchz < subdivision) {
753 if (terrain.patchobjectnum[whichpatchx][whichpatchz] > 0 && terrain.patchobjectnum[whichpatchx][whichpatchz] < 500) {
754 for (int j = 0; j < terrain.patchobjectnum[whichpatchx][whichpatchz]; j++) {
755 int i = terrain.patchobjects[whichpatchx][whichpatchz][j];
756 objects[i]->possible = false;
757 if (objects[i]->model.SphereCheckPossible(p1, radius, &objects[i]->position, &objects[i]->yaw) != -1) {
758 objects[i]->possible = true;
767 for (unsigned i = 0; i < objects.size(); i++) {
771 glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0 );
772 for (unsigned i = 0; i < objects.size(); i++) {
773 objects[i]->drawSecondPass();
775 if (environment == desertenvironment) {
776 glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0 );
778 glEnable(GL_ALPHA_TEST);
779 SetUpLight(&light, 0);
782 void Object::DeleteObject(int which)
784 objects.erase(objects.begin() + which);
787 void Object::MakeObject(int atype, XYZ where, float ayaw, float apitch, float ascale)
789 if ((atype != treeleavestype && atype != bushtype) || foliage == 1) {
790 unsigned nextid = objects.size();
791 objects.emplace_back(new Object(object_type(atype), where, ayaw, apitch, ascale));
792 objects.back()->addToTerrain(nextid);
796 void Object::DoStuff()
798 for (unsigned i = 0; i < objects.size(); i++) {
799 objects[i]->handleFire();
803 void Object::DoShadows()
806 lightloc = light.location;
810 Normalise(&lightloc);
812 for (unsigned i = 0; i < objects.size(); i++) {
813 objects[i]->doShadows(lightloc);
817 int Object::checkcollide(XYZ startpoint, XYZ endpoint)
819 float minx, minz, maxx, maxz, miny, maxy;
821 minx = min(startpoint.x, endpoint.x) - 1;
822 miny = min(startpoint.y, endpoint.y) - 1;
823 minz = min(startpoint.z, endpoint.z) - 1;
824 maxx = max(startpoint.x, endpoint.x) + 1;
825 maxy = max(startpoint.y, endpoint.y) + 1;
826 maxz = max(startpoint.z, endpoint.z) + 1;
828 for (unsigned int i = 0; i < objects.size(); i++) {
829 if (checkcollide(startpoint, endpoint, i, minx, miny, minz, maxx, maxy, maxz) != -1) {
837 int Object::checkcollide(XYZ startpoint, XYZ endpoint, int what)
839 float minx, minz, maxx, maxz, miny, maxy;
841 minx = min(startpoint.x, endpoint.x) - 1;
842 miny = min(startpoint.y, endpoint.y) - 1;
843 minz = min(startpoint.z, endpoint.z) - 1;
844 maxx = max(startpoint.x, endpoint.x) + 1;
845 maxy = max(startpoint.y, endpoint.y) + 1;
846 maxz = max(startpoint.z, endpoint.z) + 1;
848 return checkcollide(startpoint, endpoint, what, minx, miny, minz, maxx, maxy, maxz);
851 int Object::checkcollide(XYZ startpoint, XYZ endpoint, int what, float minx, float miny, float minz, float maxx, float maxy, float maxz)
853 XYZ colpoint, colviewer, coltarget;
856 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1) {
860 if ( objects[what]->position.x > minx - objects[what]->model.boundingsphereradius &&
861 objects[what]->position.x < maxx + objects[what]->model.boundingsphereradius &&
862 objects[what]->position.y > miny - objects[what]->model.boundingsphereradius &&
863 objects[what]->position.y < maxy + objects[what]->model.boundingsphereradius &&
864 objects[what]->position.z > minz - objects[what]->model.boundingsphereradius &&
865 objects[what]->position.z < maxz + objects[what]->model.boundingsphereradius) {
866 if ( objects[what]->type != treeleavestype &&
867 objects[what]->type != bushtype &&
868 objects[what]->type != firetype) {
869 colviewer = startpoint;
870 coltarget = endpoint;
871 if (objects[what]->model.LineCheck(&colviewer, &coltarget, &colpoint, &objects[what]->position, &objects[what]->yaw) != -1) {
881 //~ Object::~Objects()
883 //~ boxtextureptr.destroy();
884 //~ treetextureptr.destroy();
885 //~ bushtextureptr.destroy();
886 //~ rocktextureptr.destroy();