]> git.jsancho.org Git - lugaru.git/blob - Source/Models.cpp
License: Update GPLv2+ header to match current FSF recommendation
[lugaru.git] / Source / Models.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 "Game.h"
21 #include "Models.h"
22
23 extern float multiplier;
24 extern float viewdistance;
25 extern XYZ viewer;
26 extern float fadestart;
27 extern float texdetail;
28 extern bool decals;
29
30 extern bool visibleloading;
31
32 int Model::LineCheck(XYZ *p1, XYZ *p2, XYZ *p, XYZ *move, float *rotate)
33 {
34     static int j;
35     static float distance;
36     static float olddistance;
37     static int intersecting;
38     static int firstintersecting;
39     static XYZ point;
40
41     *p1 = *p1 - *move;
42     *p2 = *p2 - *move;
43     if (*rotate)
44         *p1 = DoRotation(*p1, 0, -*rotate, 0);
45     if (*rotate)
46         *p2 = DoRotation(*p2, 0, -*rotate, 0);
47     if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius))
48         return -1;
49     firstintersecting = -1;
50
51     for (j = 0; j < TriangleNum; j++) {
52         intersecting = LineFacetd(p1, p2, &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], &facenormals[j], &point);
53         distance = (point.x - p1->x) * (point.x - p1->x) + (point.y - p1->y) * (point.y - p1->y) + (point.z - p1->z) * (point.z - p1->z);
54         if ((distance < olddistance || firstintersecting == -1) && intersecting) {
55             olddistance = distance;
56             firstintersecting = j;
57             *p = point;
58         }
59     }
60
61     if (*rotate)
62         *p = DoRotation(*p, 0, *rotate, 0);
63     *p = *p + *move;
64     return firstintersecting;
65 }
66
67 int Model::LineCheckSlide(XYZ *p1, XYZ *p2, XYZ *p, XYZ *move, float *rotate)
68 {
69     static int j;
70     static float distance;
71     static float olddistance;
72     static int intersecting;
73     static int firstintersecting;
74     static XYZ point;
75
76     *p1 = *p1 - *move;
77     *p2 = *p2 - *move;
78     if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius))
79         return -1;
80     firstintersecting = -1;
81     if (*rotate)
82         *p1 = DoRotation(*p1, 0, -*rotate, 0);
83     if (*rotate)
84         *p2 = DoRotation(*p2, 0, -*rotate, 0);
85
86     for (j = 0; j < TriangleNum; j++) {
87         intersecting = LineFacetd(p1, p2, &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], &facenormals[j], &point);
88         distance = (point.x - p1->x) * (point.x - p1->x) + (point.y - p1->y) * (point.y - p1->y) + (point.z - p1->z) * (point.z - p1->z);
89         if ((distance < olddistance || firstintersecting == -1) && intersecting) {
90             olddistance = distance;
91             firstintersecting = j;
92         }
93     }
94
95     distance = abs((facenormals[firstintersecting].x * p2->x) + (facenormals[firstintersecting].y * p2->y) + (facenormals[firstintersecting].z * p2->z) - ((facenormals[firstintersecting].x * vertex[Triangles[firstintersecting].vertex[0]].x) + (facenormals[firstintersecting].y * vertex[Triangles[firstintersecting].vertex[0]].y) + (facenormals[firstintersecting].z * vertex[Triangles[firstintersecting].vertex[0]].z)));
96     *p2 -= facenormals[firstintersecting] * distance;
97
98     if (*rotate)
99         *p2 = DoRotation(*p2, 0, *rotate, 0);
100     *p2 = *p2 + *move;
101     return firstintersecting;
102 }
103
104 int Model::LineCheckPossible(XYZ *p1, XYZ *p2, XYZ *p, XYZ *move, float *rotate)
105 {
106     static int j;
107     static float distance;
108     static float olddistance;
109     static int intersecting;
110     static int firstintersecting;
111     static XYZ point;
112
113     *p1 = *p1 - *move;
114     *p2 = *p2 - *move;
115     if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius))
116         return -1;
117     firstintersecting = -1;
118     if (*rotate)
119         *p1 = DoRotation(*p1, 0, -*rotate, 0);
120     if (*rotate)
121         *p2 = DoRotation(*p2, 0, -*rotate, 0);
122
123     if (numpossible > 0 && numpossible < TriangleNum)
124         for (j = 0; j < numpossible; j++) {
125             if (possible[j] >= 0 && possible[j] < TriangleNum) {
126                 intersecting = LineFacetd(p1, p2, &vertex[Triangles[possible[j]].vertex[0]], &vertex[Triangles[possible[j]].vertex[1]], &vertex[Triangles[possible[j]].vertex[2]], &facenormals[possible[j]], &point);
127                 distance = (point.x - p1->x) * (point.x - p1->x) + (point.y - p1->y) * (point.y - p1->y) + (point.z - p1->z) * (point.z - p1->z);
128                 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
129                     olddistance = distance;
130                     firstintersecting = possible[j];
131                     *p = point;
132                 }
133             }
134         }
135
136     if (*rotate)
137         *p = DoRotation(*p, 0, *rotate, 0);
138     *p = *p + *move;
139     return firstintersecting;
140 }
141
142 int Model::LineCheckSlidePossible(XYZ *p1, XYZ *p2, XYZ *p, XYZ *move, float *rotate)
143 {
144     static int j;
145     static float distance;
146     static float olddistance;
147     static int intersecting;
148     static int firstintersecting;
149     static XYZ point;
150
151     *p1 = *p1 - *move;
152     *p2 = *p2 - *move;
153     if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius))
154         return -1;
155     firstintersecting = -1;
156     if (*rotate)
157         *p1 = DoRotation(*p1, 0, -*rotate, 0);
158     if (*rotate)
159         *p2 = DoRotation(*p2, 0, -*rotate, 0);
160
161     if (numpossible)
162         for (j = 0; j < numpossible; j++) {
163             if (possible[j] >= 0 && possible[j] < TriangleNum) {
164                 intersecting = LineFacetd(p1, p2, &vertex[Triangles[possible[j]].vertex[0]], &vertex[Triangles[possible[j]].vertex[1]], &vertex[Triangles[possible[j]].vertex[2]], &facenormals[possible[j]], &point);
165                 distance = (point.x - p1->x) * (point.x - p1->x) + (point.y - p1->y) * (point.y - p1->y) + (point.z - p1->z) * (point.z - p1->z);
166                 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
167                     olddistance = distance;
168                     firstintersecting = possible[j];
169                 }
170             }
171         }
172
173     if (firstintersecting > 0) {
174         distance = abs((facenormals[firstintersecting].x * p2->x) + (facenormals[firstintersecting].y * p2->y) + (facenormals[firstintersecting].z * p2->z) - ((facenormals[firstintersecting].x * vertex[Triangles[firstintersecting].vertex[0]].x) + (facenormals[firstintersecting].y * vertex[Triangles[firstintersecting].vertex[0]].y) + (facenormals[firstintersecting].z * vertex[Triangles[firstintersecting].vertex[0]].z)));
175         *p2 -= facenormals[firstintersecting] * distance;
176     }
177
178     if (*rotate)
179         *p2 = DoRotation(*p2, 0, *rotate, 0);
180     *p2 = *p2 + *move;
181     return firstintersecting;
182 }
183
184 int Model::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate)
185 {
186     static int i, j;
187     static float distance;
188     static float olddistance;
189     static int intersecting;
190     static int firstintersecting;
191     static XYZ point;
192     static XYZ oldp1;
193     static XYZ start, end;
194
195     firstintersecting = -1;
196
197     oldp1 = *p1;
198     *p1 = *p1 - *move;
199     if (*rotate)
200         *p1 = DoRotation(*p1, 0, -*rotate, 0);
201     if (distsq(p1, &boundingspherecenter) > radius * radius + boundingsphereradius * boundingsphereradius)
202         return -1;
203
204     for (i = 0; i < 4; i++) {
205         for (j = 0; j < TriangleNum; j++) {
206             intersecting = 0;
207             distance = abs((facenormals[j].x * p1->x) + (facenormals[j].y * p1->y) + (facenormals[j].z * p1->z) - ((facenormals[j].x * vertex[Triangles[j].vertex[0]].x) + (facenormals[j].y * vertex[Triangles[j].vertex[0]].y) + (facenormals[j].z * vertex[Triangles[j].vertex[0]].z)));
208             if (distance < radius) {
209                 point = *p1 - facenormals[j] * distance;
210                 if (PointInTriangle( &point, facenormals[j], &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]]))
211                     intersecting = 1;
212                 if (!intersecting)
213                     intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], p1, &radius);
214                 if (!intersecting)
215                     intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], p1, &radius);
216                 if (!intersecting)
217                     intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[2]], p1, &radius);
218                 if (intersecting) {
219                     *p1 += facenormals[j] * (distance - radius);
220                     /*start=*p1;
221                     end=*p1;
222                     end.y-=radius;
223                     if(LineFacetd(&start,&end,&vertex[Triangles[j].vertex[0]],&vertex[Triangles[j].vertex[1]],&vertex[Triangles[j].vertex[2]],&facenormals[j],&point)){
224                     p1->y=point.y+radius;
225                     }*/
226                 }
227             }
228             if ((distance < olddistance || firstintersecting == -1) && intersecting) {
229                 olddistance = distance;
230                 firstintersecting = j;
231                 *p = point;
232             }
233         }
234     }
235     if (*rotate)
236         *p = DoRotation(*p, 0, *rotate, 0);
237     *p = *p + *move;
238     if (*rotate)
239         *p1 = DoRotation(*p1, 0, *rotate, 0);
240     *p1 += *move;
241     return firstintersecting;
242 }
243
244 int Model::SphereCheckPossible(XYZ *p1, float radius, XYZ *move, float *rotate)
245 {
246     static int j;
247     static float distance;
248     static float olddistance;
249     static int intersecting;
250     static int firstintersecting;
251     static XYZ point;
252     static XYZ oldp1;
253     static XYZ start, end;
254
255     firstintersecting = -1;
256
257     oldp1 = *p1;
258     *p1 = *p1 - *move;
259
260     numpossible = 0;
261
262     if (*rotate)
263         *p1 = DoRotation(*p1, 0, -*rotate, 0);
264     if (distsq(p1, &boundingspherecenter) > radius * radius + boundingsphereradius * boundingsphereradius) {
265         *p1 = oldp1;
266         return -1;
267     }
268
269     for (j = 0; j < TriangleNum; j++) {
270         intersecting = 0;
271         distance = abs((facenormals[j].x * p1->x) + (facenormals[j].y * p1->y) + (facenormals[j].z * p1->z) - ((facenormals[j].x * vertex[Triangles[j].vertex[0]].x) + (facenormals[j].y * vertex[Triangles[j].vertex[0]].y) + (facenormals[j].z * vertex[Triangles[j].vertex[0]].z)));
272         if (distance < radius) {
273             point = *p1 - facenormals[j] * distance;
274             if (PointInTriangle( &point, facenormals[j], &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]]))
275                 intersecting = 1;
276             if (!intersecting)
277                 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], p1, &radius);
278             if (!intersecting)
279                 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], p1, &radius);
280             if (!intersecting)
281                 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[2]], p1, &radius);
282             if (intersecting) {
283                 //if(j>=0&&j<TriangleNum)
284                 possible[numpossible] = j;
285                 numpossible++;
286             }
287         }
288         if ((distance < olddistance || firstintersecting == -1) && intersecting) {
289             olddistance = distance;
290             firstintersecting = j;
291         }
292     }
293     if (*rotate)
294         *p1 = DoRotation(*p1, 0, *rotate, 0);
295     *p1 += *move;
296     return firstintersecting;
297 }
298
299
300 void Model::UpdateVertexArray()
301 {
302     if (type != normaltype && type != decalstype)
303         return;
304     static int i;
305     static int j;
306     if (!flat)
307         for (i = 0; i < TriangleNum; i++) {
308             j = i * 24;
309             vArray[j + 0] = Triangles[i].gx[0];
310             vArray[j + 1] = Triangles[i].gy[0];
311             vArray[j + 2] = normals[Triangles[i].vertex[0]].x;
312             vArray[j + 3] = normals[Triangles[i].vertex[0]].y;
313             vArray[j + 4] = normals[Triangles[i].vertex[0]].z;
314             vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
315             vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
316             vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
317
318             vArray[j + 8] = Triangles[i].gx[1];
319             vArray[j + 9] = Triangles[i].gy[1];
320             vArray[j + 10] = normals[Triangles[i].vertex[1]].x;
321             vArray[j + 11] = normals[Triangles[i].vertex[1]].y;
322             vArray[j + 12] = normals[Triangles[i].vertex[1]].z;
323             vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
324             vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
325             vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
326
327             vArray[j + 16] = Triangles[i].gx[2];
328             vArray[j + 17] = Triangles[i].gy[2];
329             vArray[j + 18] = normals[Triangles[i].vertex[2]].x;
330             vArray[j + 19] = normals[Triangles[i].vertex[2]].y;
331             vArray[j + 20] = normals[Triangles[i].vertex[2]].z;
332             vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
333             vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
334             vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
335         }
336     if (flat)
337         for (i = 0; i < TriangleNum; i++) {
338             j = i * 24;
339             vArray[j + 0] = Triangles[i].gx[0];
340             vArray[j + 1] = Triangles[i].gy[0];
341             vArray[j + 2] = facenormals[i].x * -1;
342             vArray[j + 3] = facenormals[i].y * -1;
343             vArray[j + 4] = facenormals[i].z * -1;
344             vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
345             vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
346             vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
347
348             vArray[j + 8] = Triangles[i].gx[1];
349             vArray[j + 9] = Triangles[i].gy[1];
350             vArray[j + 10] = facenormals[i].x * -1;
351             vArray[j + 11] = facenormals[i].y * -1;
352             vArray[j + 12] = facenormals[i].z * -1;
353             vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
354             vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
355             vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
356
357             vArray[j + 16] = Triangles[i].gx[2];
358             vArray[j + 17] = Triangles[i].gy[2];
359             vArray[j + 18] = facenormals[i].x * -1;
360             vArray[j + 19] = facenormals[i].y * -1;
361             vArray[j + 20] = facenormals[i].z * -1;
362             vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
363             vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
364             vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
365
366         }
367 }
368
369 void Model::UpdateVertexArrayNoTex()
370 {
371     if (type != normaltype && type != decalstype)
372         return;
373     static int i;
374     static int j;
375     if (!flat)
376         for (i = 0; i < TriangleNum; i++) {
377             j = i * 24;
378             vArray[j + 2] = normals[Triangles[i].vertex[0]].x;
379             vArray[j + 3] = normals[Triangles[i].vertex[0]].y;
380             vArray[j + 4] = normals[Triangles[i].vertex[0]].z;
381             vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
382             vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
383             vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
384
385             vArray[j + 10] = normals[Triangles[i].vertex[1]].x;
386             vArray[j + 11] = normals[Triangles[i].vertex[1]].y;
387             vArray[j + 12] = normals[Triangles[i].vertex[1]].z;
388             vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
389             vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
390             vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
391
392             vArray[j + 18] = normals[Triangles[i].vertex[2]].x;
393             vArray[j + 19] = normals[Triangles[i].vertex[2]].y;
394             vArray[j + 20] = normals[Triangles[i].vertex[2]].z;
395             vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
396             vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
397             vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
398         }
399     if (flat)
400         for (i = 0; i < TriangleNum; i++) {
401             j = i * 24;
402             vArray[j + 2] = facenormals[i].x * -1;
403             vArray[j + 3] = facenormals[i].y * -1;
404             vArray[j + 4] = facenormals[i].z * -1;
405             vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
406             vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
407             vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
408
409             vArray[j + 10] = facenormals[i].x * -1;
410             vArray[j + 11] = facenormals[i].y * -1;
411             vArray[j + 12] = facenormals[i].z * -1;
412             vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
413             vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
414             vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
415
416             vArray[j + 18] = facenormals[i].x * -1;
417             vArray[j + 19] = facenormals[i].y * -1;
418             vArray[j + 20] = facenormals[i].z * -1;
419             vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
420             vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
421             vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
422         }
423 }
424
425 void Model::UpdateVertexArrayNoTexNoNorm()
426 {
427     if (type != normaltype && type != decalstype)
428         return;
429     static int i;
430     static int j;
431     for (i = 0; i < TriangleNum; i++) {
432         j = i * 24;
433         vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
434         vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
435         vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
436
437         vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
438         vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
439         vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
440
441         vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
442         vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
443         vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
444     }
445 }
446
447 bool Model::loadnotex(const char *filename )
448 {
449     FILE *tfile;
450     long i;
451
452     //~ int oldvertexNum, oldTriangleNum;
453     //~ oldvertexNum = vertexNum;
454     //~ oldTriangleNum = TriangleNum;
455
456     type = notextype;
457     color = 0;
458
459     tfile = fopen( ConvertFileName(filename), "rb" );
460     // read model settings
461
462     fseek(tfile, 0, SEEK_SET);
463     funpackf(tfile, "Bs Bs", &vertexNum, &TriangleNum);
464
465     // read the model data
466     deallocate();
467
468     numpossible = 0;
469
470     owner = (int*)malloc(sizeof(int) * vertexNum);
471     possible = (int*)malloc(sizeof(int) * TriangleNum);
472     vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
473     Triangles = (TexturedTriangle*)malloc(sizeof(TexturedTriangle) * TriangleNum);
474     vArray = (GLfloat*)malloc(sizeof(GLfloat) * TriangleNum * 24);
475
476     for (i = 0; i < vertexNum; i++) {
477         funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
478     }
479
480     for (i = 0; i < TriangleNum; i++) {
481         //funpackf(tfile, "Bi Bi Bi", &Triangles[i].vertex[0], &Triangles[i].vertex[1], &Triangles[i].vertex[2]);
482         short vertex[ 6];
483         funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[ 0], &vertex[ 1], &vertex[ 2], &vertex[ 3], &vertex[ 4], &vertex[ 5]);
484         Triangles[i].vertex[ 0] = vertex[ 0];
485         Triangles[i].vertex[ 1] = vertex[ 2];
486         Triangles[i].vertex[ 2] = vertex[ 4];
487         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
488         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
489     }
490
491     fclose(tfile);
492
493     UpdateVertexArray();
494
495     for (i = 0; i < vertexNum; i++) {
496         owner[i] = -1;
497     }
498
499     static int j;
500     boundingsphereradius = 0;
501     for (i = 0; i < vertexNum; i++) {
502         for (j = 0; j < vertexNum; j++) {
503             if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
504                 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
505                 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
506             }
507         }
508     }
509     boundingsphereradius = fast_sqrt(boundingsphereradius);
510
511     return 1;
512 }
513
514
515 bool Model::load(const char *filename, bool texture )
516 {
517     FILE *tfile;
518     long i;
519
520     LOGFUNC;
521
522     LOG(std::string("Loading model...") + filename);
523
524     if (visibleloading)
525         Game::LoadingScreen();
526
527     //~ int oldvertexNum, oldTriangleNum;
528     //~ oldvertexNum = vertexNum;
529     //~ oldTriangleNum = TriangleNum;
530
531     type = normaltype;
532     color = 0;
533
534     tfile = fopen( ConvertFileName(filename), "rb" );
535     // read model settings
536
537
538     fseek(tfile, 0, SEEK_SET);
539     funpackf(tfile, "Bs Bs", &vertexNum, &TriangleNum);
540
541     // read the model data
542     deallocate();
543
544     numpossible = 0;
545
546     owner = (int*)malloc(sizeof(int) * vertexNum);
547     possible = (int*)malloc(sizeof(int) * TriangleNum);
548     vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
549     normals = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
550     facenormals = (XYZ*)malloc(sizeof(XYZ) * TriangleNum);
551     Triangles = (TexturedTriangle*)malloc(sizeof(TexturedTriangle) * TriangleNum);
552     vArray = (GLfloat*)malloc(sizeof(GLfloat) * TriangleNum * 24);
553
554     for (i = 0; i < vertexNum; i++) {
555         funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
556     }
557
558     for (i = 0; i < TriangleNum; i++) {
559         //funpackf(tfile, "Bi Bi Bi", &Triangles[i].vertex[0], &Triangles[i].vertex[1], &Triangles[i].vertex[2]);
560         short vertex[ 6];
561         funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[ 0], &vertex[ 1], &vertex[ 2], &vertex[ 3], &vertex[ 4], &vertex[ 5]);
562         Triangles[i].vertex[ 0] = vertex[ 0];
563         Triangles[i].vertex[ 1] = vertex[ 2];
564         Triangles[i].vertex[ 2] = vertex[ 4];
565         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
566         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
567     }
568
569     modelTexture.xsz = 0;
570
571     fclose(tfile);
572
573     UpdateVertexArray();
574
575     for (i = 0; i < vertexNum; i++) {
576         owner[i] = -1;
577     }
578
579     static int j;
580     boundingsphereradius = 0;
581     for (i = 0; i < vertexNum; i++) {
582         for (j = 0; j < vertexNum; j++) {
583             if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
584                 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
585                 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
586             }
587         }
588     }
589     boundingsphereradius = fast_sqrt(boundingsphereradius);
590
591     return 1;
592 }
593
594 bool Model::loaddecal(const char *filename, bool texture )
595 {
596     FILE *tfile;
597     long i, j;
598
599     LOGFUNC;
600
601     // Changing the filename so that its more os specific
602     char * FixedFN = ConvertFileName(filename);
603
604     LOG(std::string("Loading decal...") + FixedFN);
605
606     //~ int oldvertexNum, oldTriangleNum;
607     //~ oldvertexNum = vertexNum;
608     //~ oldTriangleNum = TriangleNum;
609
610     type = decalstype;
611     numdecals = 0;
612     color = 0;
613
614     tfile = fopen( FixedFN, "rb" );
615     // read model settings
616
617
618     fseek(tfile, 0, SEEK_SET);
619     funpackf(tfile, "Bs Bs", &vertexNum, &TriangleNum);
620
621     // read the model data
622
623     deallocate();
624
625     numpossible = 0;
626
627     owner = (int*)malloc(sizeof(int) * vertexNum);
628     possible = (int*)malloc(sizeof(int) * TriangleNum);
629     vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
630     normals = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
631     facenormals = (XYZ*)malloc(sizeof(XYZ) * TriangleNum);
632     Triangles = (TexturedTriangle*)malloc(sizeof(TexturedTriangle) * TriangleNum);
633     vArray = (GLfloat*)malloc(sizeof(GLfloat) * TriangleNum * 24);
634
635
636     for (i = 0; i < vertexNum; i++) {
637         funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
638     }
639
640     for (i = 0; i < TriangleNum; i++) {
641         //funpackf(tfile, "Bi Bi Bi", &Triangles[i].vertex[0], &Triangles[i].vertex[1], &Triangles[i].vertex[2]);
642         short vertex[ 6];
643         funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[ 0], &vertex[ 1], &vertex[ 2], &vertex[ 3], &vertex[ 4], &vertex[ 5]);
644         Triangles[i].vertex[ 0] = vertex[ 0];
645         Triangles[i].vertex[ 1] = vertex[ 2];
646         Triangles[i].vertex[ 2] = vertex[ 4];
647         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
648         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
649     }
650
651
652     modelTexture.xsz = 0;
653
654     fclose(tfile);
655
656     UpdateVertexArray();
657
658     for (i = 0; i < vertexNum; i++) {
659         owner[i] = -1;
660     }
661
662     boundingsphereradius = 0;
663     for (i = 0; i < vertexNum; i++) {
664         for (j = 0; j < vertexNum; j++) {
665             if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
666                 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
667                 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
668             }
669         }
670     }
671     boundingsphereradius = fast_sqrt(boundingsphereradius);
672
673     //allow decals
674     if (!decaltexcoords) {
675         decaltexcoords = (float***)malloc(sizeof(float**)*max_model_decals);
676         for (i = 0; i < max_model_decals; i++) {
677             decaltexcoords[i] = (float**)malloc(sizeof(float*) * 3);
678             for (j = 0; j < 3; j++) {
679                 decaltexcoords[i][j] = (float*)malloc(sizeof(float) * 2);
680             }
681         }
682         //if(decalvertex)free(decalvertex);
683         decalvertex = (XYZ**)malloc(sizeof(XYZ*)*max_model_decals);
684         for (i = 0; i < max_model_decals; i++) {
685             decalvertex[i] = (XYZ*)malloc(sizeof(XYZ) * 3);
686         }
687
688         decaltype = (int*)malloc(sizeof(int) * max_model_decals);
689         decalopacity = (float*)malloc(sizeof(float) * max_model_decals);
690         decalrotation = (float*)malloc(sizeof(float) * max_model_decals);
691         decalalivetime = (float*)malloc(sizeof(float) * max_model_decals);
692         decalposition = (XYZ*)malloc(sizeof(XYZ) * max_model_decals);
693     }
694
695     return 1;
696 }
697
698 bool Model::loadraw(char *filename )
699 {
700     FILE *tfile;
701     long i;
702
703     LOGFUNC;
704
705     LOG(std::string("Loading raw...") + filename);
706
707     //~ int oldvertexNum, oldTriangleNum;
708     //~ oldvertexNum = vertexNum;
709     //~ oldTriangleNum = TriangleNum;
710
711     type = rawtype;
712     color = 0;
713
714     tfile = fopen( ConvertFileName(filename), "rb" );
715     // read model settings
716
717
718     fseek(tfile, 0, SEEK_SET);
719     funpackf(tfile, "Bs Bs", &vertexNum, &TriangleNum);
720
721     // read the model data
722     deallocate();
723
724     numpossible = 0;
725
726     owner = (int*)malloc(sizeof(int) * vertexNum);
727     possible = (int*)malloc(sizeof(int) * TriangleNum);
728     vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
729     Triangles = (TexturedTriangle*)malloc(sizeof(TexturedTriangle) * TriangleNum);
730     vArray = (GLfloat*)malloc(sizeof(GLfloat) * TriangleNum * 24);
731
732
733     for (i = 0; i < vertexNum; i++) {
734         funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
735     }
736
737     for (i = 0; i < TriangleNum; i++) {
738         //funpackf(tfile, "Bi Bi Bi", &Triangles[i].vertex[0], &Triangles[i].vertex[1], &Triangles[i].vertex[2]);
739         short vertex[ 6];
740         funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[ 0], &vertex[ 1], &vertex[ 2], &vertex[ 3], &vertex[ 4], &vertex[ 5]);
741         Triangles[i].vertex[ 0] = vertex[ 0];
742         Triangles[i].vertex[ 1] = vertex[ 2];
743         Triangles[i].vertex[ 2] = vertex[ 4];
744         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
745         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
746     }
747
748
749     fclose(tfile);
750
751     for (i = 0; i < vertexNum; i++) {
752         owner[i] = -1;
753     }
754
755     return 1;
756 }
757
758
759 void Model::UniformTexCoords()
760 {
761     static int i;
762     for (i = 0; i < TriangleNum; i++) {
763         Triangles[i].gy[0] = vertex[Triangles[i].vertex[0]].y;
764         Triangles[i].gy[1] = vertex[Triangles[i].vertex[1]].y;
765         Triangles[i].gy[2] = vertex[Triangles[i].vertex[2]].y;
766         Triangles[i].gx[0] = vertex[Triangles[i].vertex[0]].x;
767         Triangles[i].gx[1] = vertex[Triangles[i].vertex[1]].x;
768         Triangles[i].gx[2] = vertex[Triangles[i].vertex[2]].x;
769     }
770     UpdateVertexArray();
771 }
772
773
774 void Model::FlipTexCoords()
775 {
776     static int i;
777     for (i = 0; i < TriangleNum; i++) {
778         Triangles[i].gy[0] = -Triangles[i].gy[0];
779         Triangles[i].gy[1] = -Triangles[i].gy[1];
780         Triangles[i].gy[2] = -Triangles[i].gy[2];
781     }
782     UpdateVertexArray();
783 }
784
785 void Model::ScaleTexCoords(float howmuch)
786 {
787     static int i;
788     for (i = 0; i < TriangleNum; i++) {
789         Triangles[i].gx[0] *= howmuch;
790         Triangles[i].gx[1] *= howmuch;
791         Triangles[i].gx[2] *= howmuch;
792         Triangles[i].gy[0] *= howmuch;
793         Triangles[i].gy[1] *= howmuch;
794         Triangles[i].gy[2] *= howmuch;
795     }
796     UpdateVertexArray();
797 }
798
799 void Model::Scale(float xscale, float yscale, float zscale)
800 {
801     static int i;
802     for (i = 0; i < vertexNum; i++) {
803         vertex[i].x *= xscale;
804         vertex[i].y *= yscale;
805         vertex[i].z *= zscale;
806     }
807     UpdateVertexArray();
808
809     static int j;
810
811     boundingsphereradius = 0;
812     for (i = 0; i < vertexNum; i++) {
813         for (j = 0; j < vertexNum; j++) {
814             if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
815                 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
816                 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
817             }
818         }
819     }
820     boundingsphereradius = fast_sqrt(boundingsphereradius);
821 }
822
823 void Model::ScaleNormals(float xscale, float yscale, float zscale)
824 {
825     if (type != normaltype && type != decalstype)
826         return;
827     static int i;
828     for (i = 0; i < vertexNum; i++) {
829         normals[i].x *= xscale;
830         normals[i].y *= yscale;
831         normals[i].z *= zscale;
832     }
833     for (i = 0; i < TriangleNum; i++) {
834         facenormals[i].x *= xscale;
835         facenormals[i].y *= yscale;
836         facenormals[i].z *= zscale;
837     }
838     UpdateVertexArray();
839 }
840
841 void Model::Translate(float xtrans, float ytrans, float ztrans)
842 {
843     static int i;
844     for (i = 0; i < vertexNum; i++) {
845         vertex[i].x += xtrans;
846         vertex[i].y += ytrans;
847         vertex[i].z += ztrans;
848     }
849     UpdateVertexArray();
850
851     static int j;
852     boundingsphereradius = 0;
853     for (i = 0; i < vertexNum; i++) {
854         for (j = 0; j < vertexNum; j++) {
855             if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
856                 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
857                 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
858             }
859         }
860     }
861     boundingsphereradius = fast_sqrt(boundingsphereradius);
862 }
863
864 void Model::Rotate(float xang, float yang, float zang)
865 {
866     static int i;
867     for (i = 0; i < vertexNum; i++) {
868         vertex[i] = DoRotation(vertex[i], xang, yang, zang);
869     }
870     UpdateVertexArray();
871
872     static int j;
873     boundingsphereradius = 0;
874     for (i = 0; i < vertexNum; i++) {
875         for (j = 0; j < vertexNum; j++) {
876             if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
877                 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
878                 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
879             }
880         }
881     }
882     boundingsphereradius = fast_sqrt(boundingsphereradius);
883 }
884
885
886 void Model::CalculateNormals(bool facenormalise)
887 {
888     if (visibleloading)
889         Game::LoadingScreen();
890     static int i;
891     if (type != normaltype && type != decalstype)
892         return;
893
894     for (i = 0; i < vertexNum; i++) {
895         normals[i].x = 0;
896         normals[i].y = 0;
897         normals[i].z = 0;
898     }
899
900     for (i = 0; i < TriangleNum; i++) {
901         CrossProduct(vertex[Triangles[i].vertex[1]] - vertex[Triangles[i].vertex[0]], vertex[Triangles[i].vertex[2]] - vertex[Triangles[i].vertex[0]], &facenormals[i]);
902
903         normals[Triangles[i].vertex[0]].x += facenormals[i].x;
904         normals[Triangles[i].vertex[0]].y += facenormals[i].y;
905         normals[Triangles[i].vertex[0]].z += facenormals[i].z;
906
907         normals[Triangles[i].vertex[1]].x += facenormals[i].x;
908         normals[Triangles[i].vertex[1]].y += facenormals[i].y;
909         normals[Triangles[i].vertex[1]].z += facenormals[i].z;
910
911         normals[Triangles[i].vertex[2]].x += facenormals[i].x;
912         normals[Triangles[i].vertex[2]].y += facenormals[i].y;
913         normals[Triangles[i].vertex[2]].z += facenormals[i].z;
914         if (facenormalise)
915             Normalise(&facenormals[i]);
916     }
917     for (i = 0; i < vertexNum; i++) {
918         Normalise(&normals[i]);
919         normals[i] *= -1;
920     }
921     UpdateVertexArrayNoTex();
922 }
923
924 void Model::drawimmediate()
925 {
926     textureptr.bind();
927     glBegin(GL_TRIANGLES);
928     for (int i = 0; i < TriangleNum; i++) {
929         /*if(Triangles[i].vertex[0]<vertexNum&&Triangles[i].vertex[1]<vertexNum&&Triangles[i].vertex[2]<vertexNum&&Triangles[i].vertex[0]>=0&&Triangles[i].vertex[1]>=0&&Triangles[i].vertex[2]>=0){
930         if(isnormal(vertex[Triangles[i].vertex[0]].x)&&isnormal(vertex[Triangles[i].vertex[0]].y)&&isnormal(vertex[Triangles[i].vertex[0]].z)
931         &&isnormal(vertex[Triangles[i].vertex[1]].x)&&isnormal(vertex[Triangles[i].vertex[1]].y)&&isnormal(vertex[Triangles[i].vertex[1]].z)
932         &&isnormal(vertex[Triangles[i].vertex[2]].x)&&isnormal(vertex[Triangles[i].vertex[2]].y)&&isnormal(vertex[Triangles[i].vertex[2]].z)){
933         */
934         glTexCoord2f(Triangles[i].gx[0], Triangles[i].gy[0]);
935         if (color)
936             glColor3f(normals[Triangles[i].vertex[0]].x, normals[Triangles[i].vertex[0]].y, normals[Triangles[i].vertex[0]].z);
937         if (!color && !flat)
938             glNormal3f(normals[Triangles[i].vertex[0]].x, normals[Triangles[i].vertex[0]].y, normals[Triangles[i].vertex[0]].z);
939         if (!color && flat)
940             glNormal3f(facenormals[i].x, facenormals[i].y, facenormals[i].y);
941         glVertex3f(vertex[Triangles[i].vertex[0]].x, vertex[Triangles[i].vertex[0]].y, vertex[Triangles[i].vertex[0]].z);
942
943         glTexCoord2f(Triangles[i].gx[1], Triangles[i].gy[1]);
944         if (color)
945             glColor3f(normals[Triangles[i].vertex[1]].x, normals[Triangles[i].vertex[1]].y, normals[Triangles[i].vertex[1]].z);
946         if (!color && !flat)
947             glNormal3f(normals[Triangles[i].vertex[1]].x, normals[Triangles[i].vertex[1]].y, normals[Triangles[i].vertex[1]].z);
948         if (!color && flat)
949             glNormal3f(facenormals[i].x, facenormals[i].y, facenormals[i].y);
950         glVertex3f(vertex[Triangles[i].vertex[1]].x, vertex[Triangles[i].vertex[1]].y, vertex[Triangles[i].vertex[1]].z);
951
952         glTexCoord2f(Triangles[i].gx[2], Triangles[i].gy[2]);
953         if (color)
954             glColor3f(normals[Triangles[i].vertex[2]].x, normals[Triangles[i].vertex[2]].y, normals[Triangles[i].vertex[2]].z);
955         if (!color && !flat)
956             glNormal3f(normals[Triangles[i].vertex[2]].x, normals[Triangles[i].vertex[2]].y, normals[Triangles[i].vertex[2]].z);
957         if (!color && flat)
958             glNormal3f(facenormals[i].x, facenormals[i].y, facenormals[i].y);
959         glVertex3f(vertex[Triangles[i].vertex[2]].x, vertex[Triangles[i].vertex[2]].y, vertex[Triangles[i].vertex[2]].z);
960         //}
961         //}
962     }
963     glEnd();
964 }
965
966 void Model::draw()
967 {
968     if (type != normaltype && type != decalstype)
969         return;
970
971     glEnableClientState(GL_NORMAL_ARRAY);
972     glEnableClientState(GL_VERTEX_ARRAY);
973     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
974
975     if (!color)
976         glInterleavedArrays( GL_T2F_N3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
977     if (color)
978         glInterleavedArrays( GL_T2F_C3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
979     textureptr.bind();
980
981 #if PLATFORM_MACOSX
982     glLockArraysEXT( 0, TriangleNum * 3);
983 #endif
984     glDrawArrays(GL_TRIANGLES, 0, TriangleNum * 3);
985 #if PLATFORM_MACOSX
986     glUnlockArraysEXT();
987 #endif
988
989
990     if (!color)
991         glDisableClientState(GL_NORMAL_ARRAY);
992     if (color)
993         glDisableClientState(GL_COLOR_ARRAY);
994     glDisableClientState(GL_VERTEX_ARRAY);
995     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
996     //drawimmediate();
997 }
998
999 //TODO: phase out in favor of Texture
1000 void Model::drawdifftex(GLuint texture)
1001 {
1002     glEnableClientState(GL_NORMAL_ARRAY);
1003     glEnableClientState(GL_VERTEX_ARRAY);
1004     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1005     if (!color)
1006         glInterleavedArrays( GL_T2F_N3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
1007     if (color)
1008         glInterleavedArrays( GL_T2F_C3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
1009
1010     glBindTexture(GL_TEXTURE_2D, (unsigned long)texture);
1011     glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
1012     glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
1013
1014
1015 #ifndef WIN32
1016     glLockArraysEXT( 0, TriangleNum * 3);
1017 #endif
1018     glDrawArrays(GL_TRIANGLES, 0, TriangleNum * 3);
1019 #ifndef WIN32
1020     glUnlockArraysEXT();
1021 #endif
1022
1023
1024     if (!color)
1025         glDisableClientState(GL_NORMAL_ARRAY);
1026     if (color)
1027         glDisableClientState(GL_COLOR_ARRAY);
1028     glDisableClientState(GL_VERTEX_ARRAY);
1029     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1030     //drawdiffteximmediate(texture);
1031 }
1032
1033 void Model::drawdifftex(Texture texture)
1034 {
1035     glEnableClientState(GL_NORMAL_ARRAY);
1036     glEnableClientState(GL_VERTEX_ARRAY);
1037     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1038     if (!color)
1039         glInterleavedArrays( GL_T2F_N3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
1040     if (color)
1041         glInterleavedArrays( GL_T2F_C3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
1042
1043     texture.bind();
1044     glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
1045     glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
1046
1047
1048 #ifndef WIN32
1049     glLockArraysEXT( 0, TriangleNum * 3);
1050 #endif
1051     glDrawArrays(GL_TRIANGLES, 0, TriangleNum * 3);
1052 #ifndef WIN32
1053     glUnlockArraysEXT();
1054 #endif
1055
1056
1057     if (!color)
1058         glDisableClientState(GL_NORMAL_ARRAY);
1059     if (color)
1060         glDisableClientState(GL_COLOR_ARRAY);
1061     glDisableClientState(GL_VERTEX_ARRAY);
1062     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1063     //drawdiffteximmediate(texture);
1064 }
1065
1066 void Model::drawdiffteximmediate(GLuint texture)
1067 {
1068     glBindTexture(GL_TEXTURE_2D, (unsigned long)texture);
1069
1070     glBegin(GL_TRIANGLES);
1071     for (int i = 0; i < TriangleNum; i++) {
1072         /*if(Triangles[i].vertex[0]<vertexNum&&Triangles[i].vertex[1]<vertexNum&&Triangles[i].vertex[2]<vertexNum&&Triangles[i].vertex[0]>=0&&Triangles[i].vertex[1]>=0&&Triangles[i].vertex[2]>=0){
1073         if(isnormal(vertex[Triangles[i].vertex[0]].x)&&isnormal(vertex[Triangles[i].vertex[0]].y)&&isnormal(vertex[Triangles[i].vertex[0]].z)
1074         &&isnormal(vertex[Triangles[i].vertex[1]].x)&&isnormal(vertex[Triangles[i].vertex[1]].y)&&isnormal(vertex[Triangles[i].vertex[1]].z)
1075         &&isnormal(vertex[Triangles[i].vertex[2]].x)&&isnormal(vertex[Triangles[i].vertex[2]].y)&&isnormal(vertex[Triangles[i].vertex[2]].z)){
1076         */glTexCoord2f(Triangles[i].gx[0], Triangles[i].gy[0]);
1077         if (color)
1078             glColor3f(normals[Triangles[i].vertex[0]].x, normals[Triangles[i].vertex[0]].y, normals[Triangles[i].vertex[0]].z);
1079         if (!color && !flat)
1080             glNormal3f(normals[Triangles[i].vertex[0]].x, normals[Triangles[i].vertex[0]].y, normals[Triangles[i].vertex[0]].z);
1081         if (!color && flat)
1082             glNormal3f(facenormals[i].x, facenormals[i].y, facenormals[i].y);
1083         glVertex3f(vertex[Triangles[i].vertex[0]].x, vertex[Triangles[i].vertex[0]].y, vertex[Triangles[i].vertex[0]].z);
1084
1085         glTexCoord2f(Triangles[i].gx[1], Triangles[i].gy[1]);
1086         if (color)
1087             glColor3f(normals[Triangles[i].vertex[1]].x, normals[Triangles[i].vertex[1]].y, normals[Triangles[i].vertex[1]].z);
1088         if (!color && !flat)
1089             glNormal3f(normals[Triangles[i].vertex[1]].x, normals[Triangles[i].vertex[1]].y, normals[Triangles[i].vertex[1]].z);
1090         if (!color && flat)
1091             glNormal3f(facenormals[i].x, facenormals[i].y, facenormals[i].y);
1092         glVertex3f(vertex[Triangles[i].vertex[1]].x, vertex[Triangles[i].vertex[1]].y, vertex[Triangles[i].vertex[1]].z);
1093
1094         glTexCoord2f(Triangles[i].gx[2], Triangles[i].gy[2]);
1095         if (color)
1096             glColor3f(normals[Triangles[i].vertex[2]].x, normals[Triangles[i].vertex[2]].y, normals[Triangles[i].vertex[2]].z);
1097         if (!color && !flat)
1098             glNormal3f(normals[Triangles[i].vertex[2]].x, normals[Triangles[i].vertex[2]].y, normals[Triangles[i].vertex[2]].z);
1099         if (!color && flat)
1100             glNormal3f(facenormals[i].x, facenormals[i].y, facenormals[i].y);
1101         glVertex3f(vertex[Triangles[i].vertex[2]].x, vertex[Triangles[i].vertex[2]].y, vertex[Triangles[i].vertex[2]].z);
1102         //}
1103         //}
1104     }
1105     glEnd();
1106 }
1107
1108 void Model::drawdecals(Texture shadowtexture, Texture bloodtexture, Texture bloodtexture2, Texture breaktexture)
1109 {
1110     if (decals) {
1111         if (type != decalstype)
1112             return;
1113         static int i;
1114         //~ static float distancemult;
1115         static int lasttype;
1116         //~ static float viewdistsquared;
1117         static bool blend;
1118
1119         //~ viewdistsquared = viewdistance * viewdistance;
1120         blend = 1;
1121
1122         lasttype = -1;
1123         glEnable(GL_BLEND);
1124         glDisable(GL_LIGHTING);
1125         glDisable(GL_CULL_FACE);
1126         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1127         glDepthMask(0);
1128         if (numdecals > max_model_decals)
1129             numdecals = max_model_decals;
1130         for (i = 0; i < numdecals; i++) {
1131             if (decaltype[i] == blooddecalfast && decalalivetime[i] < 2)
1132                 decalalivetime[i] = 2;
1133
1134             if (decaltype[i] == shadowdecal && decaltype[i] != lasttype) {
1135                 shadowtexture.bind();
1136                 if (!blend) {
1137                     blend = 1;
1138                     glAlphaFunc(GL_GREATER, 0.0001);
1139                     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1140                 }
1141             }
1142             if (decaltype[i] == breakdecal && decaltype[i] != lasttype) {
1143                 breaktexture.bind();
1144                 if (!blend) {
1145                     blend = 1;
1146                     glAlphaFunc(GL_GREATER, 0.0001);
1147                     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1148                 }
1149             }
1150             if ((decaltype[i] == blooddecal || decaltype[i] == blooddecalslow) && decaltype[i] != lasttype) {
1151                 bloodtexture.bind();
1152                 if (blend) {
1153                     blend = 0;
1154                     glAlphaFunc(GL_GREATER, 0.15);
1155                     glBlendFunc(GL_ONE, GL_ZERO);
1156                 }
1157             }
1158             if ((decaltype[i] == blooddecalfast) && decaltype[i] != lasttype) {
1159                 bloodtexture2.bind();
1160                 if (blend) {
1161                     blend = 0;
1162                     glAlphaFunc(GL_GREATER, 0.15);
1163                     glBlendFunc(GL_ONE, GL_ZERO);
1164                 }
1165             }
1166             if (decaltype[i] == shadowdecal) {
1167                 glColor4f(1, 1, 1, decalopacity[i]);
1168             }
1169             if (decaltype[i] == breakdecal) {
1170                 glColor4f(1, 1, 1, decalopacity[i]);
1171                 if (decalalivetime[i] > 58)
1172                     glColor4f(1, 1, 1, decalopacity[i] * (60 - decalalivetime[i]) / 2);
1173             }
1174             if ((decaltype[i] == blooddecal || decaltype[i] == blooddecalfast || decaltype[i] == blooddecalslow)) {
1175                 glColor4f(1, 1, 1, decalopacity[i]);
1176                 if (decalalivetime[i] < 4)
1177                     glColor4f(1, 1, 1, decalopacity[i]*decalalivetime[i]*.25);
1178                 if (decalalivetime[i] > 58)
1179                     glColor4f(1, 1, 1, decalopacity[i] * (60 - decalalivetime[i]) / 2);
1180             }
1181             lasttype = decaltype[i];
1182             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1183             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1184
1185             glMatrixMode(GL_MODELVIEW);
1186             glPushMatrix();
1187             glBegin(GL_TRIANGLES);
1188             for (int j = 0; j < 3; j++) {
1189                 glTexCoord2f(decaltexcoords[i][j][0], decaltexcoords[i][j][1]);
1190                 glVertex3f(decalvertex[i][j].x, decalvertex[i][j].y, decalvertex[i][j].z);
1191             }
1192             glEnd();
1193             glPopMatrix();
1194         }
1195         for (i = numdecals - 1; i >= 0; i--) {
1196             decalalivetime[i] += multiplier;
1197             if (decaltype[i] == blooddecalslow)
1198                 decalalivetime[i] -= multiplier * 2 / 3;
1199             if (decaltype[i] == blooddecalfast)
1200                 decalalivetime[i] += multiplier * 4;
1201             if (decaltype[i] == shadowdecal)
1202                 DeleteDecal(i);
1203             if ((decaltype[i] == blooddecal || decaltype[i] == blooddecalfast || decaltype[i] == blooddecalslow) && decalalivetime[i] >= 60)
1204                 DeleteDecal(i);
1205         }
1206         glAlphaFunc(GL_GREATER, 0.0001);
1207         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1208     }
1209 }
1210
1211 void Model::DeleteDecal(int which)
1212 {
1213     if (decals) {
1214         if (type != decalstype)
1215             return;
1216         decaltype[which] = decaltype[numdecals - 1];
1217         decalposition[which] = decalposition[numdecals - 1];
1218         for (int i = 0; i < 3; i++) {
1219             decalvertex[which][i] = decalvertex[numdecals - 1][i];
1220             decaltexcoords[which][i][0] = decaltexcoords[numdecals - 1][i][0];
1221             decaltexcoords[which][i][1] = decaltexcoords[numdecals - 1][i][1];
1222         }
1223         decalrotation[which] = decalrotation[numdecals - 1];
1224         decalalivetime[which] = decalalivetime[numdecals - 1];
1225         decalopacity[which] = decalopacity[numdecals - 1];
1226         numdecals--;
1227     }
1228 }
1229
1230 void Model::MakeDecal(int atype, XYZ *where, float *size, float *opacity, float *rotation)
1231 {
1232     if (decals) {
1233         if (type != decalstype)
1234             return;
1235
1236         static float placex, placez;
1237         static XYZ rot;
1238         //static XYZ point,point1,point2;
1239         static float distance;
1240         static int i, j;
1241
1242         if (*opacity > 0)
1243             if (distsq(where, &boundingspherecenter) < (boundingsphereradius + *size) * (boundingsphereradius + *size))
1244                 for (i = 0; i < TriangleNum; i++) {
1245                     if (facenormals[i].y < -.1 && (vertex[Triangles[i].vertex[0]].y < where->y || vertex[Triangles[i].vertex[1]].y < where->y || vertex[Triangles[i].vertex[2]].y < where->y)) {
1246                         decalposition[numdecals] = *where;
1247                         decaltype[numdecals] = atype;
1248                         decalrotation[numdecals] = *rotation;
1249                         decalalivetime[numdecals] = 0;
1250                         distance = abs(((facenormals[i].x * where->x) + (facenormals[i].y * where->y) + (facenormals[i].z * where->z) - ((facenormals[i].x * vertex[Triangles[i].vertex[0]].x) + (facenormals[i].y * vertex[Triangles[i].vertex[0]].y) + (facenormals[i].z * vertex[Triangles[i].vertex[0]].z))) / facenormals[i].y);
1251                         decalopacity[numdecals] = *opacity - distance / 10;
1252
1253                         if (decalopacity[numdecals > 0]) {
1254                             placex = vertex[Triangles[i].vertex[0]].x;
1255                             placez = vertex[Triangles[i].vertex[0]].z;
1256
1257                             decaltexcoords[numdecals][0][0] = (placex - where->x) / (*size) / 2 + .5;
1258                             decaltexcoords[numdecals][0][1] = (placez - where->z) / (*size) / 2 + .5;
1259
1260                             decalvertex[numdecals][0].x = placex;
1261                             decalvertex[numdecals][0].z = placez;
1262                             decalvertex[numdecals][0].y = vertex[Triangles[i].vertex[0]].y;
1263
1264
1265                             placex = vertex[Triangles[i].vertex[1]].x;
1266                             placez = vertex[Triangles[i].vertex[1]].z;
1267
1268                             decaltexcoords[numdecals][1][0] = (placex - where->x) / (*size) / 2 + .5;
1269                             decaltexcoords[numdecals][1][1] = (placez - where->z) / (*size) / 2 + .5;
1270
1271                             decalvertex[numdecals][1].x = placex;
1272                             decalvertex[numdecals][1].z = placez;
1273                             decalvertex[numdecals][1].y = vertex[Triangles[i].vertex[1]].y;
1274
1275
1276                             placex = vertex[Triangles[i].vertex[2]].x;
1277                             placez = vertex[Triangles[i].vertex[2]].z;
1278
1279                             decaltexcoords[numdecals][2][0] = (placex - where->x) / (*size) / 2 + .5;
1280                             decaltexcoords[numdecals][2][1] = (placez - where->z) / (*size) / 2 + .5;
1281
1282                             decalvertex[numdecals][2].x = placex;
1283                             decalvertex[numdecals][2].z = placez;
1284                             decalvertex[numdecals][2].y = vertex[Triangles[i].vertex[2]].y;
1285
1286                             if (!(decaltexcoords[numdecals][0][0] < 0 && decaltexcoords[numdecals][1][0] < 0 && decaltexcoords[numdecals][2][0] < 0))
1287                                 if (!(decaltexcoords[numdecals][0][1] < 0 && decaltexcoords[numdecals][1][1] < 0 && decaltexcoords[numdecals][2][1] < 0))
1288                                     if (!(decaltexcoords[numdecals][0][0] > 1 && decaltexcoords[numdecals][1][0] > 1 && decaltexcoords[numdecals][2][0] > 1))
1289                                         if (!(decaltexcoords[numdecals][0][1] > 1 && decaltexcoords[numdecals][1][1] > 1 && decaltexcoords[numdecals][2][1] > 1)) {
1290                                             if (decalrotation[numdecals]) {
1291                                                 for (j = 0; j < 3; j++) {
1292                                                     rot.y = 0;
1293                                                     rot.x = decaltexcoords[numdecals][j][0] - .5;
1294                                                     rot.z = decaltexcoords[numdecals][j][1] - .5;
1295                                                     rot = DoRotation(rot, 0, -decalrotation[numdecals], 0);
1296                                                     decaltexcoords[numdecals][j][0] = rot.x + .5;
1297                                                     decaltexcoords[numdecals][j][1] = rot.z + .5;
1298                                                 }
1299                                             }
1300                                             if (numdecals < max_model_decals - 1)
1301                                                 numdecals++;
1302                                         }
1303                         }
1304                     }
1305                 }
1306     }
1307 }
1308
1309 void Model::MakeDecal(int atype, XYZ where, float size, float opacity, float rotation)
1310 {
1311     if (decals) {
1312         if (type != decalstype)
1313             return;
1314
1315         static float placex, placez;
1316         static XYZ rot;
1317         //static XYZ point,point1,point2;
1318         static float distance;
1319         static int i, j;
1320
1321         if (opacity > 0)
1322             if (distsq(&where, &boundingspherecenter) < (boundingsphereradius + size) * (boundingsphereradius + size))
1323                 for (i = 0; i < TriangleNum; i++) {
1324                     distance = abs(((facenormals[i].x * where.x) + (facenormals[i].y * where.y) + (facenormals[i].z * where.z) - ((facenormals[i].x * vertex[Triangles[i].vertex[0]].x) + (facenormals[i].y * vertex[Triangles[i].vertex[0]].y) + (facenormals[i].z * vertex[Triangles[i].vertex[0]].z))));
1325                     if (distance < .02 && abs(facenormals[i].y) > abs(facenormals[i].x) && abs(facenormals[i].y) > abs(facenormals[i].z)) {
1326                         decalposition[numdecals] = where;
1327                         decaltype[numdecals] = atype;
1328                         decalrotation[numdecals] = rotation;
1329                         decalalivetime[numdecals] = 0;
1330                         decalopacity[numdecals] = opacity - distance / 10;
1331
1332                         if (decalopacity[numdecals > 0]) {
1333                             placex = vertex[Triangles[i].vertex[0]].x;
1334                             placez = vertex[Triangles[i].vertex[0]].z;
1335
1336                             decaltexcoords[numdecals][0][0] = (placex - where.x) / (size) / 2 + .5;
1337                             decaltexcoords[numdecals][0][1] = (placez - where.z) / (size) / 2 + .5;
1338
1339                             decalvertex[numdecals][0].x = placex;
1340                             decalvertex[numdecals][0].z = placez;
1341                             decalvertex[numdecals][0].y = vertex[Triangles[i].vertex[0]].y;
1342
1343
1344                             placex = vertex[Triangles[i].vertex[1]].x;
1345                             placez = vertex[Triangles[i].vertex[1]].z;
1346
1347                             decaltexcoords[numdecals][1][0] = (placex - where.x) / (size) / 2 + .5;
1348                             decaltexcoords[numdecals][1][1] = (placez - where.z) / (size) / 2 + .5;
1349
1350                             decalvertex[numdecals][1].x = placex;
1351                             decalvertex[numdecals][1].z = placez;
1352                             decalvertex[numdecals][1].y = vertex[Triangles[i].vertex[1]].y;
1353
1354
1355                             placex = vertex[Triangles[i].vertex[2]].x;
1356                             placez = vertex[Triangles[i].vertex[2]].z;
1357
1358                             decaltexcoords[numdecals][2][0] = (placex - where.x) / (size) / 2 + .5;
1359                             decaltexcoords[numdecals][2][1] = (placez - where.z) / (size) / 2 + .5;
1360
1361                             decalvertex[numdecals][2].x = placex;
1362                             decalvertex[numdecals][2].z = placez;
1363                             decalvertex[numdecals][2].y = vertex[Triangles[i].vertex[2]].y;
1364
1365                             if (!(decaltexcoords[numdecals][0][0] < 0 && decaltexcoords[numdecals][1][0] < 0 && decaltexcoords[numdecals][2][0] < 0))
1366                                 if (!(decaltexcoords[numdecals][0][1] < 0 && decaltexcoords[numdecals][1][1] < 0 && decaltexcoords[numdecals][2][1] < 0))
1367                                     if (!(decaltexcoords[numdecals][0][0] > 1 && decaltexcoords[numdecals][1][0] > 1 && decaltexcoords[numdecals][2][0] > 1))
1368                                         if (!(decaltexcoords[numdecals][0][1] > 1 && decaltexcoords[numdecals][1][1] > 1 && decaltexcoords[numdecals][2][1] > 1)) {
1369                                             if (decalrotation[numdecals]) {
1370                                                 for (j = 0; j < 3; j++) {
1371                                                     rot.y = 0;
1372                                                     rot.x = decaltexcoords[numdecals][j][0] - .5;
1373                                                     rot.z = decaltexcoords[numdecals][j][1] - .5;
1374                                                     rot = DoRotation(rot, 0, -decalrotation[numdecals], 0);
1375                                                     decaltexcoords[numdecals][j][0] = rot.x + .5;
1376                                                     decaltexcoords[numdecals][j][1] = rot.z + .5;
1377                                                 }
1378                                             }
1379                                             if (numdecals < max_model_decals - 1)
1380                                                 numdecals++;
1381                                         }
1382                         }
1383                     } else if (distance < .02 && abs(facenormals[i].x) > abs(facenormals[i].y) && abs(facenormals[i].x) > abs(facenormals[i].z)) {
1384                         decalposition[numdecals] = where;
1385                         decaltype[numdecals] = atype;
1386                         decalrotation[numdecals] = rotation;
1387                         decalalivetime[numdecals] = 0;
1388                         decalopacity[numdecals] = opacity - distance / 10;
1389
1390                         if (decalopacity[numdecals > 0]) {
1391                             placex = vertex[Triangles[i].vertex[0]].y;
1392                             placez = vertex[Triangles[i].vertex[0]].z;
1393
1394                             decaltexcoords[numdecals][0][0] = (placex - where.y) / (size) / 2 + .5;
1395                             decaltexcoords[numdecals][0][1] = (placez - where.z) / (size) / 2 + .5;
1396
1397                             decalvertex[numdecals][0].x = vertex[Triangles[i].vertex[0]].x;
1398                             decalvertex[numdecals][0].z = placez;
1399                             decalvertex[numdecals][0].y = placex;
1400
1401
1402                             placex = vertex[Triangles[i].vertex[1]].y;
1403                             placez = vertex[Triangles[i].vertex[1]].z;
1404
1405                             decaltexcoords[numdecals][1][0] = (placex - where.y) / (size) / 2 + .5;
1406                             decaltexcoords[numdecals][1][1] = (placez - where.z) / (size) / 2 + .5;
1407
1408                             decalvertex[numdecals][1].x = vertex[Triangles[i].vertex[1]].x;
1409                             decalvertex[numdecals][1].z = placez;
1410                             decalvertex[numdecals][1].y = placex;
1411
1412
1413                             placex = vertex[Triangles[i].vertex[2]].y;
1414                             placez = vertex[Triangles[i].vertex[2]].z;
1415
1416                             decaltexcoords[numdecals][2][0] = (placex - where.y) / (size) / 2 + .5;
1417                             decaltexcoords[numdecals][2][1] = (placez - where.z) / (size) / 2 + .5;
1418
1419                             decalvertex[numdecals][2].x = vertex[Triangles[i].vertex[2]].x;
1420                             decalvertex[numdecals][2].z = placez;
1421                             decalvertex[numdecals][2].y = placex;
1422
1423                             if (!(decaltexcoords[numdecals][0][0] < 0 && decaltexcoords[numdecals][1][0] < 0 && decaltexcoords[numdecals][2][0] < 0))
1424                                 if (!(decaltexcoords[numdecals][0][1] < 0 && decaltexcoords[numdecals][1][1] < 0 && decaltexcoords[numdecals][2][1] < 0))
1425                                     if (!(decaltexcoords[numdecals][0][0] > 1 && decaltexcoords[numdecals][1][0] > 1 && decaltexcoords[numdecals][2][0] > 1))
1426                                         if (!(decaltexcoords[numdecals][0][1] > 1 && decaltexcoords[numdecals][1][1] > 1 && decaltexcoords[numdecals][2][1] > 1)) {
1427                                             if (decalrotation[numdecals]) {
1428                                                 for (j = 0; j < 3; j++) {
1429                                                     rot.y = 0;
1430                                                     rot.x = decaltexcoords[numdecals][j][0] - .5;
1431                                                     rot.z = decaltexcoords[numdecals][j][1] - .5;
1432                                                     rot = DoRotation(rot, 0, -decalrotation[numdecals], 0);
1433                                                     decaltexcoords[numdecals][j][0] = rot.x + .5;
1434                                                     decaltexcoords[numdecals][j][1] = rot.z + .5;
1435                                                 }
1436                                             }
1437                                             if (numdecals < max_model_decals - 1)
1438                                                 numdecals++;
1439                                         }
1440                         }
1441                     } else if (distance < .02 && abs(facenormals[i].z) > abs(facenormals[i].y) && abs(facenormals[i].z) > abs(facenormals[i].x)) {
1442                         decalposition[numdecals] = where;
1443                         decaltype[numdecals] = atype;
1444                         decalrotation[numdecals] = rotation;
1445                         decalalivetime[numdecals] = 0;
1446                         decalopacity[numdecals] = opacity - distance / 10;
1447
1448                         if (decalopacity[numdecals > 0]) {
1449                             placex = vertex[Triangles[i].vertex[0]].x;
1450                             placez = vertex[Triangles[i].vertex[0]].y;
1451
1452                             decaltexcoords[numdecals][0][0] = (placex - where.x) / (size) / 2 + .5;
1453                             decaltexcoords[numdecals][0][1] = (placez - where.y) / (size) / 2 + .5;
1454
1455                             decalvertex[numdecals][0].x = placex;
1456                             decalvertex[numdecals][0].z = vertex[Triangles[i].vertex[0]].z;
1457                             decalvertex[numdecals][0].y = placez;
1458
1459
1460                             placex = vertex[Triangles[i].vertex[1]].x;
1461                             placez = vertex[Triangles[i].vertex[1]].y;
1462
1463                             decaltexcoords[numdecals][1][0] = (placex - where.x) / (size) / 2 + .5;
1464                             decaltexcoords[numdecals][1][1] = (placez - where.y) / (size) / 2 + .5;
1465
1466                             decalvertex[numdecals][1].x = placex;
1467                             decalvertex[numdecals][1].z = vertex[Triangles[i].vertex[1]].z;
1468                             decalvertex[numdecals][1].y = placez;
1469
1470
1471                             placex = vertex[Triangles[i].vertex[2]].x;
1472                             placez = vertex[Triangles[i].vertex[2]].y;
1473
1474                             decaltexcoords[numdecals][2][0] = (placex - where.x) / (size) / 2 + .5;
1475                             decaltexcoords[numdecals][2][1] = (placez - where.y) / (size) / 2 + .5;
1476
1477                             decalvertex[numdecals][2].x = placex;
1478                             decalvertex[numdecals][2].z = vertex[Triangles[i].vertex[2]].z;
1479                             decalvertex[numdecals][2].y = placez;
1480
1481                             if (!(decaltexcoords[numdecals][0][0] < 0 && decaltexcoords[numdecals][1][0] < 0 && decaltexcoords[numdecals][2][0] < 0))
1482                                 if (!(decaltexcoords[numdecals][0][1] < 0 && decaltexcoords[numdecals][1][1] < 0 && decaltexcoords[numdecals][2][1] < 0))
1483                                     if (!(decaltexcoords[numdecals][0][0] > 1 && decaltexcoords[numdecals][1][0] > 1 && decaltexcoords[numdecals][2][0] > 1))
1484                                         if (!(decaltexcoords[numdecals][0][1] > 1 && decaltexcoords[numdecals][1][1] > 1 && decaltexcoords[numdecals][2][1] > 1)) {
1485                                             if (decalrotation[numdecals]) {
1486                                                 for (j = 0; j < 3; j++) {
1487                                                     rot.y = 0;
1488                                                     rot.x = decaltexcoords[numdecals][j][0] - .5;
1489                                                     rot.z = decaltexcoords[numdecals][j][1] - .5;
1490                                                     rot = DoRotation(rot, 0, -decalrotation[numdecals], 0);
1491                                                     decaltexcoords[numdecals][j][0] = rot.x + .5;
1492                                                     decaltexcoords[numdecals][j][1] = rot.z + .5;
1493                                                 }
1494                                             }
1495                                             if (numdecals < max_model_decals - 1)
1496                                                 numdecals++;
1497                                         }
1498                         }
1499                     }
1500                 }
1501     }
1502 }
1503
1504 Model::~Model()
1505 {
1506     deallocate();
1507     textureptr.destroy();
1508 }
1509
1510 void Model::deallocate()
1511 {
1512     int i = 0, j = 0;
1513
1514     if (owner)
1515         free(owner);
1516     owner = 0;
1517
1518     if (possible)
1519         free(possible);
1520     possible = 0;
1521
1522     if (vertex)
1523         free(vertex);
1524     vertex = 0;
1525
1526     if (normals)
1527         free(normals);
1528     normals = 0;
1529
1530     if (facenormals)
1531         free(facenormals);
1532     facenormals = 0;
1533
1534     if (Triangles)
1535         free(Triangles);
1536     Triangles = 0;
1537
1538     if (vArray)
1539         free(vArray);
1540     vArray = 0;
1541
1542
1543     //allow decals
1544     if (decaltexcoords) {
1545         for (i = 0; i < max_model_decals; i++) {
1546             for (j = 0; j < 3; j++) {
1547                 free(decaltexcoords[i][j]);
1548             }
1549             free(decaltexcoords[i]);
1550         }
1551         free(decaltexcoords);
1552     }
1553     decaltexcoords = 0;
1554
1555
1556     if (decalvertex) {
1557         for (i = 0; i < max_model_decals; i++) {
1558             free(decalvertex[i]);
1559         }
1560         free(decalvertex);
1561     }
1562     decalvertex = 0;
1563
1564
1565     free(decaltype);
1566     decaltype = 0;
1567
1568     free(decalopacity);
1569     decalopacity = 0;
1570
1571     free(decalrotation);
1572     decalrotation = 0;
1573
1574     free(decalalivetime);
1575     decalalivetime = 0;
1576
1577     free(decalposition);
1578     decalposition = 0;
1579
1580 };
1581
1582 Model::Model()
1583 {
1584     vertexNum = 0, TriangleNum = 0;
1585     hastexture = 0;
1586
1587     type = 0, oldtype = 0;
1588
1589     possible = 0;
1590     owner = 0;
1591     vertex = 0;
1592     normals = 0;
1593     facenormals = 0;
1594     Triangles = 0;
1595     vArray = 0;
1596
1597     memset(&modelTexture, 0, sizeof(modelTexture));
1598     numpossible = 0;
1599     color = 0;
1600
1601     boundingspherecenter = 0;
1602     boundingsphereradius = 0;
1603
1604     decaltexcoords = 0;
1605     decalvertex = 0;
1606     decaltype = 0;
1607     decalopacity = 0;
1608     decalrotation = 0;
1609     decalalivetime = 0;
1610     decalposition = 0;
1611
1612     numdecals = 0;
1613
1614     flat = 0;
1615
1616     type = nothing;
1617 }
1618