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