]> git.jsancho.org Git - lugaru.git/blob - Source/Objects/Objects.cpp
9064ff8adb263c662613c30cd1970c96123d56a9
[lugaru.git] / Source / Objects / Objects.cpp
1 /*
2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2016 - Lugaru contributors (see AUTHORS file)
4
5 This file is part of Lugaru.
6
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.
11
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.
16
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/>.
19 */
20
21 #include "Objects/Objects.hpp"
22
23 extern XYZ viewer;
24 extern float viewdistance;
25 extern float fadestart;
26 extern int environment;
27 extern float texscale;
28 extern Light light;
29 extern float multiplier;
30 extern float gravity;
31 extern FRUSTUM frustum;
32 extern Terrain terrain;
33 extern bool foliage;
34 extern int detail;
35 extern float blurness;
36 extern float windvar;
37 extern float playerdist;
38 extern bool skyboxtexture;
39
40 //Functions
41
42 bool Objects::checkcollide(XYZ startpoint, XYZ endpoint, int which)
43 {
44     static XYZ colpoint, colviewer, coltarget;
45     static int i;
46
47     startpoint.y += .1;
48     endpoint.y += .1;
49     startpoint.y -= .1;
50     endpoint.y -= .1;
51
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;
55             coltarget = endpoint;
56             if (model[i].LineCheck(&colviewer, &coltarget, &colpoint, &position[i], &yaw[i]) != -1)
57                 return 1;
58         }
59     }
60
61     return 0;
62 }
63
64 void Objects::SphereCheckPossible(XYZ *p1, float radius)
65 {
66     static int i, j;
67     static int whichpatchx;
68     static int whichpatchz;
69
70     whichpatchx = p1->x / (terrain.size / subdivision * terrain.scale);
71     whichpatchz = p1->z / (terrain.size / subdivision * terrain.scale);
72
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];
77                 possible[i] = 0;
78                 if (model[i].SphereCheckPossible(p1, radius, &position[i], &yaw[i]) != -1) {
79                     possible[i] = 1;
80                 }
81             }
82 }
83
84 void Objects::Draw()
85 {
86     static float distance;
87     static int i;
88     static XYZ moved, terrainlight;
89     bool hidden;
90
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]);
96                 distance *= 1.2;
97                 hidden = !(distsqflat(&viewer, &position[i]) > playerdist + 3 || (type[i] != bushtype && type[i] != treeleavestype));
98                 if (!hidden) {
99
100                     if (detail == 2 && distance > viewdistance * viewdistance / 4 && environment == desertenvironment)
101                         glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, blurness );
102                     else
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;
105                     if (distance > 1)
106                         distance = 1;
107                     if (distance > 0) {
108
109                         if (occluded[i] < 6) {
110                             glMatrixMode(GL_MODELVIEW);
111                             glPushMatrix();
112                             if (!model[i].color)
113                                 glEnable(GL_LIGHTING);
114                             else
115                                 glDisable(GL_LIGHTING);
116                             glDepthMask(1);
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)
128                                         rotx[i] = 0;
129                                     if (fabs(rotxvel[i]) < multiplier * 4)
130                                         rotxvel[i] = 0;
131
132                                     rotx[i] += rotxvel[i] * multiplier * 4;
133                                 }
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)
142                                         roty[i] = 0;
143                                     if (fabs(rotyvel[i]) < multiplier * 4)
144                                         rotyvel[i] = 0;
145
146                                     roty[i] += rotyvel[i] * multiplier * 4;
147                                 }
148                                 if (roty[i]) {
149                                     glRotatef(roty[i], 1, 0, 0);
150                                 }
151                                 if (rotx[i]) {
152                                     glRotatef(-rotx[i], 0, 0, 1);
153                                 }
154                                 if (rotx[i] > 10)
155                                     rotx[i] = 10;
156                                 if (rotx[i] < -10)
157                                     rotx[i] = -10;
158                                 if (roty[i] > 10)
159                                     roty[i] = 10;
160                                 if (roty[i] < -10)
161                                     roty[i] = -10;
162                             }
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)
174                                             rotx[i] = 0;
175                                         if (fabs(rotxvel[i]) < multiplier * 4)
176                                             rotxvel[i] = 0;
177
178                                         rotx[i] += rotxvel[i] * multiplier * 4;
179                                     }
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)
188                                             roty[i] = 0;
189                                         if (fabs(rotyvel[i]) < multiplier * 4)
190                                             rotyvel[i] = 0;
191
192                                         roty[i] += rotyvel[i] * multiplier * 4;
193                                     }
194                                     if (roty[i]) {
195                                         glRotatef(roty[i] / 6, 1, 0, 0);
196                                     }
197                                     if (rotx[i]) {
198                                         glRotatef(-rotx[i] / 6, 0, 0, 1);
199                                     }
200                                     if (rotx[i] > 10)
201                                         rotx[i] = 10;
202                                     if (rotx[i] < -10)
203                                         rotx[i] = -10;
204                                     if (roty[i] > 10)
205                                         roty[i] = 10;
206                                     if (roty[i] < -10)
207                                         roty[i] = -10;
208                                 } else {
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)
218                                             rotx[i] = 0;
219                                         if (fabs(rotxvel[i]) < multiplier * 4)
220                                             rotxvel[i] = 0;
221
222                                         rotx[i] += rotxvel[i] * multiplier * 4;
223                                     }
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)
232                                             roty[i] = 0;
233                                         if (fabs(rotyvel[i]) < multiplier * 4)
234                                             rotyvel[i] = 0;
235
236                                         roty[i] += rotyvel[i] * multiplier * 4;
237                                     }
238                                     if (roty[i]) {
239                                         glRotatef(roty[i] / 4, 1, 0, 0);
240                                     }
241                                     if (rotx[i]) {
242                                         glRotatef(-rotx[i] / 4, 0, 0, 1);
243                                     }
244                                     if (rotx[i] > 10)
245                                         rotx[i] = 10;
246                                     if (rotx[i] < -10)
247                                         rotx[i] = -10;
248                                     if (roty[i] > 10)
249                                         roty[i] = 10;
250                                     if (roty[i] < -10)
251                                         roty[i] = -10;
252                                 }
253
254                             }
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);
258                                 }
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);
261                                 }
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);
264                                 }
265                             }
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);
269                                 }
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);
272                                 }
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);
275                                 }
276                             }
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);
280                                 }
281                             }
282                             glRotatef(yaw[i], 0, 1, 0);
283                             if (distance > 1)
284                                 distance = 1;
285                             glColor4f((1 - shadowed[i]) / 2 + .5, (1 - shadowed[i]) / 2 + .5, (1 - shadowed[i]) / 2 + .5, distance);
286                             if (distance >= 1) {
287                                 glDisable(GL_BLEND);
288                                 glAlphaFunc(GL_GREATER, 0.5);
289                             }
290                             if (distance < 1) {
291                                 glEnable(GL_BLEND);
292                                 glAlphaFunc(GL_GREATER, 0.1);
293                             }
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);
299                             }
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);
306                             }
307                             if (type[i] == treeleavestype) {
308                                 glDisable(GL_CULL_FACE);
309                                 glDisable(GL_LIGHTING);
310                                 terrainlight = terrain.getLighting(position[i].x, position[i].z);
311                                 if (!hidden) {
312                                     glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, distance);
313                                     if (distance < 1)
314                                         glAlphaFunc(GL_GREATER, 0.2);
315                                 }
316                                 if (hidden) {
317                                     glDepthMask(0);
318                                     glEnable(GL_BLEND);
319                                     glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, distance / 3);
320                                     glAlphaFunc(GL_GREATER, 0);
321                                 }
322                                 model[i].drawdifftex(treetextureptr);
323                             }
324                             if (type[i] == bushtype) {
325                                 glDisable(GL_CULL_FACE);
326                                 glDisable(GL_LIGHTING);
327                                 terrainlight = terrain.getLighting(position[i].x, position[i].z);
328                                 if (!hidden) {
329                                     glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, distance);
330                                     if (distance < 1)
331                                         glAlphaFunc(GL_GREATER, 0.2);
332                                 }
333                                 if (hidden) {
334                                     glDepthMask(0);
335                                     glEnable(GL_BLEND);
336                                     glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, distance / 3);
337                                     glAlphaFunc(GL_GREATER, 0);
338                                 }
339                                 model[i].drawdifftex(bushtextureptr);
340                             }
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);
346                             }
347                             glPopMatrix();
348                         }
349                     }
350                 }
351             }
352         }
353     }
354
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;
361                 if (hidden) {
362                     distance = 1;
363                     glMatrixMode(GL_MODELVIEW);
364                     glPushMatrix();
365                     glEnable(GL_LIGHTING);
366                     glDepthMask(1);
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)
378                                 rotx[i] = 0;
379                             if (fabs(rotxvel[i]) < multiplier * 4)
380                                 rotxvel[i] = 0;
381
382                             rotx[i] += rotxvel[i] * multiplier * 4;
383                         }
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)
392                                 roty[i] = 0;
393                             if (fabs(rotyvel[i]) < multiplier * 4)
394                                 rotyvel[i] = 0;
395
396                             roty[i] += rotyvel[i] * multiplier * 4;
397                         }
398                         if (roty[i]) {
399                             glRotatef(roty[i], 1, 0, 0);
400                         }
401                         if (rotx[i]) {
402                             glRotatef(-rotx[i], 0, 0, 1);
403                         }
404                         if (rotx[i] > 10)
405                             rotx[i] = 10;
406                         if (rotx[i] < -10)
407                             rotx[i] = -10;
408                         if (roty[i] > 10)
409                             roty[i] = 10;
410                         if (roty[i] < -10)
411                             roty[i] = -10;
412                     }
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)
423                                 rotx[i] = 0;
424                             if (fabs(rotxvel[i]) < multiplier * 4)
425                                 rotxvel[i] = 0;
426
427                             rotx[i] += rotxvel[i] * multiplier * 4;
428                         }
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)
437                                 roty[i] = 0;
438                             if (fabs(rotyvel[i]) < multiplier * 4)
439                                 rotyvel[i] = 0;
440
441                             roty[i] += rotyvel[i] * multiplier * 4;
442                         }
443                         if (roty[i]) {
444                             glRotatef(roty[i] / 2, 1, 0, 0);
445                         }
446                         if (rotx[i]) {
447                             glRotatef(-rotx[i] / 2, 0, 0, 1);
448                         }
449                         if (rotx[i] > 10)
450                             rotx[i] = 10;
451                         if (rotx[i] < -10)
452                             rotx[i] = -10;
453                         if (roty[i] > 10)
454                             roty[i] = 10;
455                         if (roty[i] < -10)
456                             roty[i] = -10;
457                     }
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);
461                         }
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);
464                         }
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);
467                         }
468                     }
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);
472                         }
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);
475                         }
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);
478                         }
479                     }
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);
486                         glDepthMask(0);
487                         glEnable(GL_BLEND);
488                         glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, .3);
489                         glAlphaFunc(GL_GREATER, 0);
490                         glDisable(GL_ALPHA_TEST);
491                         model[i].drawdifftex(treetextureptr);
492                     }
493                     if (type[i] == bushtype) {
494                         glDisable(GL_CULL_FACE);
495                         glDisable(GL_LIGHTING);
496                         terrainlight = terrain.getLighting(position[i].x, position[i].z);
497                         glDepthMask(0);
498                         glEnable(GL_BLEND);
499                         glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, .3);
500                         glAlphaFunc(GL_GREATER, 0);
501                         glDisable(GL_ALPHA_TEST);
502                         model[i].drawdifftex(bushtextureptr);
503                     }
504                     glPopMatrix();
505                 }
506             }
507         }
508     }
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);
513 }
514
515 void Objects::DeleteObject(int which)
516 {
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;
522
523     numobjects--;
524 }
525
526 void Objects::MakeObject(int atype, XYZ where, float ayaw, float ascale)
527 {
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;
532
533         onfire[numobjects] = 0;
534         flamedelay[numobjects] = 0;
535         type[numobjects] = atype;
536
537         if (atype == firetype)
538             onfire[numobjects] = 1;
539
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;
544
545         rotxvel[numobjects] = 0;
546         rotyvel[numobjects] = 0;
547         rotx[numobjects] = 0;
548         roty[numobjects] = 0;
549
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);
561
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;
574
575         if (atype == platformtype) {
576             model[numobjects].loaddecal("Models/Platform.solid", 0);
577             model[numobjects].Rotate(90, 0, 0);
578         }
579
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);
582         }
583         if (type[numobjects] == rocktype) {
584             model[numobjects].ScaleTexCoords(scale[numobjects] * 3);
585         }
586         model[numobjects].flat = 1;
587         if (atype == treetrunktype || atype == treeleavestype || atype == rocktype) {
588             model[numobjects].flat = 0;
589         }
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);
594         }
595         model[numobjects].CalculateNormals(1);
596         model[numobjects].ScaleNormals(-1, -1, -1);
597
598         if (atype == treetrunktype && position[numobjects].y < terrain.getHeight(position[numobjects].x, position[numobjects].z) + 1) {
599             if (detail == 2)
600                 terrain.MakeDecal(shadowdecalpermanent, position[numobjects], 2, .4, 0);
601         }
602
603         if (atype == bushtype && position[numobjects].y < terrain.getHeight(position[numobjects].x, position[numobjects].z) + 1) {
604             if (detail == 2)
605                 terrain.MakeDecal(shadowdecalpermanent, position[numobjects], 1, .4, 0);
606         }
607
608         if (atype != treeleavestype && atype != bushtype && atype != firetype)
609             terrain.AddObject(where + DoRotation(model[numobjects].boundingspherecenter, 0, ayaw, 0), model[numobjects].boundingsphereradius, numobjects);
610
611         numobjects++;
612     }
613 }
614
615 void Objects::MakeObject(int atype, XYZ where, float ayaw, float apitch, float ascale)
616 {
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;
621
622         onfire[numobjects] = 0;
623         flamedelay[numobjects] = 0;
624         type[numobjects] = atype;
625
626         if (atype == firetype)
627             onfire[numobjects] = 1;
628
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;
634
635         rotxvel[numobjects] = 0;
636         rotyvel[numobjects] = 0;
637         rotx[numobjects] = 0;
638         roty[numobjects] = 0;
639
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);
651
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;
664
665         if (friction[numobjects] == 1.5 && fabs(apitch) > 5)
666             friction[numobjects] = .5;
667
668         if (atype == platformtype) {
669             model[numobjects].loaddecal("Models/Platform.solid", 0);
670             model[numobjects].Rotate(90, 0, 0);
671         }
672
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);
675         }
676         if (type[numobjects] == rocktype) {
677             model[numobjects].ScaleTexCoords(scale[numobjects] * 3);
678         }
679         model[numobjects].flat = 1;
680         if (atype == treetrunktype || atype == treeleavestype || atype == rocktype) {
681             model[numobjects].flat = 0;
682         }
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);
688         }
689         model[numobjects].CalculateNormals(1);
690         model[numobjects].ScaleNormals(-1, -1, -1);
691
692         if (atype == treetrunktype && position[numobjects].y < terrain.getHeight(position[numobjects].x, position[numobjects].z) + 1) {
693             if (detail == 2)
694                 terrain.MakeDecal(shadowdecalpermanent, position[numobjects], 2, .4, 0);
695         }
696
697         if (atype == bushtype && position[numobjects].y < terrain.getHeight(position[numobjects].x, position[numobjects].z) + 1) {
698             if (detail == 2)
699                 terrain.MakeDecal(shadowdecalpermanent, position[numobjects], 1, .4, 0);
700         }
701
702         if (atype != treeleavestype && atype != bushtype && atype != firetype)
703             terrain.AddObject(where + DoRotation(model[numobjects].boundingspherecenter, 0, ayaw, 0), model[numobjects].boundingsphereradius, numobjects);
704
705         numobjects++;
706     }
707 }
708
709 void Objects::DoStuff()
710 {
711     XYZ spawnpoint;
712     for (int i = 0; i < numobjects; i++) {
713         if (type[i] == firetype)
714             onfire[i] = 1;
715         if (onfire[i]) {
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];
727                     spawnpoint.z = 0;
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);
731                 }
732                 if (type[i] == treeleavestype) {
733                     spawnpoint.x = ((float)(Random() % 100)) / 80 * scale[i];
734                     spawnpoint.y = ((float)(Random() % 100) + 80) / 12 * scale[i];
735                     spawnpoint.z = 0;
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);
739                 }
740             }
741
742         }
743     }
744 }
745
746 void Objects::DoShadows()
747 {
748     int i, j, k, l;
749     static XYZ testpoint, testpoint2, terrainpoint, lightloc, col;
750     lightloc = light.location;
751     if (!skyboxtexture)
752         lightloc = 0;
753     lightloc.y += 10;
754     Normalise(&lightloc);
755     int patchx, patchz;
756
757     if (numobjects > 0)
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;
763                     shadowed[i] = 0;
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);
775                                     }
776                                 }
777                             }
778                     if (shadowed[i] > 0) {
779                         col = model[i].normals[j] - DoRotation(lightloc * shadowed[i], 0, -yaw[i], 0);
780                         Normalise(&col);
781                         for (k = 0; k < model[i].TriangleNum; k++) {
782                             if (model[i].Triangles[k].vertex[0] == j) {
783                                 l = k * 24;
784                                 model[i].vArray[l + 2] = col.x;
785                                 model[i].vArray[l + 3] = col.y;
786                                 model[i].vArray[l + 4] = col.z;
787                             }
788                             if (model[i].Triangles[k].vertex[1] == j) {
789                                 l = k * 24;
790                                 model[i].vArray[l + 10] = col.x;
791                                 model[i].vArray[l + 11] = col.y;
792                                 model[i].vArray[l + 12] = col.z;
793                             }
794                             if (model[i].Triangles[k].vertex[2] == j) {
795                                 l = k * 24;
796                                 model[i].vArray[l + 18] = col.x;
797                                 model[i].vArray[l + 19] = col.y;
798                                 model[i].vArray[l + 20] = col.z;
799                             }
800                         }
801                     }
802                 }
803             }
804             shadowed[i] = 0;
805         }
806 }
807
808 Objects::Objects()
809 {
810     center = 0;
811     radius = 0;
812     numobjects = 0;
813
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));
833 }
834
835 Objects::~Objects()
836 {
837     boxtextureptr.destroy();
838     treetextureptr.destroy();
839     bushtextureptr.destroy();
840     rocktextureptr.destroy();
841 };
842