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