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