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