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