]> git.jsancho.org Git - lugaru.git/blob - Source/Objects.cpp
6f98ead6d536f158581f024dd1d652e439708c07
[lugaru.git] / Source / 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.h"
22 extern XYZ viewer;
23 extern float viewdistance;
24 extern float fadestart;
25 extern int environment;
26 extern float texscale;
27 extern Light light;
28 extern float multiplier;
29 extern float gravity;
30 extern FRUSTUM frustum;
31 extern Terrain terrain;
32 extern bool foliage;
33 extern int detail;
34 extern float blurness;
35 extern float windvar;
36 extern float playerdist;
37 extern bool skyboxtexture;
38
39 //Functions
40
41 bool Objects::checkcollide(XYZ startpoint, XYZ endpoint, int which)
42 {
43     static XYZ colpoint, colviewer, coltarget;
44     static int i;
45
46     startpoint.y += .1;
47     endpoint.y += .1;
48     startpoint.y -= .1;
49     endpoint.y -= .1;
50
51     for (i = 0; i < numobjects; i++) {
52         if (type[i] != treeleavestype && type[i] != treetrunktype && type[i] != bushtype && type[i] != firetype && i != which) {
53             colviewer = startpoint;
54             coltarget = endpoint;
55             if (model[i].LineCheck(&colviewer, &coltarget, &colpoint, &position[i], &yaw[i]) != -1)
56                 return 1;
57         }
58     }
59
60     return 0;
61 }
62
63 void Objects::SphereCheckPossible(XYZ *p1, float radius)
64 {
65     static int i, j;
66     static int whichpatchx;
67     static int whichpatchz;
68
69     whichpatchx = p1->x / (terrain.size / subdivision * terrain.scale);
70     whichpatchz = p1->z / (terrain.size / subdivision * terrain.scale);
71
72     if (whichpatchx >= 0 && whichpatchz >= 0 && whichpatchx < subdivision && whichpatchz < subdivision)
73         if (terrain.patchobjectnum[whichpatchx][whichpatchz] > 0 && terrain.patchobjectnum[whichpatchx][whichpatchz] < 500)
74             for (j = 0; j < terrain.patchobjectnum[whichpatchx][whichpatchz]; j++) {
75                 i = terrain.patchobjects[whichpatchx][whichpatchz][j];
76                 possible[i] = 0;
77                 if (model[i].SphereCheckPossible(p1, radius, &position[i], &yaw[i]) != -1) {
78                     possible[i] = 1;
79                 }
80             }
81 }
82
83 void Objects::Draw()
84 {
85     static float distance;
86     static int i;
87     static XYZ moved, terrainlight;
88     bool hidden;
89
90     for (i = 0; i < numobjects; i++) {
91         if (type[i] != firetype) {
92             moved = DoRotation(model[i].boundingspherecenter, 0, yaw[i], 0);
93             if (type[i] == tunneltype || frustum.SphereInFrustum(position[i].x + moved.x, position[i].y + moved.y, position[i].z + moved.z, model[i].boundingsphereradius)) {
94                 distance = distsq(&viewer, &position[i]);
95                 distance *= 1.2;
96                 hidden = !(distsqflat(&viewer, &position[i]) > playerdist + 3 || (type[i] != bushtype && type[i] != treeleavestype));
97                 if (!hidden) {
98
99                     if (detail == 2 && distance > viewdistance * viewdistance / 4 && environment == desertenvironment)
100                         glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, blurness );
101                     else
102                         glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0 );
103                     distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
104                     if (distance > 1)
105                         distance = 1;
106                     if (distance > 0) {
107
108                         if (occluded[i] < 6) {
109                             glMatrixMode(GL_MODELVIEW);
110                             glPushMatrix();
111                             if (!model[i].color)
112                                 glEnable(GL_LIGHTING);
113                             else
114                                 glDisable(GL_LIGHTING);
115                             glDepthMask(1);
116                             glTranslatef(position[i].x, position[i].y, position[i].z);
117                             if (type[i] == bushtype) {
118                                 messedwith[i] -= multiplier;
119                                 if (rotxvel[i] || rotx[i]) {
120                                     if (rotx[i] > 0) rotxvel[i] -= multiplier * 8 * fabs(rotx[i]);
121                                     if (rotx[i] < 0) rotxvel[i] += multiplier * 8 * fabs(rotx[i]);
122                                     if (rotx[i] > 0) rotxvel[i] -= multiplier * 4;
123                                     if (rotx[i] < 0) rotxvel[i] += multiplier * 4;
124                                     if (rotxvel[i] > 0) rotxvel[i] -= multiplier * 4;
125                                     if (rotxvel[i] < 0) rotxvel[i] += multiplier * 4;
126                                     if (fabs(rotx[i]) < multiplier * 4)
127                                         rotx[i] = 0;
128                                     if (fabs(rotxvel[i]) < multiplier * 4)
129                                         rotxvel[i] = 0;
130
131                                     rotx[i] += rotxvel[i] * multiplier * 4;
132                                 }
133                                 if (rotyvel[i] || roty[i]) {
134                                     if (roty[i] > 0) rotyvel[i] -= multiplier * 8 * fabs(roty[i]);
135                                     if (roty[i] < 0) rotyvel[i] += multiplier * 8 * fabs(roty[i]);
136                                     if (roty[i] > 0) rotyvel[i] -= multiplier * 4;
137                                     if (roty[i] < 0) rotyvel[i] += multiplier * 4;
138                                     if (rotyvel[i] > 0) rotyvel[i] -= multiplier * 4;
139                                     if (rotyvel[i] < 0) rotyvel[i] += multiplier * 4;
140                                     if (fabs(roty[i]) < multiplier * 4)
141                                         roty[i] = 0;
142                                     if (fabs(rotyvel[i]) < multiplier * 4)
143                                         rotyvel[i] = 0;
144
145                                     roty[i] += rotyvel[i] * multiplier * 4;
146                                 }
147                                 if (roty[i]) {
148                                     glRotatef(roty[i], 1, 0, 0);
149                                 }
150                                 if (rotx[i]) {
151                                     glRotatef(-rotx[i], 0, 0, 1);
152                                 }
153                                 if (rotx[i] > 10)
154                                     rotx[i] = 10;
155                                 if (rotx[i] < -10)
156                                     rotx[i] = -10;
157                                 if (roty[i] > 10)
158                                     roty[i] = 10;
159                                 if (roty[i] < -10)
160                                     roty[i] = -10;
161                             }
162                             if (type[i] == treetrunktype || type[i] == treeleavestype) {
163                                 if (type[i] == treetrunktype || environment == desertenvironment) {
164                                     messedwith[i] -= multiplier;
165                                     if (rotxvel[i] || rotx[i]) {
166                                         if (rotx[i] > 0) rotxvel[i] -= multiplier * 8 * fabs(rotx[i]);
167                                         if (rotx[i] < 0) rotxvel[i] += multiplier * 8 * fabs(rotx[i]);
168                                         if (rotx[i] > 0) rotxvel[i] -= multiplier * 4;
169                                         if (rotx[i] < 0) rotxvel[i] += multiplier * 4;
170                                         if (rotxvel[i] > 0) rotxvel[i] -= multiplier * 4;
171                                         if (rotxvel[i] < 0) rotxvel[i] += multiplier * 4;
172                                         if (fabs(rotx[i]) < multiplier * 4)
173                                             rotx[i] = 0;
174                                         if (fabs(rotxvel[i]) < multiplier * 4)
175                                             rotxvel[i] = 0;
176
177                                         rotx[i] += rotxvel[i] * multiplier * 4;
178                                     }
179                                     if (rotyvel[i] || roty[i]) {
180                                         if (roty[i] > 0) rotyvel[i] -= multiplier * 8 * fabs(roty[i]);
181                                         if (roty[i] < 0) rotyvel[i] += multiplier * 8 * fabs(roty[i]);
182                                         if (roty[i] > 0) rotyvel[i] -= multiplier * 4;
183                                         if (roty[i] < 0) rotyvel[i] += multiplier * 4;
184                                         if (rotyvel[i] > 0) rotyvel[i] -= multiplier * 4;
185                                         if (rotyvel[i] < 0) rotyvel[i] += multiplier * 4;
186                                         if (fabs(roty[i]) < multiplier * 4)
187                                             roty[i] = 0;
188                                         if (fabs(rotyvel[i]) < multiplier * 4)
189                                             rotyvel[i] = 0;
190
191                                         roty[i] += rotyvel[i] * multiplier * 4;
192                                     }
193                                     if (roty[i]) {
194                                         glRotatef(roty[i] / 6, 1, 0, 0);
195                                     }
196                                     if (rotx[i]) {
197                                         glRotatef(-rotx[i] / 6, 0, 0, 1);
198                                     }
199                                     if (rotx[i] > 10)
200                                         rotx[i] = 10;
201                                     if (rotx[i] < -10)
202                                         rotx[i] = -10;
203                                     if (roty[i] > 10)
204                                         roty[i] = 10;
205                                     if (roty[i] < -10)
206                                         roty[i] = -10;
207                                 } else {
208                                     messedwith[i] -= multiplier;
209                                     if (rotxvel[i] || rotx[i]) {
210                                         if (rotx[i] > 0) rotxvel[i] -= multiplier * 8 * fabs(rotx[i]);
211                                         if (rotx[i] < 0) rotxvel[i] += multiplier * 8 * fabs(rotx[i]);
212                                         if (rotx[i] > 0) rotxvel[i] -= multiplier * 4;
213                                         if (rotx[i] < 0) rotxvel[i] += multiplier * 4;
214                                         if (rotxvel[i] > 0) rotxvel[i] -= multiplier * 4;
215                                         if (rotxvel[i] < 0) rotxvel[i] += multiplier * 4;
216                                         if (fabs(rotx[i]) < multiplier * 4)
217                                             rotx[i] = 0;
218                                         if (fabs(rotxvel[i]) < multiplier * 4)
219                                             rotxvel[i] = 0;
220
221                                         rotx[i] += rotxvel[i] * multiplier * 4;
222                                     }
223                                     if (rotyvel[i] || roty[i]) {
224                                         if (roty[i] > 0) rotyvel[i] -= multiplier * 8 * fabs(roty[i]);
225                                         if (roty[i] < 0) rotyvel[i] += multiplier * 8 * fabs(roty[i]);
226                                         if (roty[i] > 0) rotyvel[i] -= multiplier * 4;
227                                         if (roty[i] < 0) rotyvel[i] += multiplier * 4;
228                                         if (rotyvel[i] > 0) rotyvel[i] -= multiplier * 4;
229                                         if (rotyvel[i] < 0) rotyvel[i] += multiplier * 4;
230                                         if (fabs(roty[i]) < multiplier * 4)
231                                             roty[i] = 0;
232                                         if (fabs(rotyvel[i]) < multiplier * 4)
233                                             rotyvel[i] = 0;
234
235                                         roty[i] += rotyvel[i] * multiplier * 4;
236                                     }
237                                     if (roty[i]) {
238                                         glRotatef(roty[i] / 4, 1, 0, 0);
239                                     }
240                                     if (rotx[i]) {
241                                         glRotatef(-rotx[i] / 4, 0, 0, 1);
242                                     }
243                                     if (rotx[i] > 10)
244                                         rotx[i] = 10;
245                                     if (rotx[i] < -10)
246                                         rotx[i] = -10;
247                                     if (roty[i] > 10)
248                                         roty[i] = 10;
249                                     if (roty[i] < -10)
250                                         roty[i] = -10;
251                                 }
252
253                             }
254                             if (/*detail==2&&*/environment == snowyenvironment) {
255                                 if (type[i] == treeleavestype) {
256                                     glRotatef((sin(windvar + position[i].x * .3) + .5) * 1.5 * (sin(windvar * 2 + position[i].x * .3) + 1) / 2, 1, 0, 0);
257                                 }
258                                 if (type[i] == treetrunktype) {
259                                     glRotatef((sin(windvar + position[i].x * .3) + .5)*.5 * (sin(windvar * 2 + position[i].x * .3) + 1) / 2, 1, 0, 0);
260                                 }
261                                 if (type[i] == bushtype) {
262                                     glRotatef((sin(windvar + position[i].x * .3) + .5) * 4 * (sin(windvar * 2 + position[i].x * .3) + 1) / 2, 1, 0, 0);
263                                 }
264                             }
265                             if (/*detail==2&&*/environment == grassyenvironment) {
266                                 if (type[i] == treeleavestype) {
267                                     glRotatef((sin(windvar + position[i].x * .3) + .5) * 1.5 * .5 * (sin(windvar * 2 + position[i].x * .3) + 1) / 2, 1, 0, 0);
268                                 }
269                                 if (type[i] == treetrunktype) {
270                                     glRotatef((sin(windvar + position[i].x * .3) + .5)*.5 * .5 * (sin(windvar * 2 + position[i].x * .3) + 1) / 2, 1, 0, 0);
271                                 }
272                                 if (type[i] == bushtype) {
273                                     glRotatef((sin(windvar + position[i].x * .3) + .5) * 4 * .5 * (sin(windvar * 2 + position[i].x * .3) + 1) / 2, 1, 0, 0);
274                                 }
275                             }
276                             if (/*detail==2&&*/environment == desertenvironment) {
277                                 if (type[i] == bushtype) {
278                                     glRotatef((sin(windvar + position[i].x * .3) + .5) * 4 * .5 * (sin(windvar * 2 + position[i].x * .3) + 1) / 2, 1, 0, 0);
279                                 }
280                             }
281                             glRotatef(yaw[i], 0, 1, 0);
282                             if (distance > 1)
283                                 distance = 1;
284                             glColor4f((1 - shadowed[i]) / 2 + .5, (1 - shadowed[i]) / 2 + .5, (1 - shadowed[i]) / 2 + .5, distance);
285                             if (distance >= 1) {
286                                 glDisable(GL_BLEND);
287                                 glAlphaFunc(GL_GREATER, 0.5);
288                             }
289                             if (distance < 1) {
290                                 glEnable(GL_BLEND);
291                                 glAlphaFunc(GL_GREATER, 0.1);
292                             }
293                             if (type[i] != treetrunktype && type[i] != treeleavestype && type[i] != bushtype && type[i] != rocktype) {
294                                 glEnable(GL_CULL_FACE);
295                                 glAlphaFunc(GL_GREATER, 0.0001);
296                                 model[i].drawdifftex(boxtextureptr);
297                                 model[i].drawdecals(terrain.shadowtexture, terrain.bloodtexture, terrain.bloodtexture2, terrain.breaktexture);
298                             }
299                             if (type[i] == rocktype) {
300                                 glEnable(GL_CULL_FACE);
301                                 glAlphaFunc(GL_GREATER, 0.0001);
302                                 glColor4f((1 - shadowed[i]) / 2 + light.ambient[0], (1 - shadowed[i]) / 2 + light.ambient[1], (1 - shadowed[i]) / 2 + light.ambient[2], distance);
303                                 model[i].drawdifftex(rocktextureptr);
304                                 model[i].drawdecals(terrain.shadowtexture, terrain.bloodtexture, terrain.bloodtexture2, terrain.breaktexture);
305                             }
306                             if (type[i] == treeleavestype) {
307                                 glDisable(GL_CULL_FACE);
308                                 glDisable(GL_LIGHTING);
309                                 terrainlight = terrain.getLighting(position[i].x, position[i].z);
310                                 if (!hidden) {
311                                     glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, distance);
312                                     if (distance < 1)
313                                         glAlphaFunc(GL_GREATER, 0.2);
314                                 }
315                                 if (hidden) {
316                                     glDepthMask(0);
317                                     glEnable(GL_BLEND);
318                                     glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, distance / 3);
319                                     glAlphaFunc(GL_GREATER, 0);
320                                 }
321                                 model[i].drawdifftex(treetextureptr);
322                             }
323                             if (type[i] == bushtype) {
324                                 glDisable(GL_CULL_FACE);
325                                 glDisable(GL_LIGHTING);
326                                 terrainlight = terrain.getLighting(position[i].x, position[i].z);
327                                 if (!hidden) {
328                                     glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, distance);
329                                     if (distance < 1)
330                                         glAlphaFunc(GL_GREATER, 0.2);
331                                 }
332                                 if (hidden) {
333                                     glDepthMask(0);
334                                     glEnable(GL_BLEND);
335                                     glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, distance / 3);
336                                     glAlphaFunc(GL_GREATER, 0);
337                                 }
338                                 model[i].drawdifftex(bushtextureptr);
339                             }
340                             if (type[i] == treetrunktype) {
341                                 glEnable(GL_CULL_FACE);
342                                 terrainlight = terrain.getLighting(position[i].x, position[i].z);
343                                 glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, distance);
344                                 model[i].drawdifftex(treetextureptr);
345                             }
346                             glPopMatrix();
347                         }
348                     }
349                 }
350             }
351         }
352     }
353
354     glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0 );
355     for (i = 0; i < numobjects; i++) {
356         if (type[i] == treeleavestype || type[i] == bushtype) {
357             moved = DoRotation(model[i].boundingspherecenter, 0, yaw[i], 0);
358             if (frustum.SphereInFrustum(position[i].x + moved.x, position[i].y + moved.y, position[i].z + moved.z, model[i].boundingsphereradius)) {
359                 hidden = distsqflat(&viewer, &position[i]) <= playerdist + 3;
360                 if (hidden) {
361                     distance = 1;
362                     glMatrixMode(GL_MODELVIEW);
363                     glPushMatrix();
364                     glEnable(GL_LIGHTING);
365                     glDepthMask(1);
366                     glTranslatef(position[i].x, position[i].y, position[i].z);
367                     if (type[i] == bushtype) {
368                         messedwith[i] -= multiplier;
369                         if (rotxvel[i] || rotx[i]) {
370                             if (rotx[i] > 0) rotxvel[i] -= multiplier * 8 * fabs(rotx[i]);
371                             if (rotx[i] < 0) rotxvel[i] += multiplier * 8 * fabs(rotx[i]);
372                             if (rotx[i] > 0) rotxvel[i] -= multiplier * 4;
373                             if (rotx[i] < 0) rotxvel[i] += multiplier * 4;
374                             if (rotxvel[i] > 0) rotxvel[i] -= multiplier * 4;
375                             if (rotxvel[i] < 0) rotxvel[i] += multiplier * 4;
376                             if (fabs(rotx[i]) < multiplier * 4)
377                                 rotx[i] = 0;
378                             if (fabs(rotxvel[i]) < multiplier * 4)
379                                 rotxvel[i] = 0;
380
381                             rotx[i] += rotxvel[i] * multiplier * 4;
382                         }
383                         if (rotyvel[i] || roty[i]) {
384                             if (roty[i] > 0) rotyvel[i] -= multiplier * 8 * fabs(roty[i]);
385                             if (roty[i] < 0) rotyvel[i] += multiplier * 8 * fabs(roty[i]);
386                             if (roty[i] > 0) rotyvel[i] -= multiplier * 4;
387                             if (roty[i] < 0) rotyvel[i] += multiplier * 4;
388                             if (rotyvel[i] > 0) rotyvel[i] -= multiplier * 4;
389                             if (rotyvel[i] < 0) rotyvel[i] += multiplier * 4;
390                             if (fabs(roty[i]) < multiplier * 4)
391                                 roty[i] = 0;
392                             if (fabs(rotyvel[i]) < multiplier * 4)
393                                 rotyvel[i] = 0;
394
395                             roty[i] += rotyvel[i] * multiplier * 4;
396                         }
397                         if (roty[i]) {
398                             glRotatef(roty[i], 1, 0, 0);
399                         }
400                         if (rotx[i]) {
401                             glRotatef(-rotx[i], 0, 0, 1);
402                         }
403                         if (rotx[i] > 10)
404                             rotx[i] = 10;
405                         if (rotx[i] < -10)
406                             rotx[i] = -10;
407                         if (roty[i] > 10)
408                             roty[i] = 10;
409                         if (roty[i] < -10)
410                             roty[i] = -10;
411                     }
412                     if (type[i] == treetrunktype || type[i] == treeleavestype) {
413                         messedwith[i] -= multiplier;
414                         if (rotxvel[i] || rotx[i]) {
415                             if (rotx[i] > 0) rotxvel[i] -= multiplier * 8 * fabs(rotx[i]);
416                             if (rotx[i] < 0) rotxvel[i] += multiplier * 8 * fabs(rotx[i]);
417                             if (rotx[i] > 0) rotxvel[i] -= multiplier * 4;
418                             if (rotx[i] < 0) rotxvel[i] += multiplier * 4;
419                             if (rotxvel[i] > 0) rotxvel[i] -= multiplier * 4;
420                             if (rotxvel[i] < 0) rotxvel[i] += multiplier * 4;
421                             if (fabs(rotx[i]) < multiplier * 4)
422                                 rotx[i] = 0;
423                             if (fabs(rotxvel[i]) < multiplier * 4)
424                                 rotxvel[i] = 0;
425
426                             rotx[i] += rotxvel[i] * multiplier * 4;
427                         }
428                         if (rotyvel[i] || roty[i]) {
429                             if (roty[i] > 0) rotyvel[i] -= multiplier * 8 * fabs(roty[i]);
430                             if (roty[i] < 0) rotyvel[i] += multiplier * 8 * fabs(roty[i]);
431                             if (roty[i] > 0) rotyvel[i] -= multiplier * 4;
432                             if (roty[i] < 0) rotyvel[i] += multiplier * 4;
433                             if (rotyvel[i] > 0) rotyvel[i] -= multiplier * 4;
434                             if (rotyvel[i] < 0) rotyvel[i] += multiplier * 4;
435                             if (fabs(roty[i]) < multiplier * 4)
436                                 roty[i] = 0;
437                             if (fabs(rotyvel[i]) < multiplier * 4)
438                                 rotyvel[i] = 0;
439
440                             roty[i] += rotyvel[i] * multiplier * 4;
441                         }
442                         if (roty[i]) {
443                             glRotatef(roty[i] / 2, 1, 0, 0);
444                         }
445                         if (rotx[i]) {
446                             glRotatef(-rotx[i] / 2, 0, 0, 1);
447                         }
448                         if (rotx[i] > 10)
449                             rotx[i] = 10;
450                         if (rotx[i] < -10)
451                             rotx[i] = -10;
452                         if (roty[i] > 10)
453                             roty[i] = 10;
454                         if (roty[i] < -10)
455                             roty[i] = -10;
456                     }
457                     if (environment == snowyenvironment) {
458                         if (type[i] == treeleavestype) {
459                             glRotatef((sin(windvar + position[i].x * .3) + .5) * 1.5 * (sin(windvar * 2 + position[i].x * .3) + 1) / 2, 1, 0, 0);
460                         }
461                         if (type[i] == treetrunktype) {
462                             glRotatef((sin(windvar + position[i].x * .3) + .5)*.5 * (sin(windvar * 2 + position[i].x * .3) + 1) / 2, 1, 0, 0);
463                         }
464                         if (type[i] == bushtype) {
465                             glRotatef((sin(windvar + position[i].x * .3) + .5) * 4 * (sin(windvar * 2 + position[i].x * .3) + 1) / 2, 1, 0, 0);
466                         }
467                     }
468                     if (environment == grassyenvironment) {
469                         if (type[i] == treeleavestype) {
470                             glRotatef((sin(windvar + position[i].x * .3) + .5) * 1.5 * .5 * (sin(windvar * 2 + position[i].x * .3) + 1) / 2, 1, 0, 0);
471                         }
472                         if (type[i] == treetrunktype) {
473                             glRotatef((sin(windvar + position[i].x * .3) + .5)*.5 * .5 * (sin(windvar * 2 + position[i].x * .3) + 1) / 2, 1, 0, 0);
474                         }
475                         if (type[i] == bushtype) {
476                             glRotatef((sin(windvar + position[i].x * .3) + .5) * 4 * .5 * (sin(windvar * 2 + position[i].x * .3) + 1) / 2, 1, 0, 0);
477                         }
478                     }
479                     glRotatef(yaw[i], 0, 1, 0);
480                     glColor4f(1, 1, 1, distance);
481                     if (type[i] == treeleavestype) {
482                         glDisable(GL_CULL_FACE);
483                         glDisable(GL_LIGHTING);
484                         terrainlight = terrain.getLighting(position[i].x, position[i].z);
485                         glDepthMask(0);
486                         glEnable(GL_BLEND);
487                         glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, .3);
488                         glAlphaFunc(GL_GREATER, 0);
489                         glDisable(GL_ALPHA_TEST);
490                         model[i].drawdifftex(treetextureptr);
491                     }
492                     if (type[i] == bushtype) {
493                         glDisable(GL_CULL_FACE);
494                         glDisable(GL_LIGHTING);
495                         terrainlight = terrain.getLighting(position[i].x, position[i].z);
496                         glDepthMask(0);
497                         glEnable(GL_BLEND);
498                         glColor4f(terrainlight.x, terrainlight.y, terrainlight.z, .3);
499                         glAlphaFunc(GL_GREATER, 0);
500                         glDisable(GL_ALPHA_TEST);
501                         model[i].drawdifftex(bushtextureptr);
502                     }
503                     glPopMatrix();
504                 }
505             }
506         }
507     }
508     if (environment == desertenvironment)
509         glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0 );
510     glEnable(GL_ALPHA_TEST);
511     SetUpLight(&light, 0);
512 }
513
514 void Objects::DeleteObject(int which)
515 {
516     type[numobjects - 1] = 0;
517     yaw[numobjects - 1] = 0;
518     position[numobjects - 1] = 0;
519     scale[numobjects - 1] = 0;
520     friction[numobjects - 1] = 0;
521
522     numobjects--;
523 }
524
525 void Objects::MakeObject(int atype, XYZ where, float ayaw, float ascale)
526 {
527     if ((atype != treeleavestype && atype != bushtype) || foliage == 1) {
528         scale[numobjects] = ascale;
529         if (atype == treeleavestype)
530             scale[numobjects] += fabs((float)(Random() % 100) / 900) * ascale;
531
532         onfire[numobjects] = 0;
533         flamedelay[numobjects] = 0;
534         type[numobjects] = atype;
535
536         if (atype == firetype)
537             onfire[numobjects] = 1;
538
539         position[numobjects] = where;
540         if (atype == bushtype)
541             position[numobjects].y = terrain.getHeight(position[numobjects].x, position[numobjects].z) - .3;
542         yaw[numobjects] = ayaw;
543
544         rotxvel[numobjects] = 0;
545         rotyvel[numobjects] = 0;
546         rotx[numobjects] = 0;
547         roty[numobjects] = 0;
548
549         if (atype == boxtype)           model[numobjects].loaddecal((char *)":Data:Models:Box.solid", 0);
550         if (atype == cooltype)          model[numobjects].loaddecal((char *)":Data:Models:Cool.solid", 0);
551         if (atype == walltype)          model[numobjects].loaddecal((char *)":Data:Models:Wall.solid", 0);
552         if (atype == tunneltype)        model[numobjects].loaddecal((char *)":Data:Models:Tunnel.solid", 0);
553         if (atype == chimneytype)       model[numobjects].loaddecal((char *)":Data:Models:Chimney.solid", 0);
554         if (atype == spiketype)         model[numobjects].load((char *)":Data:Models:Spike.solid", 0);
555         if (atype == weirdtype)         model[numobjects].loaddecal((char *)":Data:Models:Weird.solid", 0);
556         if (atype == rocktype)          model[numobjects].loaddecal((char *)":Data:Models:Rock.solid", 0);
557         if (atype == treetrunktype)     model[numobjects].load((char *)":Data:Models:Treetrunk.solid", 0);
558         if (atype == treeleavestype)    model[numobjects].load((char *)":Data:Models:Leaves.solid", 0);
559         if (atype == bushtype)          model[numobjects].load((char *)":Data:Models:Bush.solid", 0);
560
561         if (atype == boxtype)           friction[numobjects] = 1.5;
562         if (atype == cooltype)          friction[numobjects] = 1.5;
563         if (atype == walltype)          friction[numobjects] = 1.5;
564         if (atype == platformtype)      friction[numobjects] = 1.5;
565         if (atype == tunneltype)        friction[numobjects] = 1.5;
566         if (atype == chimneytype)       friction[numobjects] = 1.5;
567         if (atype == rocktype)          friction[numobjects] = .5;
568         if (atype == rocktype && ascale>.5) friction[numobjects] = 1.5;
569         if (atype == weirdtype)         friction[numobjects] = 1.5;
570         if (atype == spiketype)         friction[numobjects] = .4;
571         if (atype == treetrunktype)     friction[numobjects] = .4;
572         if (atype == treeleavestype)    friction[numobjects] = 0;
573
574         if (atype == platformtype) {
575             model[numobjects].loaddecal((char *)":Data:Models:Platform.solid", 0);
576             model[numobjects].Rotate(90, 0, 0);
577         }
578
579         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) {
580             model[numobjects].ScaleTexCoords(scale[numobjects] * 1.5);
581         }
582         if (type[numobjects] == rocktype) {
583             model[numobjects].ScaleTexCoords(scale[numobjects] * 3);
584         }
585         model[numobjects].flat = 1;
586         if (atype == treetrunktype || atype == treeleavestype || atype == rocktype) {
587             model[numobjects].flat = 0;
588         }
589         model[numobjects].Scale(.3 * scale[numobjects], .3 * scale[numobjects], .3 * scale[numobjects]);
590         model[numobjects].Rotate(90, 1, 1);
591         if (type[numobjects] == rocktype) {
592             model[numobjects].Rotate(ayaw * 5, 1, 1);
593         }
594         model[numobjects].CalculateNormals(1);
595         model[numobjects].ScaleNormals(-1, -1, -1);
596
597         if (atype == treetrunktype && position[numobjects].y < terrain.getHeight(position[numobjects].x, position[numobjects].z) + 1) {
598             if (detail == 2)
599                 terrain.MakeDecal(shadowdecalpermanent, position[numobjects], 2, .4, 0);
600         }
601
602         if (atype == bushtype && position[numobjects].y < terrain.getHeight(position[numobjects].x, position[numobjects].z) + 1) {
603             if (detail == 2)
604                 terrain.MakeDecal(shadowdecalpermanent, position[numobjects], 1, .4, 0);
605         }
606
607         if (atype != treeleavestype && atype != bushtype && atype != firetype)
608             terrain.AddObject(where + DoRotation(model[numobjects].boundingspherecenter, 0, ayaw, 0), model[numobjects].boundingsphereradius, numobjects);
609
610         numobjects++;
611     }
612 }
613
614 void Objects::MakeObject(int atype, XYZ where, float ayaw, float apitch, float ascale)
615 {
616     if ((atype != treeleavestype && atype != bushtype) || foliage == 1) {
617         scale[numobjects] = ascale;
618         if (atype == treeleavestype)
619             scale[numobjects] += fabs((float)(Random() % 100) / 900) * ascale;
620
621         onfire[numobjects] = 0;
622         flamedelay[numobjects] = 0;
623         type[numobjects] = atype;
624
625         if (atype == firetype)
626             onfire[numobjects] = 1;
627
628         position[numobjects] = where;
629         if (atype == bushtype)
630             position[numobjects].y = terrain.getHeight(position[numobjects].x, position[numobjects].z) - .3;
631         yaw[numobjects] = ayaw;
632         pitch[numobjects] = apitch;
633
634         rotxvel[numobjects] = 0;
635         rotyvel[numobjects] = 0;
636         rotx[numobjects] = 0;
637         roty[numobjects] = 0;
638
639         if (atype == boxtype)           model[numobjects].loaddecal((char *)":Data:Models:Box.solid", 0);
640         if (atype == cooltype)          model[numobjects].loaddecal((char *)":Data:Models:Cool.solid", 0);
641         if (atype == walltype)          model[numobjects].loaddecal((char *)":Data:Models:Wall.solid", 0);
642         if (atype == tunneltype)        model[numobjects].loaddecal((char *)":Data:Models:Tunnel.solid", 0);
643         if (atype == chimneytype)       model[numobjects].loaddecal((char *)":Data:Models:Chimney.solid", 0);
644         if (atype == spiketype)         model[numobjects].load((char *)":Data:Models:Spike.solid", 0);
645         if (atype == weirdtype)         model[numobjects].loaddecal((char *)":Data:Models:Weird.solid", 0);
646         if (atype == rocktype)          model[numobjects].loaddecal((char *)":Data:Models:Rock.solid", 0);
647         if (atype == treetrunktype)     model[numobjects].load((char *)":Data:Models:Treetrunk.solid", 0);
648         if (atype == treeleavestype)    model[numobjects].load((char *)":Data:Models:Leaves.solid", 0);
649         if (atype == bushtype)          model[numobjects].load((char *)":Data:Models:Bush.solid", 0);
650
651         if (atype == boxtype)           friction[numobjects] = 1.5;
652         if (atype == cooltype)          friction[numobjects] = 1.5;
653         if (atype == walltype)          friction[numobjects] = 1.5;
654         if (atype == platformtype)      friction[numobjects] = 1.5;
655         if (atype == tunneltype)        friction[numobjects] = 1.5;
656         if (atype == chimneytype)       friction[numobjects] = 1.5;
657         if (atype == rocktype)          friction[numobjects] = .5;
658         if (atype == rocktype && ascale>.5) friction[numobjects] = 1.5;
659         if (atype == weirdtype)         friction[numobjects] = 1.5;
660         if (atype == spiketype)         friction[numobjects] = .4;
661         if (atype == treetrunktype)     friction[numobjects] = .4;
662         if (atype == treeleavestype)    friction[numobjects] = 0;
663
664         if (friction[numobjects] == 1.5 && fabs(apitch) > 5)
665             friction[numobjects] = .5;
666
667         if (atype == platformtype) {
668             model[numobjects].loaddecal((char *)":Data:Models:Platform.solid", 0);
669             model[numobjects].Rotate(90, 0, 0);
670         }
671
672         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) {
673             model[numobjects].ScaleTexCoords(scale[numobjects] * 1.5);
674         }
675         if (type[numobjects] == rocktype) {
676             model[numobjects].ScaleTexCoords(scale[numobjects] * 3);
677         }
678         model[numobjects].flat = 1;
679         if (atype == treetrunktype || atype == treeleavestype || atype == rocktype) {
680             model[numobjects].flat = 0;
681         }
682         model[numobjects].Scale(.3 * scale[numobjects], .3 * scale[numobjects], .3 * scale[numobjects]);
683         model[numobjects].Rotate(90, 1, 1);
684         model[numobjects].Rotate(apitch, 0, 0);
685         if (type[numobjects] == rocktype) {
686             model[numobjects].Rotate(ayaw * 5, 0, 0);
687         }
688         model[numobjects].CalculateNormals(1);
689         model[numobjects].ScaleNormals(-1, -1, -1);
690
691         if (atype == treetrunktype && position[numobjects].y < terrain.getHeight(position[numobjects].x, position[numobjects].z) + 1) {
692             if (detail == 2)
693                 terrain.MakeDecal(shadowdecalpermanent, position[numobjects], 2, .4, 0);
694         }
695
696         if (atype == bushtype && position[numobjects].y < terrain.getHeight(position[numobjects].x, position[numobjects].z) + 1) {
697             if (detail == 2)
698                 terrain.MakeDecal(shadowdecalpermanent, position[numobjects], 1, .4, 0);
699         }
700
701         if (atype != treeleavestype && atype != bushtype && atype != firetype)
702             terrain.AddObject(where + DoRotation(model[numobjects].boundingspherecenter, 0, ayaw, 0), model[numobjects].boundingsphereradius, numobjects);
703
704         numobjects++;
705     }
706 }
707
708 void Objects::DoStuff()
709 {
710     XYZ spawnpoint;
711     for (int i = 0; i < numobjects; i++) {
712         if (type[i] == firetype)
713             onfire[i] = 1;
714         if (onfire[i]) {
715             if (type[i] == bushtype)
716                 flamedelay[i] -= multiplier * 3;
717             if (type[i] == firetype)
718                 flamedelay[i] -= multiplier * 3;
719             if (type[i] == treeleavestype)
720                 flamedelay[i] -= multiplier * 4;
721             while (flamedelay[i] < 0 && onfire[i]) {
722                 flamedelay[i] += .006;
723                 if (type[i] == bushtype || type[i] == firetype) {
724                     spawnpoint.x = ((float)(Random() % 100)) / 30 * scale[i];
725                     spawnpoint.y = ((float)(Random() % 100) + 60) / 30 * scale[i];
726                     spawnpoint.z = 0;
727                     spawnpoint = DoRotation(spawnpoint, 0, Random() % 360, 0);
728                     spawnpoint += position[i];
729                     Sprite::MakeSprite(flamesprite, spawnpoint, spawnpoint * 0, 1, 1, 1, (.6 + (float)abs(Random() % 100) / 200 - .25) * 5 * scale[i], 1);
730                 }
731                 if (type[i] == treeleavestype) {
732                     spawnpoint.x = ((float)(Random() % 100)) / 80 * scale[i];
733                     spawnpoint.y = ((float)(Random() % 100) + 80) / 12 * scale[i];
734                     spawnpoint.z = 0;
735                     spawnpoint = DoRotation(spawnpoint, 0, Random() % 360, 0);
736                     spawnpoint += position[i];
737                     Sprite::MakeSprite(flamesprite, spawnpoint, spawnpoint * 0, 1, 1, 1, (.6 + (float)abs(Random() % 100) / 200 - .25) * 6, 1);
738                 }
739             }
740
741         }
742     }
743 }
744
745 void Objects::DoShadows()
746 {
747     int i, j, k, l;
748     static XYZ testpoint, testpoint2, terrainpoint, lightloc, col;
749     lightloc = light.location;
750     if (!skyboxtexture)
751         lightloc = 0;
752     lightloc.y += 10;
753     Normalise(&lightloc);
754     int patchx, patchz;
755
756     if (numobjects > 0)
757         for (i = 0; i < numobjects; i++) {
758             if (type[i] != treeleavestype && type[i] != treetrunktype && type[i] != bushtype && type[i] != firetype) {
759                 for (j = 0; j < model[i].vertexNum; j++) {
760                     terrainpoint = position[i] + DoRotation(model[i].vertex[j] + model[i].normals[j] * .1, 0, yaw[i], 0);
761                     //terrainpoint.y+=model[i].boundingsphereradius;
762                     shadowed[i] = 0;
763                     patchx = terrainpoint.x / (terrain.size / subdivision * terrain.scale);
764                     patchz = terrainpoint.z / (terrain.size / subdivision * terrain.scale);
765                     if (patchx >= 0 && patchz >= 0 && patchx < subdivision && patchz < subdivision)
766                         if (terrain.patchobjectnum[patchx][patchz])
767                             for (k = 0; k < terrain.patchobjectnum[patchx][patchz]; k++) {
768                                 l = terrain.patchobjects[patchx][patchz][k];
769                                 if (type[l] != treetrunktype/*&&l!=i*/) {
770                                     testpoint = terrainpoint;
771                                     testpoint2 = terrainpoint + lightloc * 50 * (1 - shadowed[i]);
772                                     if (model[l].LineCheck(&testpoint, &testpoint2, &col, &position[l], &yaw[l]) != -1) {
773                                         shadowed[i] = 1 - (findDistance(&terrainpoint, &col) / 50);
774                                     }
775                                 }
776                             }
777                     if (shadowed[i] > 0) {
778                         col = model[i].normals[j] - DoRotation(lightloc * shadowed[i], 0, -yaw[i], 0);
779                         Normalise(&col);
780                         for (k = 0; k < model[i].TriangleNum; k++) {
781                             if (model[i].Triangles[k].vertex[0] == j) {
782                                 l = k * 24;
783                                 model[i].vArray[l + 2] = col.x;
784                                 model[i].vArray[l + 3] = col.y;
785                                 model[i].vArray[l + 4] = col.z;
786                             }
787                             if (model[i].Triangles[k].vertex[1] == j) {
788                                 l = k * 24;
789                                 model[i].vArray[l + 10] = col.x;
790                                 model[i].vArray[l + 11] = col.y;
791                                 model[i].vArray[l + 12] = col.z;
792                             }
793                             if (model[i].Triangles[k].vertex[2] == j) {
794                                 l = k * 24;
795                                 model[i].vArray[l + 18] = col.x;
796                                 model[i].vArray[l + 19] = col.y;
797                                 model[i].vArray[l + 20] = col.z;
798                             }
799                         }
800                     }
801                 }
802             }
803             shadowed[i] = 0;
804         }
805 }
806
807 Objects::Objects()
808 {
809     center = 0;
810     radius = 0;
811     numobjects = 0;
812
813     memset(position, 0, sizeof(position));
814     memset(type, 0, sizeof(type));
815     memset(yaw, 0, sizeof(yaw));
816     memset(pitch, 0, sizeof(pitch));
817     memset(rotx, 0, sizeof(rotx));
818     memset(rotxvel, 0, sizeof(rotxvel));
819     memset(roty, 0, sizeof(roty));
820     memset(rotyvel, 0, sizeof(rotyvel));
821     memset(possible, 0, sizeof(possible));
822     memset(model, 0, sizeof(model));
823     memset(displaymodel, 0, sizeof(displaymodel));
824     memset(friction, 0, sizeof(friction));
825     memset(scale, 0, sizeof(scale));
826     memset(messedwith, 0, sizeof(messedwith));
827     memset(checked, 0, sizeof(checked));
828     memset(shadowed, 0, sizeof(shadowed));
829     memset(occluded, 0, sizeof(occluded));
830     memset(onfire, 0, sizeof(onfire));
831     memset(flamedelay, 0, sizeof(flamedelay));
832 }
833
834 Objects::~Objects()
835 {
836     boxtextureptr.destroy();
837     treetextureptr.destroy();
838     bushtextureptr.destroy();
839     rocktextureptr.destroy();
840 };
841