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/Objects.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;
42 bool Objects::checkcollide(XYZ startpoint, XYZ endpoint, int which)
44 static XYZ colpoint, colviewer, coltarget;
52 for (i = 0; i < numobjects; i++) {
53 if (type[i] != treeleavestype && type[i] != treetrunktype && type[i] != bushtype && type[i] != firetype && i != which) {
54 colviewer = startpoint;
56 if (model[i].LineCheck(&colviewer, &coltarget, &colpoint, &position[i], &yaw[i]) != -1)
64 void Objects::SphereCheckPossible(XYZ *p1, float radius)
67 static int whichpatchx;
68 static int whichpatchz;
70 whichpatchx = p1->x / (terrain.size / subdivision * terrain.scale);
71 whichpatchz = p1->z / (terrain.size / subdivision * terrain.scale);
73 if (whichpatchx >= 0 && whichpatchz >= 0 && whichpatchx < subdivision && whichpatchz < subdivision)
74 if (terrain.patchobjectnum[whichpatchx][whichpatchz] > 0 && terrain.patchobjectnum[whichpatchx][whichpatchz] < 500)
75 for (j = 0; j < terrain.patchobjectnum[whichpatchx][whichpatchz]; j++) {
76 i = terrain.patchobjects[whichpatchx][whichpatchz][j];
78 if (model[i].SphereCheckPossible(p1, radius, &position[i], &yaw[i]) != -1) {
86 static float distance;
88 static XYZ moved, terrainlight;
91 for (i = 0; i < numobjects; i++) {
92 if (type[i] != firetype) {
93 moved = DoRotation(model[i].boundingspherecenter, 0, yaw[i], 0);
94 if (type[i] == tunneltype || frustum.SphereInFrustum(position[i].x + moved.x, position[i].y + moved.y, position[i].z + moved.z, model[i].boundingsphereradius)) {
95 distance = distsq(&viewer, &position[i]);
97 hidden = !(distsqflat(&viewer, &position[i]) > playerdist + 3 || (type[i] != bushtype && type[i] != treeleavestype));
100 if (detail == 2 && distance > viewdistance * viewdistance / 4 && environment == desertenvironment)
101 glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, blurness );
103 glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0 );
104 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
109 if (occluded[i] < 6) {
110 glMatrixMode(GL_MODELVIEW);
113 glEnable(GL_LIGHTING);
115 glDisable(GL_LIGHTING);
117 glTranslatef(position[i].x, position[i].y, position[i].z);
118 if (type[i] == bushtype) {
119 messedwith[i] -= multiplier;
120 if (rotxvel[i] || rotx[i]) {
121 if (rotx[i] > 0) rotxvel[i] -= multiplier * 8 * fabs(rotx[i]);
122 if (rotx[i] < 0) rotxvel[i] += multiplier * 8 * fabs(rotx[i]);
123 if (rotx[i] > 0) rotxvel[i] -= multiplier * 4;
124 if (rotx[i] < 0) rotxvel[i] += multiplier * 4;
125 if (rotxvel[i] > 0) rotxvel[i] -= multiplier * 4;
126 if (rotxvel[i] < 0) rotxvel[i] += multiplier * 4;
127 if (fabs(rotx[i]) < multiplier * 4)
129 if (fabs(rotxvel[i]) < multiplier * 4)
132 rotx[i] += rotxvel[i] * multiplier * 4;
134 if (rotyvel[i] || roty[i]) {
135 if (roty[i] > 0) rotyvel[i] -= multiplier * 8 * fabs(roty[i]);
136 if (roty[i] < 0) rotyvel[i] += multiplier * 8 * fabs(roty[i]);
137 if (roty[i] > 0) rotyvel[i] -= multiplier * 4;
138 if (roty[i] < 0) rotyvel[i] += multiplier * 4;
139 if (rotyvel[i] > 0) rotyvel[i] -= multiplier * 4;
140 if (rotyvel[i] < 0) rotyvel[i] += multiplier * 4;
141 if (fabs(roty[i]) < multiplier * 4)
143 if (fabs(rotyvel[i]) < multiplier * 4)
146 roty[i] += rotyvel[i] * multiplier * 4;
149 glRotatef(roty[i], 1, 0, 0);
152 glRotatef(-rotx[i], 0, 0, 1);
163 if (type[i] == treetrunktype || type[i] == treeleavestype) {
164 if (type[i] == treetrunktype || environment == desertenvironment) {
165 messedwith[i] -= multiplier;
166 if (rotxvel[i] || rotx[i]) {
167 if (rotx[i] > 0) rotxvel[i] -= multiplier * 8 * fabs(rotx[i]);
168 if (rotx[i] < 0) rotxvel[i] += multiplier * 8 * fabs(rotx[i]);
169 if (rotx[i] > 0) rotxvel[i] -= multiplier * 4;
170 if (rotx[i] < 0) rotxvel[i] += multiplier * 4;
171 if (rotxvel[i] > 0) rotxvel[i] -= multiplier * 4;
172 if (rotxvel[i] < 0) rotxvel[i] += multiplier * 4;
173 if (fabs(rotx[i]) < multiplier * 4)
175 if (fabs(rotxvel[i]) < multiplier * 4)
178 rotx[i] += rotxvel[i] * multiplier * 4;
180 if (rotyvel[i] || roty[i]) {
181 if (roty[i] > 0) rotyvel[i] -= multiplier * 8 * fabs(roty[i]);
182 if (roty[i] < 0) rotyvel[i] += multiplier * 8 * fabs(roty[i]);
183 if (roty[i] > 0) rotyvel[i] -= multiplier * 4;
184 if (roty[i] < 0) rotyvel[i] += multiplier * 4;
185 if (rotyvel[i] > 0) rotyvel[i] -= multiplier * 4;
186 if (rotyvel[i] < 0) rotyvel[i] += multiplier * 4;
187 if (fabs(roty[i]) < multiplier * 4)
189 if (fabs(rotyvel[i]) < multiplier * 4)
192 roty[i] += rotyvel[i] * multiplier * 4;
195 glRotatef(roty[i] / 6, 1, 0, 0);
198 glRotatef(-rotx[i] / 6, 0, 0, 1);
209 messedwith[i] -= multiplier;
210 if (rotxvel[i] || rotx[i]) {
211 if (rotx[i] > 0) rotxvel[i] -= multiplier * 8 * fabs(rotx[i]);
212 if (rotx[i] < 0) rotxvel[i] += multiplier * 8 * fabs(rotx[i]);
213 if (rotx[i] > 0) rotxvel[i] -= multiplier * 4;
214 if (rotx[i] < 0) rotxvel[i] += multiplier * 4;
215 if (rotxvel[i] > 0) rotxvel[i] -= multiplier * 4;
216 if (rotxvel[i] < 0) rotxvel[i] += multiplier * 4;
217 if (fabs(rotx[i]) < multiplier * 4)
219 if (fabs(rotxvel[i]) < multiplier * 4)
222 rotx[i] += rotxvel[i] * multiplier * 4;
224 if (rotyvel[i] || roty[i]) {
225 if (roty[i] > 0) rotyvel[i] -= multiplier * 8 * fabs(roty[i]);
226 if (roty[i] < 0) rotyvel[i] += multiplier * 8 * fabs(roty[i]);
227 if (roty[i] > 0) rotyvel[i] -= multiplier * 4;
228 if (roty[i] < 0) rotyvel[i] += multiplier * 4;
229 if (rotyvel[i] > 0) rotyvel[i] -= multiplier * 4;
230 if (rotyvel[i] < 0) rotyvel[i] += multiplier * 4;
231 if (fabs(roty[i]) < multiplier * 4)
233 if (fabs(rotyvel[i]) < multiplier * 4)
236 roty[i] += rotyvel[i] * multiplier * 4;
239 glRotatef(roty[i] / 4, 1, 0, 0);
242 glRotatef(-rotx[i] / 4, 0, 0, 1);
255 if (/*detail==2&&*/environment == snowyenvironment) {
256 if (type[i] == treeleavestype) {
257 glRotatef((sin(windvar + position[i].x * .3) + .5) * 1.5 * (sin(windvar * 2 + position[i].x * .3) + 1) / 2, 1, 0, 0);
259 if (type[i] == treetrunktype) {
260 glRotatef((sin(windvar + position[i].x * .3) + .5)*.5 * (sin(windvar * 2 + position[i].x * .3) + 1) / 2, 1, 0, 0);
262 if (type[i] == bushtype) {
263 glRotatef((sin(windvar + position[i].x * .3) + .5) * 4 * (sin(windvar * 2 + position[i].x * .3) + 1) / 2, 1, 0, 0);
266 if (/*detail==2&&*/environment == grassyenvironment) {
267 if (type[i] == treeleavestype) {
268 glRotatef((sin(windvar + position[i].x * .3) + .5) * 1.5 * .5 * (sin(windvar * 2 + position[i].x * .3) + 1) / 2, 1, 0, 0);
270 if (type[i] == treetrunktype) {
271 glRotatef((sin(windvar + position[i].x * .3) + .5)*.5 * .5 * (sin(windvar * 2 + position[i].x * .3) + 1) / 2, 1, 0, 0);
273 if (type[i] == bushtype) {
274 glRotatef((sin(windvar + position[i].x * .3) + .5) * 4 * .5 * (sin(windvar * 2 + position[i].x * .3) + 1) / 2, 1, 0, 0);
277 if (/*detail==2&&*/environment == desertenvironment) {
278 if (type[i] == bushtype) {
279 glRotatef((sin(windvar + position[i].x * .3) + .5) * 4 * .5 * (sin(windvar * 2 + position[i].x * .3) + 1) / 2, 1, 0, 0);
282 glRotatef(yaw[i], 0, 1, 0);
285 glColor4f((1 - shadowed[i]) / 2 + .5, (1 - shadowed[i]) / 2 + .5, (1 - shadowed[i]) / 2 + .5, distance);
288 glAlphaFunc(GL_GREATER, 0.5);
292 glAlphaFunc(GL_GREATER, 0.1);
294 if (type[i] != treetrunktype && type[i] != treeleavestype && type[i] != bushtype && type[i] != rocktype) {
295 glEnable(GL_CULL_FACE);
296 glAlphaFunc(GL_GREATER, 0.0001);
297 model[i].drawdifftex(boxtextureptr);
298 model[i].drawdecals(terrain.shadowtexture, terrain.bloodtexture, terrain.bloodtexture2, terrain.breaktexture);
300 if (type[i] == rocktype) {
301 glEnable(GL_CULL_FACE);
302 glAlphaFunc(GL_GREATER, 0.0001);
303 glColor4f((1 - shadowed[i]) / 2 + light.ambient[0], (1 - shadowed[i]) / 2 + light.ambient[1], (1 - shadowed[i]) / 2 + light.ambient[2], distance);
304 model[i].drawdifftex(rocktextureptr);
305 model[i].drawdecals(terrain.shadowtexture, terrain.bloodtexture, terrain.bloodtexture2, terrain.breaktexture);
307 if (type[i] == treeleavestype) {
308 glDisable(GL_CULL_FACE);
309 glDisable(GL_LIGHTING);
310 terrainlight = terrain.getLighting(position[i].x, position[i].z);
312 glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, distance);
314 glAlphaFunc(GL_GREATER, 0.2);
319 glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, distance / 3);
320 glAlphaFunc(GL_GREATER, 0);
322 model[i].drawdifftex(treetextureptr);
324 if (type[i] == bushtype) {
325 glDisable(GL_CULL_FACE);
326 glDisable(GL_LIGHTING);
327 terrainlight = terrain.getLighting(position[i].x, position[i].z);
329 glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, distance);
331 glAlphaFunc(GL_GREATER, 0.2);
336 glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, distance / 3);
337 glAlphaFunc(GL_GREATER, 0);
339 model[i].drawdifftex(bushtextureptr);
341 if (type[i] == treetrunktype) {
342 glEnable(GL_CULL_FACE);
343 terrainlight = terrain.getLighting(position[i].x, position[i].z);
344 glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, distance);
345 model[i].drawdifftex(treetextureptr);
355 glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0 );
356 for (i = 0; i < numobjects; i++) {
357 if (type[i] == treeleavestype || type[i] == bushtype) {
358 moved = DoRotation(model[i].boundingspherecenter, 0, yaw[i], 0);
359 if (frustum.SphereInFrustum(position[i].x + moved.x, position[i].y + moved.y, position[i].z + moved.z, model[i].boundingsphereradius)) {
360 hidden = distsqflat(&viewer, &position[i]) <= playerdist + 3;
363 glMatrixMode(GL_MODELVIEW);
365 glEnable(GL_LIGHTING);
367 glTranslatef(position[i].x, position[i].y, position[i].z);
368 if (type[i] == bushtype) {
369 messedwith[i] -= multiplier;
370 if (rotxvel[i] || rotx[i]) {
371 if (rotx[i] > 0) rotxvel[i] -= multiplier * 8 * fabs(rotx[i]);
372 if (rotx[i] < 0) rotxvel[i] += multiplier * 8 * fabs(rotx[i]);
373 if (rotx[i] > 0) rotxvel[i] -= multiplier * 4;
374 if (rotx[i] < 0) rotxvel[i] += multiplier * 4;
375 if (rotxvel[i] > 0) rotxvel[i] -= multiplier * 4;
376 if (rotxvel[i] < 0) rotxvel[i] += multiplier * 4;
377 if (fabs(rotx[i]) < multiplier * 4)
379 if (fabs(rotxvel[i]) < multiplier * 4)
382 rotx[i] += rotxvel[i] * multiplier * 4;
384 if (rotyvel[i] || roty[i]) {
385 if (roty[i] > 0) rotyvel[i] -= multiplier * 8 * fabs(roty[i]);
386 if (roty[i] < 0) rotyvel[i] += multiplier * 8 * fabs(roty[i]);
387 if (roty[i] > 0) rotyvel[i] -= multiplier * 4;
388 if (roty[i] < 0) rotyvel[i] += multiplier * 4;
389 if (rotyvel[i] > 0) rotyvel[i] -= multiplier * 4;
390 if (rotyvel[i] < 0) rotyvel[i] += multiplier * 4;
391 if (fabs(roty[i]) < multiplier * 4)
393 if (fabs(rotyvel[i]) < multiplier * 4)
396 roty[i] += rotyvel[i] * multiplier * 4;
399 glRotatef(roty[i], 1, 0, 0);
402 glRotatef(-rotx[i], 0, 0, 1);
413 if (type[i] == treetrunktype || type[i] == treeleavestype) {
414 messedwith[i] -= multiplier;
415 if (rotxvel[i] || rotx[i]) {
416 if (rotx[i] > 0) rotxvel[i] -= multiplier * 8 * fabs(rotx[i]);
417 if (rotx[i] < 0) rotxvel[i] += multiplier * 8 * fabs(rotx[i]);
418 if (rotx[i] > 0) rotxvel[i] -= multiplier * 4;
419 if (rotx[i] < 0) rotxvel[i] += multiplier * 4;
420 if (rotxvel[i] > 0) rotxvel[i] -= multiplier * 4;
421 if (rotxvel[i] < 0) rotxvel[i] += multiplier * 4;
422 if (fabs(rotx[i]) < multiplier * 4)
424 if (fabs(rotxvel[i]) < multiplier * 4)
427 rotx[i] += rotxvel[i] * multiplier * 4;
429 if (rotyvel[i] || roty[i]) {
430 if (roty[i] > 0) rotyvel[i] -= multiplier * 8 * fabs(roty[i]);
431 if (roty[i] < 0) rotyvel[i] += multiplier * 8 * fabs(roty[i]);
432 if (roty[i] > 0) rotyvel[i] -= multiplier * 4;
433 if (roty[i] < 0) rotyvel[i] += multiplier * 4;
434 if (rotyvel[i] > 0) rotyvel[i] -= multiplier * 4;
435 if (rotyvel[i] < 0) rotyvel[i] += multiplier * 4;
436 if (fabs(roty[i]) < multiplier * 4)
438 if (fabs(rotyvel[i]) < multiplier * 4)
441 roty[i] += rotyvel[i] * multiplier * 4;
444 glRotatef(roty[i] / 2, 1, 0, 0);
447 glRotatef(-rotx[i] / 2, 0, 0, 1);
458 if (environment == snowyenvironment) {
459 if (type[i] == treeleavestype) {
460 glRotatef((sin(windvar + position[i].x * .3) + .5) * 1.5 * (sin(windvar * 2 + position[i].x * .3) + 1) / 2, 1, 0, 0);
462 if (type[i] == treetrunktype) {
463 glRotatef((sin(windvar + position[i].x * .3) + .5)*.5 * (sin(windvar * 2 + position[i].x * .3) + 1) / 2, 1, 0, 0);
465 if (type[i] == bushtype) {
466 glRotatef((sin(windvar + position[i].x * .3) + .5) * 4 * (sin(windvar * 2 + position[i].x * .3) + 1) / 2, 1, 0, 0);
469 if (environment == grassyenvironment) {
470 if (type[i] == treeleavestype) {
471 glRotatef((sin(windvar + position[i].x * .3) + .5) * 1.5 * .5 * (sin(windvar * 2 + position[i].x * .3) + 1) / 2, 1, 0, 0);
473 if (type[i] == treetrunktype) {
474 glRotatef((sin(windvar + position[i].x * .3) + .5)*.5 * .5 * (sin(windvar * 2 + position[i].x * .3) + 1) / 2, 1, 0, 0);
476 if (type[i] == bushtype) {
477 glRotatef((sin(windvar + position[i].x * .3) + .5) * 4 * .5 * (sin(windvar * 2 + position[i].x * .3) + 1) / 2, 1, 0, 0);
480 glRotatef(yaw[i], 0, 1, 0);
481 glColor4f(1, 1, 1, distance);
482 if (type[i] == treeleavestype) {
483 glDisable(GL_CULL_FACE);
484 glDisable(GL_LIGHTING);
485 terrainlight = terrain.getLighting(position[i].x, position[i].z);
488 glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, .3);
489 glAlphaFunc(GL_GREATER, 0);
490 glDisable(GL_ALPHA_TEST);
491 model[i].drawdifftex(treetextureptr);
493 if (type[i] == bushtype) {
494 glDisable(GL_CULL_FACE);
495 glDisable(GL_LIGHTING);
496 terrainlight = terrain.getLighting(position[i].x, position[i].z);
499 glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, .3);
500 glAlphaFunc(GL_GREATER, 0);
501 glDisable(GL_ALPHA_TEST);
502 model[i].drawdifftex(bushtextureptr);
509 if (environment == desertenvironment)
510 glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0 );
511 glEnable(GL_ALPHA_TEST);
512 SetUpLight(&light, 0);
515 void Objects::DeleteObject(int which)
517 type[numobjects - 1] = 0;
518 yaw[numobjects - 1] = 0;
519 position[numobjects - 1] = 0;
520 scale[numobjects - 1] = 0;
521 friction[numobjects - 1] = 0;
526 void Objects::MakeObject(int atype, XYZ where, float ayaw, float ascale)
528 if ((atype != treeleavestype && atype != bushtype) || foliage == 1) {
529 scale[numobjects] = ascale;
530 if (atype == treeleavestype)
531 scale[numobjects] += fabs((float)(Random() % 100) / 900) * ascale;
533 onfire[numobjects] = 0;
534 flamedelay[numobjects] = 0;
535 type[numobjects] = atype;
537 if (atype == firetype)
538 onfire[numobjects] = 1;
540 position[numobjects] = where;
541 if (atype == bushtype)
542 position[numobjects].y = terrain.getHeight(position[numobjects].x, position[numobjects].z) - .3;
543 yaw[numobjects] = ayaw;
545 rotxvel[numobjects] = 0;
546 rotyvel[numobjects] = 0;
547 rotx[numobjects] = 0;
548 roty[numobjects] = 0;
550 if (atype == boxtype) model[numobjects].loaddecal("Models/Box.solid", 0);
551 if (atype == cooltype) model[numobjects].loaddecal("Models/Cool.solid", 0);
552 if (atype == walltype) model[numobjects].loaddecal("Models/Wall.solid", 0);
553 if (atype == tunneltype) model[numobjects].loaddecal("Models/Tunnel.solid", 0);
554 if (atype == chimneytype) model[numobjects].loaddecal("Models/Chimney.solid", 0);
555 if (atype == spiketype) model[numobjects].load("Models/Spike.solid", 0);
556 if (atype == weirdtype) model[numobjects].loaddecal("Models/Weird.solid", 0);
557 if (atype == rocktype) model[numobjects].loaddecal("Models/Rock.solid", 0);
558 if (atype == treetrunktype) model[numobjects].load("Models/TreeTrunk.solid", 0);
559 if (atype == treeleavestype) model[numobjects].load("Models/Leaves.solid", 0);
560 if (atype == bushtype) model[numobjects].load("Models/Bush.solid", 0);
562 if (atype == boxtype) friction[numobjects] = 1.5;
563 if (atype == cooltype) friction[numobjects] = 1.5;
564 if (atype == walltype) friction[numobjects] = 1.5;
565 if (atype == platformtype) friction[numobjects] = 1.5;
566 if (atype == tunneltype) friction[numobjects] = 1.5;
567 if (atype == chimneytype) friction[numobjects] = 1.5;
568 if (atype == rocktype) friction[numobjects] = .5;
569 if (atype == rocktype && ascale>.5) friction[numobjects] = 1.5;
570 if (atype == weirdtype) friction[numobjects] = 1.5;
571 if (atype == spiketype) friction[numobjects] = .4;
572 if (atype == treetrunktype) friction[numobjects] = .4;
573 if (atype == treeleavestype) friction[numobjects] = 0;
575 if (atype == platformtype) {
576 model[numobjects].loaddecal("Models/Platform.solid", 0);
577 model[numobjects].Rotate(90, 0, 0);
580 if (type[numobjects] == boxtype || type[numobjects] == cooltype || type[numobjects] == spiketype || type[numobjects] == weirdtype || type[numobjects] == walltype || type[numobjects] == chimneytype || type[numobjects] == tunneltype || type[numobjects] == platformtype) {
581 model[numobjects].ScaleTexCoords(scale[numobjects] * 1.5);
583 if (type[numobjects] == rocktype) {
584 model[numobjects].ScaleTexCoords(scale[numobjects] * 3);
586 model[numobjects].flat = 1;
587 if (atype == treetrunktype || atype == treeleavestype || atype == rocktype) {
588 model[numobjects].flat = 0;
590 model[numobjects].Scale(.3 * scale[numobjects], .3 * scale[numobjects], .3 * scale[numobjects]);
591 model[numobjects].Rotate(90, 1, 1);
592 if (type[numobjects] == rocktype) {
593 model[numobjects].Rotate(ayaw * 5, 1, 1);
595 model[numobjects].CalculateNormals(1);
596 model[numobjects].ScaleNormals(-1, -1, -1);
598 if (atype == treetrunktype && position[numobjects].y < terrain.getHeight(position[numobjects].x, position[numobjects].z) + 1) {
600 terrain.MakeDecal(shadowdecalpermanent, position[numobjects], 2, .4, 0);
603 if (atype == bushtype && position[numobjects].y < terrain.getHeight(position[numobjects].x, position[numobjects].z) + 1) {
605 terrain.MakeDecal(shadowdecalpermanent, position[numobjects], 1, .4, 0);
608 if (atype != treeleavestype && atype != bushtype && atype != firetype)
609 terrain.AddObject(where + DoRotation(model[numobjects].boundingspherecenter, 0, ayaw, 0), model[numobjects].boundingsphereradius, numobjects);
615 void Objects::MakeObject(int atype, XYZ where, float ayaw, float apitch, float ascale)
617 if ((atype != treeleavestype && atype != bushtype) || foliage == 1) {
618 scale[numobjects] = ascale;
619 if (atype == treeleavestype)
620 scale[numobjects] += fabs((float)(Random() % 100) / 900) * ascale;
622 onfire[numobjects] = 0;
623 flamedelay[numobjects] = 0;
624 type[numobjects] = atype;
626 if (atype == firetype)
627 onfire[numobjects] = 1;
629 position[numobjects] = where;
630 if (atype == bushtype)
631 position[numobjects].y = terrain.getHeight(position[numobjects].x, position[numobjects].z) - .3;
632 yaw[numobjects] = ayaw;
633 pitch[numobjects] = apitch;
635 rotxvel[numobjects] = 0;
636 rotyvel[numobjects] = 0;
637 rotx[numobjects] = 0;
638 roty[numobjects] = 0;
640 if (atype == boxtype) model[numobjects].loaddecal("Models/Box.solid", 0);
641 if (atype == cooltype) model[numobjects].loaddecal("Models/Cool.solid", 0);
642 if (atype == walltype) model[numobjects].loaddecal("Models/Wall.solid", 0);
643 if (atype == tunneltype) model[numobjects].loaddecal("Models/Tunnel.solid", 0);
644 if (atype == chimneytype) model[numobjects].loaddecal("Models/Chimney.solid", 0);
645 if (atype == spiketype) model[numobjects].load("Models/Spike.solid", 0);
646 if (atype == weirdtype) model[numobjects].loaddecal("Models/Weird.solid", 0);
647 if (atype == rocktype) model[numobjects].loaddecal("Models/Rock.solid", 0);
648 if (atype == treetrunktype) model[numobjects].load("Models/TreeTrunk.solid", 0);
649 if (atype == treeleavestype) model[numobjects].load("Models/Leaves.solid", 0);
650 if (atype == bushtype) model[numobjects].load("Models/Bush.solid", 0);
652 if (atype == boxtype) friction[numobjects] = 1.5;
653 if (atype == cooltype) friction[numobjects] = 1.5;
654 if (atype == walltype) friction[numobjects] = 1.5;
655 if (atype == platformtype) friction[numobjects] = 1.5;
656 if (atype == tunneltype) friction[numobjects] = 1.5;
657 if (atype == chimneytype) friction[numobjects] = 1.5;
658 if (atype == rocktype) friction[numobjects] = .5;
659 if (atype == rocktype && ascale>.5) friction[numobjects] = 1.5;
660 if (atype == weirdtype) friction[numobjects] = 1.5;
661 if (atype == spiketype) friction[numobjects] = .4;
662 if (atype == treetrunktype) friction[numobjects] = .4;
663 if (atype == treeleavestype) friction[numobjects] = 0;
665 if (friction[numobjects] == 1.5 && fabs(apitch) > 5)
666 friction[numobjects] = .5;
668 if (atype == platformtype) {
669 model[numobjects].loaddecal("Models/Platform.solid", 0);
670 model[numobjects].Rotate(90, 0, 0);
673 if (type[numobjects] == boxtype || type[numobjects] == cooltype || type[numobjects] == spiketype || type[numobjects] == weirdtype || type[numobjects] == walltype || type[numobjects] == chimneytype || type[numobjects] == tunneltype || type[numobjects] == platformtype) {
674 model[numobjects].ScaleTexCoords(scale[numobjects] * 1.5);
676 if (type[numobjects] == rocktype) {
677 model[numobjects].ScaleTexCoords(scale[numobjects] * 3);
679 model[numobjects].flat = 1;
680 if (atype == treetrunktype || atype == treeleavestype || atype == rocktype) {
681 model[numobjects].flat = 0;
683 model[numobjects].Scale(.3 * scale[numobjects], .3 * scale[numobjects], .3 * scale[numobjects]);
684 model[numobjects].Rotate(90, 1, 1);
685 model[numobjects].Rotate(apitch, 0, 0);
686 if (type[numobjects] == rocktype) {
687 model[numobjects].Rotate(ayaw * 5, 0, 0);
689 model[numobjects].CalculateNormals(1);
690 model[numobjects].ScaleNormals(-1, -1, -1);
692 if (atype == treetrunktype && position[numobjects].y < terrain.getHeight(position[numobjects].x, position[numobjects].z) + 1) {
694 terrain.MakeDecal(shadowdecalpermanent, position[numobjects], 2, .4, 0);
697 if (atype == bushtype && position[numobjects].y < terrain.getHeight(position[numobjects].x, position[numobjects].z) + 1) {
699 terrain.MakeDecal(shadowdecalpermanent, position[numobjects], 1, .4, 0);
702 if (atype != treeleavestype && atype != bushtype && atype != firetype)
703 terrain.AddObject(where + DoRotation(model[numobjects].boundingspherecenter, 0, ayaw, 0), model[numobjects].boundingsphereradius, numobjects);
709 void Objects::DoStuff()
712 for (int i = 0; i < numobjects; i++) {
713 if (type[i] == firetype)
716 if (type[i] == bushtype)
717 flamedelay[i] -= multiplier * 3;
718 if (type[i] == firetype)
719 flamedelay[i] -= multiplier * 3;
720 if (type[i] == treeleavestype)
721 flamedelay[i] -= multiplier * 4;
722 while (flamedelay[i] < 0 && onfire[i]) {
723 flamedelay[i] += .006;
724 if (type[i] == bushtype || type[i] == firetype) {
725 spawnpoint.x = ((float)(Random() % 100)) / 30 * scale[i];
726 spawnpoint.y = ((float)(Random() % 100) + 60) / 30 * scale[i];
728 spawnpoint = DoRotation(spawnpoint, 0, Random() % 360, 0);
729 spawnpoint += position[i];
730 Sprite::MakeSprite(flamesprite, spawnpoint, spawnpoint * 0, 1, 1, 1, (.6 + (float)abs(Random() % 100) / 200 - .25) * 5 * scale[i], 1);
732 if (type[i] == treeleavestype) {
733 spawnpoint.x = ((float)(Random() % 100)) / 80 * scale[i];
734 spawnpoint.y = ((float)(Random() % 100) + 80) / 12 * scale[i];
736 spawnpoint = DoRotation(spawnpoint, 0, Random() % 360, 0);
737 spawnpoint += position[i];
738 Sprite::MakeSprite(flamesprite, spawnpoint, spawnpoint * 0, 1, 1, 1, (.6 + (float)abs(Random() % 100) / 200 - .25) * 6, 1);
746 void Objects::DoShadows()
749 static XYZ testpoint, testpoint2, terrainpoint, lightloc, col;
750 lightloc = light.location;
754 Normalise(&lightloc);
758 for (i = 0; i < numobjects; i++) {
759 if (type[i] != treeleavestype && type[i] != treetrunktype && type[i] != bushtype && type[i] != firetype) {
760 for (j = 0; j < model[i].vertexNum; j++) {
761 terrainpoint = position[i] + DoRotation(model[i].vertex[j] + model[i].normals[j] * .1, 0, yaw[i], 0);
762 //terrainpoint.y+=model[i].boundingsphereradius;
764 patchx = terrainpoint.x / (terrain.size / subdivision * terrain.scale);
765 patchz = terrainpoint.z / (terrain.size / subdivision * terrain.scale);
766 if (patchx >= 0 && patchz >= 0 && patchx < subdivision && patchz < subdivision)
767 if (terrain.patchobjectnum[patchx][patchz])
768 for (k = 0; k < terrain.patchobjectnum[patchx][patchz]; k++) {
769 l = terrain.patchobjects[patchx][patchz][k];
770 if (type[l] != treetrunktype/*&&l!=i*/) {
771 testpoint = terrainpoint;
772 testpoint2 = terrainpoint + lightloc * 50 * (1 - shadowed[i]);
773 if (model[l].LineCheck(&testpoint, &testpoint2, &col, &position[l], &yaw[l]) != -1) {
774 shadowed[i] = 1 - (findDistance(&terrainpoint, &col) / 50);
778 if (shadowed[i] > 0) {
779 col = model[i].normals[j] - DoRotation(lightloc * shadowed[i], 0, -yaw[i], 0);
781 for (k = 0; k < model[i].TriangleNum; k++) {
782 if (model[i].Triangles[k].vertex[0] == j) {
784 model[i].vArray[l + 2] = col.x;
785 model[i].vArray[l + 3] = col.y;
786 model[i].vArray[l + 4] = col.z;
788 if (model[i].Triangles[k].vertex[1] == j) {
790 model[i].vArray[l + 10] = col.x;
791 model[i].vArray[l + 11] = col.y;
792 model[i].vArray[l + 12] = col.z;
794 if (model[i].Triangles[k].vertex[2] == j) {
796 model[i].vArray[l + 18] = col.x;
797 model[i].vArray[l + 19] = col.y;
798 model[i].vArray[l + 20] = col.z;
814 memset(position, 0, sizeof(position));
815 memset(type, 0, sizeof(type));
816 memset(yaw, 0, sizeof(yaw));
817 memset(pitch, 0, sizeof(pitch));
818 memset(rotx, 0, sizeof(rotx));
819 memset(rotxvel, 0, sizeof(rotxvel));
820 memset(roty, 0, sizeof(roty));
821 memset(rotyvel, 0, sizeof(rotyvel));
822 memset(possible, 0, sizeof(possible));
823 memset(model, 0, sizeof(model));
824 memset(displaymodel, 0, sizeof(displaymodel));
825 memset(friction, 0, sizeof(friction));
826 memset(scale, 0, sizeof(scale));
827 memset(messedwith, 0, sizeof(messedwith));
828 memset(checked, 0, sizeof(checked));
829 memset(shadowed, 0, sizeof(shadowed));
830 memset(occluded, 0, sizeof(occluded));
831 memset(onfire, 0, sizeof(onfire));
832 memset(flamedelay, 0, sizeof(flamedelay));
837 boxtextureptr.destroy();
838 treetextureptr.destroy();
839 bushtextureptr.destroy();
840 rocktextureptr.destroy();