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