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