]> git.jsancho.org Git - lugaru.git/blob - Source/Models.cpp
Removed obsolete PLATFORM_MACOSX code
[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     glDrawArrays(GL_TRIANGLES, 0, TriangleNum * 3);
926
927     if (!color)
928         glDisableClientState(GL_NORMAL_ARRAY);
929     if (color)
930         glDisableClientState(GL_COLOR_ARRAY);
931     glDisableClientState(GL_VERTEX_ARRAY);
932     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
933 }
934
935 //TODO: phase out in favor of Texture
936 void Model::drawdifftex(GLuint texture)
937 {
938     glEnableClientState(GL_NORMAL_ARRAY);
939     glEnableClientState(GL_VERTEX_ARRAY);
940     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
941     if (!color)
942         glInterleavedArrays( GL_T2F_N3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
943     if (color)
944         glInterleavedArrays( GL_T2F_C3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
945
946     glBindTexture(GL_TEXTURE_2D, (unsigned long)texture);
947     glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
948     glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
949
950
951 #ifndef WIN32
952     glLockArraysEXT( 0, TriangleNum * 3);
953 #endif
954     glDrawArrays(GL_TRIANGLES, 0, TriangleNum * 3);
955 #ifndef WIN32
956     glUnlockArraysEXT();
957 #endif
958
959
960     if (!color)
961         glDisableClientState(GL_NORMAL_ARRAY);
962     if (color)
963         glDisableClientState(GL_COLOR_ARRAY);
964     glDisableClientState(GL_VERTEX_ARRAY);
965     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
966 }
967
968 void Model::drawdifftex(Texture texture)
969 {
970     glEnableClientState(GL_NORMAL_ARRAY);
971     glEnableClientState(GL_VERTEX_ARRAY);
972     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
973     if (!color)
974         glInterleavedArrays( GL_T2F_N3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
975     if (color)
976         glInterleavedArrays( GL_T2F_C3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
977
978     texture.bind();
979     glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
980     glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
981
982
983 #ifndef WIN32
984     glLockArraysEXT( 0, TriangleNum * 3);
985 #endif
986     glDrawArrays(GL_TRIANGLES, 0, TriangleNum * 3);
987 #ifndef WIN32
988     glUnlockArraysEXT();
989 #endif
990
991
992     if (!color)
993         glDisableClientState(GL_NORMAL_ARRAY);
994     if (color)
995         glDisableClientState(GL_COLOR_ARRAY);
996     glDisableClientState(GL_VERTEX_ARRAY);
997     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
998 }
999
1000 void Model::drawdecals(Texture shadowtexture, Texture bloodtexture, Texture bloodtexture2, Texture breaktexture)
1001 {
1002     if (decals) {
1003         if (type != decalstype)
1004             return;
1005         static int i;
1006         static int lasttype;
1007         static bool blend;
1008
1009         blend = 1;
1010
1011         lasttype = -1;
1012         glEnable(GL_BLEND);
1013         glDisable(GL_LIGHTING);
1014         glDisable(GL_CULL_FACE);
1015         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1016         glDepthMask(0);
1017         if (numdecals > max_model_decals)
1018             numdecals = max_model_decals;
1019         for (i = 0; i < numdecals; i++) {
1020             if (decaltype[i] == blooddecalfast && decalalivetime[i] < 2)
1021                 decalalivetime[i] = 2;
1022
1023             if (decaltype[i] == shadowdecal && decaltype[i] != lasttype) {
1024                 shadowtexture.bind();
1025                 if (!blend) {
1026                     blend = 1;
1027                     glAlphaFunc(GL_GREATER, 0.0001);
1028                     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1029                 }
1030             }
1031             if (decaltype[i] == breakdecal && decaltype[i] != lasttype) {
1032                 breaktexture.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] == blooddecal || decaltype[i] == blooddecalslow) && decaltype[i] != lasttype) {
1040                 bloodtexture.bind();
1041                 if (blend) {
1042                     blend = 0;
1043                     glAlphaFunc(GL_GREATER, 0.15);
1044                     glBlendFunc(GL_ONE, GL_ZERO);
1045                 }
1046             }
1047             if ((decaltype[i] == blooddecalfast) && decaltype[i] != lasttype) {
1048                 bloodtexture2.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] == shadowdecal) {
1056                 glColor4f(1, 1, 1, decalopacity[i]);
1057             }
1058             if (decaltype[i] == breakdecal) {
1059                 glColor4f(1, 1, 1, decalopacity[i]);
1060                 if (decalalivetime[i] > 58)
1061                     glColor4f(1, 1, 1, decalopacity[i] * (60 - decalalivetime[i]) / 2);
1062             }
1063             if ((decaltype[i] == blooddecal || decaltype[i] == blooddecalfast || decaltype[i] == blooddecalslow)) {
1064                 glColor4f(1, 1, 1, decalopacity[i]);
1065                 if (decalalivetime[i] < 4)
1066                     glColor4f(1, 1, 1, decalopacity[i]*decalalivetime[i]*.25);
1067                 if (decalalivetime[i] > 58)
1068                     glColor4f(1, 1, 1, decalopacity[i] * (60 - decalalivetime[i]) / 2);
1069             }
1070             lasttype = decaltype[i];
1071             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1072             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1073
1074             glMatrixMode(GL_MODELVIEW);
1075             glPushMatrix();
1076             glBegin(GL_TRIANGLES);
1077             for (int j = 0; j < 3; j++) {
1078                 glTexCoord2f(decaltexcoords[i][j][0], decaltexcoords[i][j][1]);
1079                 glVertex3f(decalvertex[i][j].x, decalvertex[i][j].y, decalvertex[i][j].z);
1080             }
1081             glEnd();
1082             glPopMatrix();
1083         }
1084         for (i = numdecals - 1; i >= 0; i--) {
1085             decalalivetime[i] += multiplier;
1086             if (decaltype[i] == blooddecalslow)
1087                 decalalivetime[i] -= multiplier * 2 / 3;
1088             if (decaltype[i] == blooddecalfast)
1089                 decalalivetime[i] += multiplier * 4;
1090             if (decaltype[i] == shadowdecal)
1091                 DeleteDecal(i);
1092             if ((decaltype[i] == blooddecal || decaltype[i] == blooddecalfast || decaltype[i] == blooddecalslow) && decalalivetime[i] >= 60)
1093                 DeleteDecal(i);
1094         }
1095         glAlphaFunc(GL_GREATER, 0.0001);
1096         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1097     }
1098 }
1099
1100 void Model::DeleteDecal(int which)
1101 {
1102     if (decals) {
1103         if (type != decalstype)
1104             return;
1105         decaltype[which] = decaltype[numdecals - 1];
1106         decalposition[which] = decalposition[numdecals - 1];
1107         for (int i = 0; i < 3; i++) {
1108             decalvertex[which][i] = decalvertex[numdecals - 1][i];
1109             decaltexcoords[which][i][0] = decaltexcoords[numdecals - 1][i][0];
1110             decaltexcoords[which][i][1] = decaltexcoords[numdecals - 1][i][1];
1111         }
1112         decalrotation[which] = decalrotation[numdecals - 1];
1113         decalalivetime[which] = decalalivetime[numdecals - 1];
1114         decalopacity[which] = decalopacity[numdecals - 1];
1115         numdecals--;
1116     }
1117 }
1118
1119 void Model::MakeDecal(int atype, XYZ *where, float *size, float *opacity, float *rotation)
1120 {
1121     if (decals) {
1122         if (type != decalstype)
1123             return;
1124
1125         static float placex, placez;
1126         static XYZ rot;
1127         static float distance;
1128         static int i, j;
1129
1130         if (*opacity > 0)
1131             if (distsq(where, &boundingspherecenter) < (boundingsphereradius + *size) * (boundingsphereradius + *size))
1132                 for (i = 0; i < TriangleNum; i++) {
1133                     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)) {
1134                         decalposition[numdecals] = *where;
1135                         decaltype[numdecals] = atype;
1136                         decalrotation[numdecals] = *rotation;
1137                         decalalivetime[numdecals] = 0;
1138                         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);
1139                         decalopacity[numdecals] = *opacity - distance / 10;
1140
1141                         if (decalopacity[numdecals > 0]) {
1142                             placex = vertex[Triangles[i].vertex[0]].x;
1143                             placez = vertex[Triangles[i].vertex[0]].z;
1144
1145                             decaltexcoords[numdecals][0][0] = (placex - where->x) / (*size) / 2 + .5;
1146                             decaltexcoords[numdecals][0][1] = (placez - where->z) / (*size) / 2 + .5;
1147
1148                             decalvertex[numdecals][0].x = placex;
1149                             decalvertex[numdecals][0].z = placez;
1150                             decalvertex[numdecals][0].y = vertex[Triangles[i].vertex[0]].y;
1151
1152
1153                             placex = vertex[Triangles[i].vertex[1]].x;
1154                             placez = vertex[Triangles[i].vertex[1]].z;
1155
1156                             decaltexcoords[numdecals][1][0] = (placex - where->x) / (*size) / 2 + .5;
1157                             decaltexcoords[numdecals][1][1] = (placez - where->z) / (*size) / 2 + .5;
1158
1159                             decalvertex[numdecals][1].x = placex;
1160                             decalvertex[numdecals][1].z = placez;
1161                             decalvertex[numdecals][1].y = vertex[Triangles[i].vertex[1]].y;
1162
1163
1164                             placex = vertex[Triangles[i].vertex[2]].x;
1165                             placez = vertex[Triangles[i].vertex[2]].z;
1166
1167                             decaltexcoords[numdecals][2][0] = (placex - where->x) / (*size) / 2 + .5;
1168                             decaltexcoords[numdecals][2][1] = (placez - where->z) / (*size) / 2 + .5;
1169
1170                             decalvertex[numdecals][2].x = placex;
1171                             decalvertex[numdecals][2].z = placez;
1172                             decalvertex[numdecals][2].y = vertex[Triangles[i].vertex[2]].y;
1173
1174                             if (!(decaltexcoords[numdecals][0][0] < 0 && decaltexcoords[numdecals][1][0] < 0 && decaltexcoords[numdecals][2][0] < 0))
1175                                 if (!(decaltexcoords[numdecals][0][1] < 0 && decaltexcoords[numdecals][1][1] < 0 && decaltexcoords[numdecals][2][1] < 0))
1176                                     if (!(decaltexcoords[numdecals][0][0] > 1 && decaltexcoords[numdecals][1][0] > 1 && decaltexcoords[numdecals][2][0] > 1))
1177                                         if (!(decaltexcoords[numdecals][0][1] > 1 && decaltexcoords[numdecals][1][1] > 1 && decaltexcoords[numdecals][2][1] > 1)) {
1178                                             if (decalrotation[numdecals]) {
1179                                                 for (j = 0; j < 3; j++) {
1180                                                     rot.y = 0;
1181                                                     rot.x = decaltexcoords[numdecals][j][0] - .5;
1182                                                     rot.z = decaltexcoords[numdecals][j][1] - .5;
1183                                                     rot = DoRotation(rot, 0, -decalrotation[numdecals], 0);
1184                                                     decaltexcoords[numdecals][j][0] = rot.x + .5;
1185                                                     decaltexcoords[numdecals][j][1] = rot.z + .5;
1186                                                 }
1187                                             }
1188                                             if (numdecals < max_model_decals - 1)
1189                                                 numdecals++;
1190                                         }
1191                         }
1192                     }
1193                 }
1194     }
1195 }
1196
1197 void Model::MakeDecal(int atype, XYZ where, float size, float opacity, float rotation)
1198 {
1199     if (decals) {
1200         if (type != decalstype)
1201             return;
1202
1203         static float placex, placez;
1204         static XYZ rot;
1205         static float distance;
1206         static int i, j;
1207
1208         if (opacity > 0)
1209             if (distsq(&where, &boundingspherecenter) < (boundingsphereradius + size) * (boundingsphereradius + size))
1210                 for (i = 0; i < TriangleNum; i++) {
1211                     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))));
1212                     if (distance < .02 && abs(facenormals[i].y) > abs(facenormals[i].x) && abs(facenormals[i].y) > abs(facenormals[i].z)) {
1213                         decalposition[numdecals] = where;
1214                         decaltype[numdecals] = atype;
1215                         decalrotation[numdecals] = rotation;
1216                         decalalivetime[numdecals] = 0;
1217                         decalopacity[numdecals] = opacity - distance / 10;
1218
1219                         if (decalopacity[numdecals > 0]) {
1220                             placex = vertex[Triangles[i].vertex[0]].x;
1221                             placez = vertex[Triangles[i].vertex[0]].z;
1222
1223                             decaltexcoords[numdecals][0][0] = (placex - where.x) / (size) / 2 + .5;
1224                             decaltexcoords[numdecals][0][1] = (placez - where.z) / (size) / 2 + .5;
1225
1226                             decalvertex[numdecals][0].x = placex;
1227                             decalvertex[numdecals][0].z = placez;
1228                             decalvertex[numdecals][0].y = vertex[Triangles[i].vertex[0]].y;
1229
1230
1231                             placex = vertex[Triangles[i].vertex[1]].x;
1232                             placez = vertex[Triangles[i].vertex[1]].z;
1233
1234                             decaltexcoords[numdecals][1][0] = (placex - where.x) / (size) / 2 + .5;
1235                             decaltexcoords[numdecals][1][1] = (placez - where.z) / (size) / 2 + .5;
1236
1237                             decalvertex[numdecals][1].x = placex;
1238                             decalvertex[numdecals][1].z = placez;
1239                             decalvertex[numdecals][1].y = vertex[Triangles[i].vertex[1]].y;
1240
1241
1242                             placex = vertex[Triangles[i].vertex[2]].x;
1243                             placez = vertex[Triangles[i].vertex[2]].z;
1244
1245                             decaltexcoords[numdecals][2][0] = (placex - where.x) / (size) / 2 + .5;
1246                             decaltexcoords[numdecals][2][1] = (placez - where.z) / (size) / 2 + .5;
1247
1248                             decalvertex[numdecals][2].x = placex;
1249                             decalvertex[numdecals][2].z = placez;
1250                             decalvertex[numdecals][2].y = vertex[Triangles[i].vertex[2]].y;
1251
1252                             if (!(decaltexcoords[numdecals][0][0] < 0 && decaltexcoords[numdecals][1][0] < 0 && decaltexcoords[numdecals][2][0] < 0))
1253                                 if (!(decaltexcoords[numdecals][0][1] < 0 && decaltexcoords[numdecals][1][1] < 0 && decaltexcoords[numdecals][2][1] < 0))
1254                                     if (!(decaltexcoords[numdecals][0][0] > 1 && decaltexcoords[numdecals][1][0] > 1 && decaltexcoords[numdecals][2][0] > 1))
1255                                         if (!(decaltexcoords[numdecals][0][1] > 1 && decaltexcoords[numdecals][1][1] > 1 && decaltexcoords[numdecals][2][1] > 1)) {
1256                                             if (decalrotation[numdecals]) {
1257                                                 for (j = 0; j < 3; j++) {
1258                                                     rot.y = 0;
1259                                                     rot.x = decaltexcoords[numdecals][j][0] - .5;
1260                                                     rot.z = decaltexcoords[numdecals][j][1] - .5;
1261                                                     rot = DoRotation(rot, 0, -decalrotation[numdecals], 0);
1262                                                     decaltexcoords[numdecals][j][0] = rot.x + .5;
1263                                                     decaltexcoords[numdecals][j][1] = rot.z + .5;
1264                                                 }
1265                                             }
1266                                             if (numdecals < max_model_decals - 1)
1267                                                 numdecals++;
1268                                         }
1269                         }
1270                     } else if (distance < .02 && abs(facenormals[i].x) > abs(facenormals[i].y) && abs(facenormals[i].x) > abs(facenormals[i].z)) {
1271                         decalposition[numdecals] = where;
1272                         decaltype[numdecals] = atype;
1273                         decalrotation[numdecals] = rotation;
1274                         decalalivetime[numdecals] = 0;
1275                         decalopacity[numdecals] = opacity - distance / 10;
1276
1277                         if (decalopacity[numdecals > 0]) {
1278                             placex = vertex[Triangles[i].vertex[0]].y;
1279                             placez = vertex[Triangles[i].vertex[0]].z;
1280
1281                             decaltexcoords[numdecals][0][0] = (placex - where.y) / (size) / 2 + .5;
1282                             decaltexcoords[numdecals][0][1] = (placez - where.z) / (size) / 2 + .5;
1283
1284                             decalvertex[numdecals][0].x = vertex[Triangles[i].vertex[0]].x;
1285                             decalvertex[numdecals][0].z = placez;
1286                             decalvertex[numdecals][0].y = placex;
1287
1288
1289                             placex = vertex[Triangles[i].vertex[1]].y;
1290                             placez = vertex[Triangles[i].vertex[1]].z;
1291
1292                             decaltexcoords[numdecals][1][0] = (placex - where.y) / (size) / 2 + .5;
1293                             decaltexcoords[numdecals][1][1] = (placez - where.z) / (size) / 2 + .5;
1294
1295                             decalvertex[numdecals][1].x = vertex[Triangles[i].vertex[1]].x;
1296                             decalvertex[numdecals][1].z = placez;
1297                             decalvertex[numdecals][1].y = placex;
1298
1299
1300                             placex = vertex[Triangles[i].vertex[2]].y;
1301                             placez = vertex[Triangles[i].vertex[2]].z;
1302
1303                             decaltexcoords[numdecals][2][0] = (placex - where.y) / (size) / 2 + .5;
1304                             decaltexcoords[numdecals][2][1] = (placez - where.z) / (size) / 2 + .5;
1305
1306                             decalvertex[numdecals][2].x = vertex[Triangles[i].vertex[2]].x;
1307                             decalvertex[numdecals][2].z = placez;
1308                             decalvertex[numdecals][2].y = placex;
1309
1310                             if (!(decaltexcoords[numdecals][0][0] < 0 && decaltexcoords[numdecals][1][0] < 0 && decaltexcoords[numdecals][2][0] < 0))
1311                                 if (!(decaltexcoords[numdecals][0][1] < 0 && decaltexcoords[numdecals][1][1] < 0 && decaltexcoords[numdecals][2][1] < 0))
1312                                     if (!(decaltexcoords[numdecals][0][0] > 1 && decaltexcoords[numdecals][1][0] > 1 && decaltexcoords[numdecals][2][0] > 1))
1313                                         if (!(decaltexcoords[numdecals][0][1] > 1 && decaltexcoords[numdecals][1][1] > 1 && decaltexcoords[numdecals][2][1] > 1)) {
1314                                             if (decalrotation[numdecals]) {
1315                                                 for (j = 0; j < 3; j++) {
1316                                                     rot.y = 0;
1317                                                     rot.x = decaltexcoords[numdecals][j][0] - .5;
1318                                                     rot.z = decaltexcoords[numdecals][j][1] - .5;
1319                                                     rot = DoRotation(rot, 0, -decalrotation[numdecals], 0);
1320                                                     decaltexcoords[numdecals][j][0] = rot.x + .5;
1321                                                     decaltexcoords[numdecals][j][1] = rot.z + .5;
1322                                                 }
1323                                             }
1324                                             if (numdecals < max_model_decals - 1)
1325                                                 numdecals++;
1326                                         }
1327                         }
1328                     } else if (distance < .02 && abs(facenormals[i].z) > abs(facenormals[i].y) && abs(facenormals[i].z) > abs(facenormals[i].x)) {
1329                         decalposition[numdecals] = where;
1330                         decaltype[numdecals] = atype;
1331                         decalrotation[numdecals] = rotation;
1332                         decalalivetime[numdecals] = 0;
1333                         decalopacity[numdecals] = opacity - distance / 10;
1334
1335                         if (decalopacity[numdecals > 0]) {
1336                             placex = vertex[Triangles[i].vertex[0]].x;
1337                             placez = vertex[Triangles[i].vertex[0]].y;
1338
1339                             decaltexcoords[numdecals][0][0] = (placex - where.x) / (size) / 2 + .5;
1340                             decaltexcoords[numdecals][0][1] = (placez - where.y) / (size) / 2 + .5;
1341
1342                             decalvertex[numdecals][0].x = placex;
1343                             decalvertex[numdecals][0].z = vertex[Triangles[i].vertex[0]].z;
1344                             decalvertex[numdecals][0].y = placez;
1345
1346
1347                             placex = vertex[Triangles[i].vertex[1]].x;
1348                             placez = vertex[Triangles[i].vertex[1]].y;
1349
1350                             decaltexcoords[numdecals][1][0] = (placex - where.x) / (size) / 2 + .5;
1351                             decaltexcoords[numdecals][1][1] = (placez - where.y) / (size) / 2 + .5;
1352
1353                             decalvertex[numdecals][1].x = placex;
1354                             decalvertex[numdecals][1].z = vertex[Triangles[i].vertex[1]].z;
1355                             decalvertex[numdecals][1].y = placez;
1356
1357
1358                             placex = vertex[Triangles[i].vertex[2]].x;
1359                             placez = vertex[Triangles[i].vertex[2]].y;
1360
1361                             decaltexcoords[numdecals][2][0] = (placex - where.x) / (size) / 2 + .5;
1362                             decaltexcoords[numdecals][2][1] = (placez - where.y) / (size) / 2 + .5;
1363
1364                             decalvertex[numdecals][2].x = placex;
1365                             decalvertex[numdecals][2].z = vertex[Triangles[i].vertex[2]].z;
1366                             decalvertex[numdecals][2].y = placez;
1367
1368                             if (!(decaltexcoords[numdecals][0][0] < 0 && decaltexcoords[numdecals][1][0] < 0 && decaltexcoords[numdecals][2][0] < 0))
1369                                 if (!(decaltexcoords[numdecals][0][1] < 0 && decaltexcoords[numdecals][1][1] < 0 && decaltexcoords[numdecals][2][1] < 0))
1370                                     if (!(decaltexcoords[numdecals][0][0] > 1 && decaltexcoords[numdecals][1][0] > 1 && decaltexcoords[numdecals][2][0] > 1))
1371                                         if (!(decaltexcoords[numdecals][0][1] > 1 && decaltexcoords[numdecals][1][1] > 1 && decaltexcoords[numdecals][2][1] > 1)) {
1372                                             if (decalrotation[numdecals]) {
1373                                                 for (j = 0; j < 3; j++) {
1374                                                     rot.y = 0;
1375                                                     rot.x = decaltexcoords[numdecals][j][0] - .5;
1376                                                     rot.z = decaltexcoords[numdecals][j][1] - .5;
1377                                                     rot = DoRotation(rot, 0, -decalrotation[numdecals], 0);
1378                                                     decaltexcoords[numdecals][j][0] = rot.x + .5;
1379                                                     decaltexcoords[numdecals][j][1] = rot.z + .5;
1380                                                 }
1381                                             }
1382                                             if (numdecals < max_model_decals - 1)
1383                                                 numdecals++;
1384                                         }
1385                         }
1386                     }
1387                 }
1388     }
1389 }
1390
1391 Model::~Model()
1392 {
1393     deallocate();
1394     textureptr.destroy();
1395 }
1396
1397 void Model::deallocate()
1398 {
1399     int i = 0, j = 0;
1400
1401     if (owner)
1402         free(owner);
1403     owner = 0;
1404
1405     if (possible)
1406         free(possible);
1407     possible = 0;
1408
1409     if (vertex)
1410         free(vertex);
1411     vertex = 0;
1412
1413     if (normals)
1414         free(normals);
1415     normals = 0;
1416
1417     if (facenormals)
1418         free(facenormals);
1419     facenormals = 0;
1420
1421     if (Triangles)
1422         free(Triangles);
1423     Triangles = 0;
1424
1425     if (vArray)
1426         free(vArray);
1427     vArray = 0;
1428
1429
1430     //allow decals
1431     if (decaltexcoords) {
1432         for (i = 0; i < max_model_decals; i++) {
1433             for (j = 0; j < 3; j++) {
1434                 free(decaltexcoords[i][j]);
1435             }
1436             free(decaltexcoords[i]);
1437         }
1438         free(decaltexcoords);
1439     }
1440     decaltexcoords = 0;
1441
1442
1443     if (decalvertex) {
1444         for (i = 0; i < max_model_decals; i++) {
1445             free(decalvertex[i]);
1446         }
1447         free(decalvertex);
1448     }
1449     decalvertex = 0;
1450
1451
1452     free(decaltype);
1453     decaltype = 0;
1454
1455     free(decalopacity);
1456     decalopacity = 0;
1457
1458     free(decalrotation);
1459     decalrotation = 0;
1460
1461     free(decalalivetime);
1462     decalalivetime = 0;
1463
1464     free(decalposition);
1465     decalposition = 0;
1466
1467 };
1468
1469 Model::Model()
1470 {
1471     vertexNum = 0, TriangleNum = 0;
1472     hastexture = 0;
1473
1474     type = 0, oldtype = 0;
1475
1476     possible = 0;
1477     owner = 0;
1478     vertex = 0;
1479     normals = 0;
1480     facenormals = 0;
1481     Triangles = 0;
1482     vArray = 0;
1483
1484     memset(&modelTexture, 0, sizeof(modelTexture));
1485     numpossible = 0;
1486     color = 0;
1487
1488     boundingspherecenter = 0;
1489     boundingsphereradius = 0;
1490
1491     decaltexcoords = 0;
1492     decalvertex = 0;
1493     decaltype = 0;
1494     decalopacity = 0;
1495     decalrotation = 0;
1496     decalalivetime = 0;
1497     decalposition = 0;
1498
1499     numdecals = 0;
1500
1501     flat = 0;
1502
1503     type = nothing;
1504 }
1505