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