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