]> git.jsancho.org Git - lugaru.git/blob - Source/Models.cpp
d0a991b8217a5b6eed602b44b613913ce6664dd9
[lugaru.git] / Source / Models.cpp
1 /*
2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2016 - Lugaru contributors (see AUTHORS file)
4
5 This file is part of Lugaru.
6
7 Lugaru is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 Lugaru is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Lugaru.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "Game.h"
22 #include "Models.h"
23
24 extern float multiplier;
25 extern float viewdistance;
26 extern XYZ viewer;
27 extern float fadestart;
28 extern float texdetail;
29 extern bool decals;
30
31 extern bool visibleloading;
32
33 int Model::LineCheck(XYZ *p1, XYZ *p2, XYZ *p, XYZ *move, float *rotate)
34 {
35     static int j;
36     static float distance;
37     static float olddistance;
38     static int intersecting;
39     static int firstintersecting;
40     static XYZ point;
41
42     *p1 = *p1 - *move;
43     *p2 = *p2 - *move;
44     if (*rotate)
45         *p1 = DoRotation(*p1, 0, -*rotate, 0);
46     if (*rotate)
47         *p2 = DoRotation(*p2, 0, -*rotate, 0);
48     if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius))
49         return -1;
50     firstintersecting = -1;
51
52     for (j = 0; j < TriangleNum; j++) {
53         intersecting = LineFacetd(p1, p2, &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], &facenormals[j], &point);
54         distance = (point.x - p1->x) * (point.x - p1->x) + (point.y - p1->y) * (point.y - p1->y) + (point.z - p1->z) * (point.z - p1->z);
55         if ((distance < olddistance || firstintersecting == -1) && intersecting) {
56             olddistance = distance;
57             firstintersecting = j;
58             *p = point;
59         }
60     }
61
62     if (*rotate)
63         *p = DoRotation(*p, 0, *rotate, 0);
64     *p = *p + *move;
65     return firstintersecting;
66 }
67
68 int Model::LineCheckPossible(XYZ *p1, XYZ *p2, XYZ *p, XYZ *move, float *rotate)
69 {
70     static int j;
71     static float distance;
72     static float olddistance;
73     static int intersecting;
74     static int firstintersecting;
75     static XYZ point;
76
77     *p1 = *p1 - *move;
78     *p2 = *p2 - *move;
79     if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius))
80         return -1;
81     firstintersecting = -1;
82     if (*rotate)
83         *p1 = DoRotation(*p1, 0, -*rotate, 0);
84     if (*rotate)
85         *p2 = DoRotation(*p2, 0, -*rotate, 0);
86
87     if (numpossible > 0 && numpossible < TriangleNum)
88         for (j = 0; j < numpossible; j++) {
89             if (possible[j] >= 0 && possible[j] < TriangleNum) {
90                 intersecting = LineFacetd(p1, p2, &vertex[Triangles[possible[j]].vertex[0]], &vertex[Triangles[possible[j]].vertex[1]], &vertex[Triangles[possible[j]].vertex[2]], &facenormals[possible[j]], &point);
91                 distance = (point.x - p1->x) * (point.x - p1->x) + (point.y - p1->y) * (point.y - p1->y) + (point.z - p1->z) * (point.z - p1->z);
92                 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
93                     olddistance = distance;
94                     firstintersecting = possible[j];
95                     *p = point;
96                 }
97             }
98         }
99
100     if (*rotate)
101         *p = DoRotation(*p, 0, *rotate, 0);
102     *p = *p + *move;
103     return firstintersecting;
104 }
105
106 int Model::LineCheckSlidePossible(XYZ *p1, XYZ *p2, XYZ *p, XYZ *move, float *rotate)
107 {
108     static int j;
109     static float distance;
110     static float olddistance;
111     static int intersecting;
112     static int firstintersecting;
113     static XYZ point;
114
115     *p1 = *p1 - *move;
116     *p2 = *p2 - *move;
117     if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius))
118         return -1;
119     firstintersecting = -1;
120     if (*rotate)
121         *p1 = DoRotation(*p1, 0, -*rotate, 0);
122     if (*rotate)
123         *p2 = DoRotation(*p2, 0, -*rotate, 0);
124
125     if (numpossible)
126         for (j = 0; j < numpossible; j++) {
127             if (possible[j] >= 0 && possible[j] < TriangleNum) {
128                 intersecting = LineFacetd(p1, p2, &vertex[Triangles[possible[j]].vertex[0]], &vertex[Triangles[possible[j]].vertex[1]], &vertex[Triangles[possible[j]].vertex[2]], &facenormals[possible[j]], &point);
129                 distance = (point.x - p1->x) * (point.x - p1->x) + (point.y - p1->y) * (point.y - p1->y) + (point.z - p1->z) * (point.z - p1->z);
130                 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
131                     olddistance = distance;
132                     firstintersecting = possible[j];
133                 }
134             }
135         }
136
137     if (firstintersecting > 0) {
138         distance = abs((facenormals[firstintersecting].x * p2->x) + (facenormals[firstintersecting].y * p2->y) + (facenormals[firstintersecting].z * p2->z) - ((facenormals[firstintersecting].x * vertex[Triangles[firstintersecting].vertex[0]].x) + (facenormals[firstintersecting].y * vertex[Triangles[firstintersecting].vertex[0]].y) + (facenormals[firstintersecting].z * vertex[Triangles[firstintersecting].vertex[0]].z)));
139         *p2 -= facenormals[firstintersecting] * distance;
140     }
141
142     if (*rotate)
143         *p2 = DoRotation(*p2, 0, *rotate, 0);
144     *p2 = *p2 + *move;
145     return firstintersecting;
146 }
147
148 int Model::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate)
149 {
150     static int i, j;
151     static float distance;
152     static float olddistance;
153     static int intersecting;
154     static int firstintersecting;
155     static XYZ point;
156     static XYZ oldp1;
157
158     firstintersecting = -1;
159
160     oldp1 = *p1;
161     *p1 = *p1 - *move;
162     if (*rotate)
163         *p1 = DoRotation(*p1, 0, -*rotate, 0);
164     if (distsq(p1, &boundingspherecenter) > radius * radius + boundingsphereradius * boundingsphereradius)
165         return -1;
166
167     for (i = 0; i < 4; i++) {
168         for (j = 0; j < TriangleNum; j++) {
169             intersecting = 0;
170             distance = abs((facenormals[j].x * p1->x) + (facenormals[j].y * p1->y) + (facenormals[j].z * p1->z) - ((facenormals[j].x * vertex[Triangles[j].vertex[0]].x) + (facenormals[j].y * vertex[Triangles[j].vertex[0]].y) + (facenormals[j].z * vertex[Triangles[j].vertex[0]].z)));
171             if (distance < radius) {
172                 point = *p1 - facenormals[j] * distance;
173                 if (PointInTriangle( &point, facenormals[j], &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]]))
174                     intersecting = 1;
175                 if (!intersecting)
176                     intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], p1, &radius);
177                 if (!intersecting)
178                     intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], p1, &radius);
179                 if (!intersecting)
180                     intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[2]], p1, &radius);
181                 if (intersecting) {
182                     *p1 += facenormals[j] * (distance - radius);
183                 }
184             }
185             if ((distance < olddistance || firstintersecting == -1) && intersecting) {
186                 olddistance = distance;
187                 firstintersecting = j;
188                 *p = point;
189             }
190         }
191     }
192     if (*rotate)
193         *p = DoRotation(*p, 0, *rotate, 0);
194     *p = *p + *move;
195     if (*rotate)
196         *p1 = DoRotation(*p1, 0, *rotate, 0);
197     *p1 += *move;
198     return firstintersecting;
199 }
200
201 int Model::SphereCheckPossible(XYZ *p1, float radius, XYZ *move, float *rotate)
202 {
203     static int j;
204     static float distance;
205     static float olddistance;
206     static int intersecting;
207     static int firstintersecting;
208     static XYZ point;
209     static XYZ oldp1;
210
211     firstintersecting = -1;
212
213     oldp1 = *p1;
214     *p1 = *p1 - *move;
215
216     numpossible = 0;
217
218     if (*rotate)
219         *p1 = DoRotation(*p1, 0, -*rotate, 0);
220     if (distsq(p1, &boundingspherecenter) > radius * radius + boundingsphereradius * boundingsphereradius) {
221         *p1 = oldp1;
222         return -1;
223     }
224
225     for (j = 0; j < TriangleNum; j++) {
226         intersecting = 0;
227         distance = abs((facenormals[j].x * p1->x) + (facenormals[j].y * p1->y) + (facenormals[j].z * p1->z) - ((facenormals[j].x * vertex[Triangles[j].vertex[0]].x) + (facenormals[j].y * vertex[Triangles[j].vertex[0]].y) + (facenormals[j].z * vertex[Triangles[j].vertex[0]].z)));
228         if (distance < radius) {
229             point = *p1 - facenormals[j] * distance;
230             if (PointInTriangle( &point, facenormals[j], &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]]))
231                 intersecting = 1;
232             if (!intersecting)
233                 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], p1, &radius);
234             if (!intersecting)
235                 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], p1, &radius);
236             if (!intersecting)
237                 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[2]], p1, &radius);
238             if (intersecting) {
239                 possible[numpossible] = j;
240                 numpossible++;
241             }
242         }
243         if ((distance < olddistance || firstintersecting == -1) && intersecting) {
244             olddistance = distance;
245             firstintersecting = j;
246         }
247     }
248     if (*rotate)
249         *p1 = DoRotation(*p1, 0, *rotate, 0);
250     *p1 += *move;
251     return firstintersecting;
252 }
253
254
255 void Model::UpdateVertexArray()
256 {
257     if (type != normaltype && type != decalstype)
258         return;
259     static int i;
260     static int j;
261     if (!flat)
262         for (i = 0; i < TriangleNum; i++) {
263             j = i * 24;
264             vArray[j + 0] = Triangles[i].gx[0];
265             vArray[j + 1] = Triangles[i].gy[0];
266             vArray[j + 2] = normals[Triangles[i].vertex[0]].x;
267             vArray[j + 3] = normals[Triangles[i].vertex[0]].y;
268             vArray[j + 4] = normals[Triangles[i].vertex[0]].z;
269             vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
270             vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
271             vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
272
273             vArray[j + 8] = Triangles[i].gx[1];
274             vArray[j + 9] = Triangles[i].gy[1];
275             vArray[j + 10] = normals[Triangles[i].vertex[1]].x;
276             vArray[j + 11] = normals[Triangles[i].vertex[1]].y;
277             vArray[j + 12] = normals[Triangles[i].vertex[1]].z;
278             vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
279             vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
280             vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
281
282             vArray[j + 16] = Triangles[i].gx[2];
283             vArray[j + 17] = Triangles[i].gy[2];
284             vArray[j + 18] = normals[Triangles[i].vertex[2]].x;
285             vArray[j + 19] = normals[Triangles[i].vertex[2]].y;
286             vArray[j + 20] = normals[Triangles[i].vertex[2]].z;
287             vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
288             vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
289             vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
290         }
291     if (flat)
292         for (i = 0; i < TriangleNum; i++) {
293             j = i * 24;
294             vArray[j + 0] = Triangles[i].gx[0];
295             vArray[j + 1] = Triangles[i].gy[0];
296             vArray[j + 2] = facenormals[i].x * -1;
297             vArray[j + 3] = facenormals[i].y * -1;
298             vArray[j + 4] = facenormals[i].z * -1;
299             vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
300             vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
301             vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
302
303             vArray[j + 8] = Triangles[i].gx[1];
304             vArray[j + 9] = Triangles[i].gy[1];
305             vArray[j + 10] = facenormals[i].x * -1;
306             vArray[j + 11] = facenormals[i].y * -1;
307             vArray[j + 12] = facenormals[i].z * -1;
308             vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
309             vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
310             vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
311
312             vArray[j + 16] = Triangles[i].gx[2];
313             vArray[j + 17] = Triangles[i].gy[2];
314             vArray[j + 18] = facenormals[i].x * -1;
315             vArray[j + 19] = facenormals[i].y * -1;
316             vArray[j + 20] = facenormals[i].z * -1;
317             vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
318             vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
319             vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
320
321         }
322 }
323
324 void Model::UpdateVertexArrayNoTex()
325 {
326     if (type != normaltype && type != decalstype)
327         return;
328     static int i;
329     static int j;
330     if (!flat)
331         for (i = 0; i < TriangleNum; i++) {
332             j = i * 24;
333             vArray[j + 2] = normals[Triangles[i].vertex[0]].x;
334             vArray[j + 3] = normals[Triangles[i].vertex[0]].y;
335             vArray[j + 4] = normals[Triangles[i].vertex[0]].z;
336             vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
337             vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
338             vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
339
340             vArray[j + 10] = normals[Triangles[i].vertex[1]].x;
341             vArray[j + 11] = normals[Triangles[i].vertex[1]].y;
342             vArray[j + 12] = normals[Triangles[i].vertex[1]].z;
343             vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
344             vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
345             vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
346
347             vArray[j + 18] = normals[Triangles[i].vertex[2]].x;
348             vArray[j + 19] = normals[Triangles[i].vertex[2]].y;
349             vArray[j + 20] = normals[Triangles[i].vertex[2]].z;
350             vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
351             vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
352             vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
353         }
354     if (flat)
355         for (i = 0; i < TriangleNum; i++) {
356             j = i * 24;
357             vArray[j + 2] = facenormals[i].x * -1;
358             vArray[j + 3] = facenormals[i].y * -1;
359             vArray[j + 4] = facenormals[i].z * -1;
360             vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
361             vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
362             vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
363
364             vArray[j + 10] = facenormals[i].x * -1;
365             vArray[j + 11] = facenormals[i].y * -1;
366             vArray[j + 12] = facenormals[i].z * -1;
367             vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
368             vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
369             vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
370
371             vArray[j + 18] = facenormals[i].x * -1;
372             vArray[j + 19] = facenormals[i].y * -1;
373             vArray[j + 20] = facenormals[i].z * -1;
374             vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
375             vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
376             vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
377         }
378 }
379
380 void Model::UpdateVertexArrayNoTexNoNorm()
381 {
382     if (type != normaltype && type != decalstype)
383         return;
384     static int i;
385     static int j;
386     for (i = 0; i < TriangleNum; i++) {
387         j = i * 24;
388         vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
389         vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
390         vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
391
392         vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
393         vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
394         vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
395
396         vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
397         vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
398         vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
399     }
400 }
401
402 bool Model::loadnotex(const char *filename )
403 {
404     FILE *tfile;
405     long i;
406
407     type = notextype;
408     color = 0;
409
410     tfile = fopen( ConvertFileName(filename), "rb" );
411     // read model settings
412
413     fseek(tfile, 0, SEEK_SET);
414     funpackf(tfile, "Bs Bs", &vertexNum, &TriangleNum);
415
416     // read the model data
417     deallocate();
418
419     numpossible = 0;
420
421     owner = (int*)malloc(sizeof(int) * vertexNum);
422     possible = (int*)malloc(sizeof(int) * TriangleNum);
423     vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
424     Triangles = (TexturedTriangle*)malloc(sizeof(TexturedTriangle) * TriangleNum);
425     vArray = (GLfloat*)malloc(sizeof(GLfloat) * TriangleNum * 24);
426
427     for (i = 0; i < vertexNum; i++) {
428         funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
429     }
430
431     for (i = 0; i < TriangleNum; i++) {
432         short vertex[ 6];
433         funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[ 0], &vertex[ 1], &vertex[ 2], &vertex[ 3], &vertex[ 4], &vertex[ 5]);
434         Triangles[i].vertex[ 0] = vertex[ 0];
435         Triangles[i].vertex[ 1] = vertex[ 2];
436         Triangles[i].vertex[ 2] = vertex[ 4];
437         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
438         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
439     }
440
441     fclose(tfile);
442
443     UpdateVertexArray();
444
445     for (i = 0; i < vertexNum; i++) {
446         owner[i] = -1;
447     }
448
449     static int j;
450     boundingsphereradius = 0;
451     for (i = 0; i < vertexNum; i++) {
452         for (j = 0; j < vertexNum; j++) {
453             if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
454                 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
455                 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
456             }
457         }
458     }
459     boundingsphereradius = fast_sqrt(boundingsphereradius);
460
461     return 1;
462 }
463
464
465 bool Model::load(const char *filename, bool texture )
466 {
467     FILE *tfile;
468     long i;
469
470     LOGFUNC;
471
472     LOG(std::string("Loading model...") + filename);
473
474     if (visibleloading)
475         Game::LoadingScreen();
476
477     type = normaltype;
478     color = 0;
479
480     tfile = fopen( ConvertFileName(filename), "rb" );
481     // read model settings
482
483
484     fseek(tfile, 0, SEEK_SET);
485     funpackf(tfile, "Bs Bs", &vertexNum, &TriangleNum);
486
487     // read the model data
488     deallocate();
489
490     numpossible = 0;
491
492     owner = (int*)malloc(sizeof(int) * vertexNum);
493     possible = (int*)malloc(sizeof(int) * TriangleNum);
494     vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
495     normals = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
496     facenormals = (XYZ*)malloc(sizeof(XYZ) * TriangleNum);
497     Triangles = (TexturedTriangle*)malloc(sizeof(TexturedTriangle) * TriangleNum);
498     vArray = (GLfloat*)malloc(sizeof(GLfloat) * TriangleNum * 24);
499
500     for (i = 0; i < vertexNum; i++) {
501         funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
502     }
503
504     for (i = 0; i < TriangleNum; i++) {
505         short vertex[ 6];
506         funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[ 0], &vertex[ 1], &vertex[ 2], &vertex[ 3], &vertex[ 4], &vertex[ 5]);
507         Triangles[i].vertex[ 0] = vertex[ 0];
508         Triangles[i].vertex[ 1] = vertex[ 2];
509         Triangles[i].vertex[ 2] = vertex[ 4];
510         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
511         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
512     }
513
514     modelTexture.xsz = 0;
515
516     fclose(tfile);
517
518     UpdateVertexArray();
519
520     for (i = 0; i < vertexNum; i++) {
521         owner[i] = -1;
522     }
523
524     static int j;
525     boundingsphereradius = 0;
526     for (i = 0; i < vertexNum; i++) {
527         for (j = 0; j < vertexNum; j++) {
528             if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
529                 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
530                 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
531             }
532         }
533     }
534     boundingsphereradius = fast_sqrt(boundingsphereradius);
535
536     return 1;
537 }
538
539 bool Model::loaddecal(const char *filename, bool texture )
540 {
541     FILE *tfile;
542     long i, j;
543
544     LOGFUNC;
545
546     // Changing the filename so that its more os specific
547     char * FixedFN = ConvertFileName(filename);
548
549     LOG(std::string("Loading decal...") + FixedFN);
550
551     type = decalstype;
552     numdecals = 0;
553     color = 0;
554
555     tfile = fopen( FixedFN, "rb" );
556     // read model settings
557
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 1;
635 }
636
637 bool Model::loadraw(char *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 = fopen( ConvertFileName(filename), "rb" );
650     // read model settings
651
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 1;
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