]> git.jsancho.org Git - lugaru.git/blob - Source/Graphic/Models.cpp
Added braces to all statements with clang-tidy and ran clang-format again
[lugaru.git] / Source / Graphic / Models.cpp
1 /*
2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2016 - Lugaru contributors (see AUTHORS file)
4
5 This file is part of Lugaru.
6
7 Lugaru is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 Lugaru is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Lugaru.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "Graphic/Models.hpp"
22
23 #include "Game.hpp"
24 #include "Utils/Folders.hpp"
25
26 extern float multiplier;
27 extern float viewdistance;
28 extern XYZ viewer;
29 extern float fadestart;
30 extern float texdetail;
31 extern bool decalstoggle;
32
33 int Model::LineCheck(XYZ* p1, XYZ* p2, XYZ* p, XYZ* move, float* rotate)
34 {
35     static float distance;
36     static float olddistance;
37     static int intersecting;
38     static int firstintersecting;
39     static XYZ point;
40
41     *p1 = *p1 - *move;
42     *p2 = *p2 - *move;
43     if (*rotate) {
44         *p1 = DoRotation(*p1, 0, -*rotate, 0);
45     }
46     if (*rotate) {
47         *p2 = DoRotation(*p2, 0, -*rotate, 0);
48     }
49     if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius)) {
50         return -1;
51     }
52     firstintersecting = -1;
53
54     for (unsigned int j = 0; j < Triangles.size(); j++) {
55         intersecting = LineFacetd(p1, p2, &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], &Triangles[j].facenormal, &point);
56         distance = (point.x - p1->x) * (point.x - p1->x) + (point.y - p1->y) * (point.y - p1->y) + (point.z - p1->z) * (point.z - p1->z);
57         if ((distance < olddistance || firstintersecting == -1) && intersecting) {
58             olddistance = distance;
59             firstintersecting = j;
60             *p = point;
61         }
62     }
63
64     if (*rotate) {
65         *p = DoRotation(*p, 0, *rotate, 0);
66     }
67     *p = *p + *move;
68     return firstintersecting;
69 }
70
71 int Model::LineCheckPossible(XYZ* p1, XYZ* p2, XYZ* p, XYZ* move, float* rotate)
72 {
73     static float distance;
74     static float olddistance;
75     static int intersecting;
76     static int firstintersecting;
77     static XYZ point;
78
79     *p1 = *p1 - *move;
80     *p2 = *p2 - *move;
81     if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius)) {
82         return -1;
83     }
84     firstintersecting = -1;
85     if (*rotate) {
86         *p1 = DoRotation(*p1, 0, -*rotate, 0);
87     }
88     if (*rotate) {
89         *p2 = DoRotation(*p2, 0, -*rotate, 0);
90     }
91
92     for (unsigned int j = 0; j < possible.size(); j++) {
93         if (possible[j] < Triangles.size()) {
94             intersecting = LineFacetd(p1, p2, &vertex[Triangles[possible[j]].vertex[0]], &vertex[Triangles[possible[j]].vertex[1]], &vertex[Triangles[possible[j]].vertex[2]], &Triangles[possible[j]].facenormal, &point);
95             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);
96             if ((distance < olddistance || firstintersecting == -1) && intersecting) {
97                 olddistance = distance;
98                 firstintersecting = possible[j];
99                 *p = point;
100             }
101         }
102     }
103
104     if (*rotate) {
105         *p = DoRotation(*p, 0, *rotate, 0);
106     }
107     *p = *p + *move;
108     return firstintersecting;
109 }
110
111 int Model::LineCheckSlidePossible(XYZ* p1, XYZ* p2, XYZ* move, float* rotate)
112 {
113     static float distance;
114     static float olddistance;
115     static int intersecting;
116     static int firstintersecting;
117     static XYZ point;
118
119     *p1 = *p1 - *move;
120     *p2 = *p2 - *move;
121     if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius)) {
122         return -1;
123     }
124     firstintersecting = -1;
125     if (*rotate) {
126         *p1 = DoRotation(*p1, 0, -*rotate, 0);
127     }
128     if (*rotate) {
129         *p2 = DoRotation(*p2, 0, -*rotate, 0);
130     }
131
132     for (unsigned int j = 0; j < possible.size(); j++) {
133         if (possible[j] < Triangles.size()) {
134             intersecting = LineFacetd(p1, p2, &vertex[Triangles[possible[j]].vertex[0]], &vertex[Triangles[possible[j]].vertex[1]], &vertex[Triangles[possible[j]].vertex[2]], &Triangles[possible[j]].facenormal, &point);
135             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);
136             if ((distance < olddistance || firstintersecting == -1) && intersecting) {
137                 olddistance = distance;
138                 firstintersecting = possible[j];
139             }
140         }
141     }
142
143     if (firstintersecting > 0) {
144         distance = abs((Triangles[firstintersecting].facenormal.x * p2->x) + (Triangles[firstintersecting].facenormal.y * p2->y) + (Triangles[firstintersecting].facenormal.z * p2->z) - ((Triangles[firstintersecting].facenormal.x * vertex[Triangles[firstintersecting].vertex[0]].x) + (Triangles[firstintersecting].facenormal.y * vertex[Triangles[firstintersecting].vertex[0]].y) + (Triangles[firstintersecting].facenormal.z * vertex[Triangles[firstintersecting].vertex[0]].z)));
145         *p2 -= Triangles[firstintersecting].facenormal * distance;
146     }
147
148     if (*rotate) {
149         *p2 = DoRotation(*p2, 0, *rotate, 0);
150     }
151     *p2 = *p2 + *move;
152     return firstintersecting;
153 }
154
155 int Model::SphereCheck(XYZ* p1, float radius, XYZ* p, XYZ* move, float* rotate)
156 {
157     static int i;
158     static float distance;
159     static float olddistance;
160     static int intersecting;
161     static int firstintersecting;
162     static XYZ point;
163     static XYZ oldp1;
164
165     firstintersecting = -1;
166
167     oldp1 = *p1;
168     *p1 = *p1 - *move;
169     if (*rotate) {
170         *p1 = DoRotation(*p1, 0, -*rotate, 0);
171     }
172     if (distsq(p1, &boundingspherecenter) > radius * radius + boundingsphereradius * boundingsphereradius) {
173         return -1;
174     }
175
176     for (i = 0; i < 4; i++) {
177         for (unsigned int j = 0; j < Triangles.size(); j++) {
178             intersecting = 0;
179             distance = abs((Triangles[j].facenormal.x * p1->x) + (Triangles[j].facenormal.y * p1->y) + (Triangles[j].facenormal.z * p1->z) - ((Triangles[j].facenormal.x * vertex[Triangles[j].vertex[0]].x) + (Triangles[j].facenormal.y * vertex[Triangles[j].vertex[0]].y) + (Triangles[j].facenormal.z * vertex[Triangles[j].vertex[0]].z)));
180             if (distance < radius) {
181                 point = *p1 - Triangles[j].facenormal * distance;
182                 if (PointInTriangle(&point, Triangles[j].facenormal, &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]])) {
183                     intersecting = 1;
184                 }
185                 if (!intersecting) {
186                     intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], p1, &radius);
187                 }
188                 if (!intersecting) {
189                     intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], p1, &radius);
190                 }
191                 if (!intersecting) {
192                     intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[2]], p1, &radius);
193                 }
194                 if (intersecting) {
195                     *p1 += Triangles[j].facenormal * (distance - radius);
196                 }
197             }
198             if ((distance < olddistance || firstintersecting == -1) && intersecting) {
199                 olddistance = distance;
200                 firstintersecting = j;
201                 *p = point;
202             }
203         }
204     }
205     if (*rotate) {
206         *p = DoRotation(*p, 0, *rotate, 0);
207     }
208     *p = *p + *move;
209     if (*rotate) {
210         *p1 = DoRotation(*p1, 0, *rotate, 0);
211     }
212     *p1 += *move;
213     return firstintersecting;
214 }
215
216 int Model::SphereCheckPossible(XYZ* p1, float radius, XYZ* move, float* rotate)
217 {
218     static float distance;
219     static float olddistance;
220     static int intersecting;
221     static int firstintersecting;
222     static XYZ point;
223     static XYZ oldp1;
224
225     firstintersecting = -1;
226
227     oldp1 = *p1;
228     *p1 = *p1 - *move;
229
230     possible.clear();
231
232     if (*rotate) {
233         *p1 = DoRotation(*p1, 0, -*rotate, 0);
234     }
235     if (distsq(p1, &boundingspherecenter) > radius * radius + boundingsphereradius * boundingsphereradius) {
236         *p1 = oldp1;
237         return -1;
238     }
239
240     for (unsigned int j = 0; j < Triangles.size(); j++) {
241         intersecting = 0;
242         distance = abs((Triangles[j].facenormal.x * p1->x) + (Triangles[j].facenormal.y * p1->y) + (Triangles[j].facenormal.z * p1->z) - ((Triangles[j].facenormal.x * vertex[Triangles[j].vertex[0]].x) + (Triangles[j].facenormal.y * vertex[Triangles[j].vertex[0]].y) + (Triangles[j].facenormal.z * vertex[Triangles[j].vertex[0]].z)));
243         if (distance < radius) {
244             point = *p1 - Triangles[j].facenormal * distance;
245             if (PointInTriangle(&point, Triangles[j].facenormal, &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]])) {
246                 intersecting = 1;
247             }
248             if (!intersecting) {
249                 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], p1, &radius);
250             }
251             if (!intersecting) {
252                 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], p1, &radius);
253             }
254             if (!intersecting) {
255                 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[2]], p1, &radius);
256             }
257             if (intersecting) {
258                 possible.push_back(j);
259             }
260         }
261         if ((distance < olddistance || firstintersecting == -1) && intersecting) {
262             olddistance = distance;
263             firstintersecting = j;
264         }
265     }
266     if (*rotate) {
267         *p1 = DoRotation(*p1, 0, *rotate, 0);
268     }
269     *p1 += *move;
270
271     return firstintersecting;
272 }
273
274 void Model::UpdateVertexArray()
275 {
276     if (type != normaltype && type != decalstype) {
277         return;
278     }
279
280     if (flat) {
281         for (unsigned int i = 0; i < Triangles.size(); i++) {
282             unsigned int j = i * 24;
283             vArray[j + 0] = Triangles[i].gx[0];
284             vArray[j + 1] = Triangles[i].gy[0];
285             vArray[j + 2] = Triangles[i].facenormal.x * -1;
286             vArray[j + 3] = Triangles[i].facenormal.y * -1;
287             vArray[j + 4] = Triangles[i].facenormal.z * -1;
288             vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
289             vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
290             vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
291
292             vArray[j + 8] = Triangles[i].gx[1];
293             vArray[j + 9] = Triangles[i].gy[1];
294             vArray[j + 10] = Triangles[i].facenormal.x * -1;
295             vArray[j + 11] = Triangles[i].facenormal.y * -1;
296             vArray[j + 12] = Triangles[i].facenormal.z * -1;
297             vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
298             vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
299             vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
300
301             vArray[j + 16] = Triangles[i].gx[2];
302             vArray[j + 17] = Triangles[i].gy[2];
303             vArray[j + 18] = Triangles[i].facenormal.x * -1;
304             vArray[j + 19] = Triangles[i].facenormal.y * -1;
305             vArray[j + 20] = Triangles[i].facenormal.z * -1;
306             vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
307             vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
308             vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
309         }
310     } else {
311         for (unsigned int i = 0; i < Triangles.size(); i++) {
312             unsigned int j = i * 24;
313             vArray[j + 0] = Triangles[i].gx[0];
314             vArray[j + 1] = Triangles[i].gy[0];
315             vArray[j + 2] = normals[Triangles[i].vertex[0]].x;
316             vArray[j + 3] = normals[Triangles[i].vertex[0]].y;
317             vArray[j + 4] = normals[Triangles[i].vertex[0]].z;
318             vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
319             vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
320             vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
321
322             vArray[j + 8] = Triangles[i].gx[1];
323             vArray[j + 9] = Triangles[i].gy[1];
324             vArray[j + 10] = normals[Triangles[i].vertex[1]].x;
325             vArray[j + 11] = normals[Triangles[i].vertex[1]].y;
326             vArray[j + 12] = normals[Triangles[i].vertex[1]].z;
327             vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
328             vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
329             vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
330
331             vArray[j + 16] = Triangles[i].gx[2];
332             vArray[j + 17] = Triangles[i].gy[2];
333             vArray[j + 18] = normals[Triangles[i].vertex[2]].x;
334             vArray[j + 19] = normals[Triangles[i].vertex[2]].y;
335             vArray[j + 20] = normals[Triangles[i].vertex[2]].z;
336             vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
337             vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
338             vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
339         }
340     }
341 }
342
343 void Model::UpdateVertexArrayNoTex()
344 {
345     if (type != normaltype && type != decalstype) {
346         return;
347     }
348
349     if (flat) {
350         for (unsigned int i = 0; i < Triangles.size(); i++) {
351             unsigned int j = i * 24;
352             vArray[j + 2] = Triangles[i].facenormal.x * -1;
353             vArray[j + 3] = Triangles[i].facenormal.y * -1;
354             vArray[j + 4] = Triangles[i].facenormal.z * -1;
355             vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
356             vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
357             vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
358
359             vArray[j + 10] = Triangles[i].facenormal.x * -1;
360             vArray[j + 11] = Triangles[i].facenormal.y * -1;
361             vArray[j + 12] = Triangles[i].facenormal.z * -1;
362             vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
363             vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
364             vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
365
366             vArray[j + 18] = Triangles[i].facenormal.x * -1;
367             vArray[j + 19] = Triangles[i].facenormal.y * -1;
368             vArray[j + 20] = Triangles[i].facenormal.z * -1;
369             vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
370             vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
371             vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
372         }
373     } else {
374         for (unsigned int i = 0; i < Triangles.size(); i++) {
375             unsigned int j = i * 24;
376             vArray[j + 2] = normals[Triangles[i].vertex[0]].x;
377             vArray[j + 3] = normals[Triangles[i].vertex[0]].y;
378             vArray[j + 4] = normals[Triangles[i].vertex[0]].z;
379             vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
380             vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
381             vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
382
383             vArray[j + 10] = normals[Triangles[i].vertex[1]].x;
384             vArray[j + 11] = normals[Triangles[i].vertex[1]].y;
385             vArray[j + 12] = normals[Triangles[i].vertex[1]].z;
386             vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
387             vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
388             vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
389
390             vArray[j + 18] = normals[Triangles[i].vertex[2]].x;
391             vArray[j + 19] = normals[Triangles[i].vertex[2]].y;
392             vArray[j + 20] = normals[Triangles[i].vertex[2]].z;
393             vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
394             vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
395             vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
396         }
397     }
398 }
399
400 void Model::UpdateVertexArrayNoTexNoNorm()
401 {
402     if (type != normaltype && type != decalstype) {
403         return;
404     }
405
406     for (unsigned int i = 0; i < Triangles.size(); i++) {
407         unsigned int j = i * 24;
408         vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
409         vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
410         vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
411
412         vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
413         vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
414         vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
415
416         vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
417         vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
418         vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
419     }
420 }
421
422 bool Model::loadnotex(const std::string& filename)
423 {
424     FILE* tfile;
425     long i;
426     short triangleNum;
427
428     type = notextype;
429     color = 0;
430
431     tfile = Folders::openMandatoryFile(Folders::getResourcePath(filename), "rb");
432
433     // read model settings
434
435     fseek(tfile, 0, SEEK_SET);
436     funpackf(tfile, "Bs Bs", &vertexNum, &triangleNum);
437
438     // read the model data
439     deallocate();
440
441     possible.clear();
442
443     owner = (int*)malloc(sizeof(int) * vertexNum);
444     vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
445     Triangles.resize(triangleNum);
446     vArray = (GLfloat*)malloc(sizeof(GLfloat) * triangleNum * 24);
447
448     for (i = 0; i < vertexNum; i++) {
449         funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
450     }
451
452     for (i = 0; i < triangleNum; i++) {
453         short vertex[6];
454         funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[0], &vertex[1], &vertex[2], &vertex[3], &vertex[4], &vertex[5]);
455         Triangles[i].vertex[0] = vertex[0];
456         Triangles[i].vertex[1] = vertex[2];
457         Triangles[i].vertex[2] = vertex[4];
458         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
459         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
460     }
461
462     fclose(tfile);
463
464     UpdateVertexArray();
465
466     for (i = 0; i < vertexNum; i++) {
467         owner[i] = -1;
468     }
469
470     boundingsphereradius = 0;
471     for (i = 0; i < vertexNum; i++) {
472         for (int j = 0; j < vertexNum; j++) {
473             if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
474                 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
475                 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
476             }
477         }
478     }
479     boundingsphereradius = fast_sqrt(boundingsphereradius);
480
481     return true;
482 }
483
484 bool Model::load(const std::string& filename)
485 {
486     FILE* tfile;
487     long i;
488     short triangleNum;
489
490     LOGFUNC;
491
492     LOG(std::string("Loading model...") + filename);
493
494     Game::LoadingScreen();
495
496     type = normaltype;
497     color = 0;
498
499     tfile = Folders::openMandatoryFile(Folders::getResourcePath(filename), "rb");
500
501     // read model settings
502
503     fseek(tfile, 0, SEEK_SET);
504     funpackf(tfile, "Bs Bs", &vertexNum, &triangleNum);
505
506     // read the model data
507     deallocate();
508
509     possible.clear();
510
511     owner = (int*)malloc(sizeof(int) * vertexNum);
512     vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
513     normals = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
514     Triangles.resize(triangleNum);
515     vArray = (GLfloat*)malloc(sizeof(GLfloat) * triangleNum * 24);
516
517     for (i = 0; i < vertexNum; i++) {
518         funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
519     }
520
521     for (i = 0; i < triangleNum; i++) {
522         short vertex[6];
523         funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[0], &vertex[1], &vertex[2], &vertex[3], &vertex[4], &vertex[5]);
524         Triangles[i].vertex[0] = vertex[0];
525         Triangles[i].vertex[1] = vertex[2];
526         Triangles[i].vertex[2] = vertex[4];
527         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
528         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
529     }
530
531     modelTexture.xsz = 0;
532
533     fclose(tfile);
534
535     UpdateVertexArray();
536
537     for (i = 0; i < vertexNum; i++) {
538         owner[i] = -1;
539     }
540
541     static int j;
542     boundingsphereradius = 0;
543     for (i = 0; i < vertexNum; i++) {
544         for (j = 0; j < vertexNum; j++) {
545             if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
546                 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
547                 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
548             }
549         }
550     }
551     boundingsphereradius = fast_sqrt(boundingsphereradius);
552
553     return true;
554 }
555
556 bool Model::loaddecal(const std::string& filename)
557 {
558     FILE* tfile;
559     long i, j;
560     short triangleNum;
561
562     LOGFUNC;
563
564     LOG(std::string("Loading decal...") + Folders::getResourcePath(filename));
565
566     type = decalstype;
567     color = 0;
568
569     tfile = Folders::openMandatoryFile(Folders::getResourcePath(filename), "rb");
570
571     // read model settings
572
573     fseek(tfile, 0, SEEK_SET);
574     funpackf(tfile, "Bs Bs", &vertexNum, &triangleNum);
575
576     // read the model data
577
578     deallocate();
579
580     possible.clear();
581
582     owner = (int*)malloc(sizeof(int) * vertexNum);
583     vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
584     normals = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
585     Triangles.resize(triangleNum);
586     vArray = (GLfloat*)malloc(sizeof(GLfloat) * triangleNum * 24);
587
588     for (i = 0; i < vertexNum; i++) {
589         funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
590     }
591
592     for (i = 0; i < triangleNum; i++) {
593         short vertex[6];
594         funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[0], &vertex[1], &vertex[2], &vertex[3], &vertex[4], &vertex[5]);
595         Triangles[i].vertex[0] = vertex[0];
596         Triangles[i].vertex[1] = vertex[2];
597         Triangles[i].vertex[2] = vertex[4];
598         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
599         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
600     }
601
602     modelTexture.xsz = 0;
603
604     fclose(tfile);
605
606     UpdateVertexArray();
607
608     for (i = 0; i < vertexNum; i++) {
609         owner[i] = -1;
610     }
611
612     boundingsphereradius = 0;
613     for (i = 0; i < vertexNum; i++) {
614         for (j = 0; j < vertexNum; j++) {
615             if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
616                 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
617                 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
618             }
619         }
620     }
621     boundingsphereradius = fast_sqrt(boundingsphereradius);
622
623     return true;
624 }
625
626 bool Model::loadraw(const std::string& filename)
627 {
628     FILE* tfile;
629     long i;
630     short triangleNum;
631
632     LOGFUNC;
633
634     LOG(std::string("Loading raw...") + filename);
635
636     type = rawtype;
637     color = 0;
638
639     tfile = Folders::openMandatoryFile(Folders::getResourcePath(filename), "rb");
640
641     // read model settings
642
643     fseek(tfile, 0, SEEK_SET);
644     funpackf(tfile, "Bs Bs", &vertexNum, &triangleNum);
645
646     // read the model data
647     deallocate();
648
649     possible.clear();
650
651     owner = (int*)malloc(sizeof(int) * vertexNum);
652     vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
653     Triangles.resize(triangleNum);
654     vArray = (GLfloat*)malloc(sizeof(GLfloat) * triangleNum * 24);
655
656     for (i = 0; i < vertexNum; i++) {
657         funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
658     }
659
660     for (i = 0; i < triangleNum; i++) {
661         short vertex[6];
662         funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[0], &vertex[1], &vertex[2], &vertex[3], &vertex[4], &vertex[5]);
663         Triangles[i].vertex[0] = vertex[0];
664         Triangles[i].vertex[1] = vertex[2];
665         Triangles[i].vertex[2] = vertex[4];
666         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
667         funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
668     }
669
670     fclose(tfile);
671
672     for (i = 0; i < vertexNum; i++) {
673         owner[i] = -1;
674     }
675
676     return true;
677 }
678
679 void Model::UniformTexCoords()
680 {
681     for (unsigned int i = 0; i < Triangles.size(); i++) {
682         Triangles[i].gy[0] = vertex[Triangles[i].vertex[0]].y;
683         Triangles[i].gy[1] = vertex[Triangles[i].vertex[1]].y;
684         Triangles[i].gy[2] = vertex[Triangles[i].vertex[2]].y;
685         Triangles[i].gx[0] = vertex[Triangles[i].vertex[0]].x;
686         Triangles[i].gx[1] = vertex[Triangles[i].vertex[1]].x;
687         Triangles[i].gx[2] = vertex[Triangles[i].vertex[2]].x;
688     }
689     UpdateVertexArray();
690 }
691
692 void Model::FlipTexCoords()
693 {
694     for (unsigned int i = 0; i < Triangles.size(); i++) {
695         Triangles[i].gy[0] = -Triangles[i].gy[0];
696         Triangles[i].gy[1] = -Triangles[i].gy[1];
697         Triangles[i].gy[2] = -Triangles[i].gy[2];
698     }
699     UpdateVertexArray();
700 }
701
702 void Model::ScaleTexCoords(float howmuch)
703 {
704     for (unsigned int i = 0; i < Triangles.size(); i++) {
705         Triangles[i].gx[0] *= howmuch;
706         Triangles[i].gx[1] *= howmuch;
707         Triangles[i].gx[2] *= howmuch;
708         Triangles[i].gy[0] *= howmuch;
709         Triangles[i].gy[1] *= howmuch;
710         Triangles[i].gy[2] *= howmuch;
711     }
712     UpdateVertexArray();
713 }
714
715 void Model::Scale(float xscale, float yscale, float zscale)
716 {
717     static int i;
718     for (i = 0; i < vertexNum; i++) {
719         vertex[i].x *= xscale;
720         vertex[i].y *= yscale;
721         vertex[i].z *= zscale;
722     }
723     UpdateVertexArray();
724
725     static int j;
726
727     boundingsphereradius = 0;
728     for (i = 0; i < vertexNum; i++) {
729         for (j = 0; j < vertexNum; j++) {
730             if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
731                 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
732                 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
733             }
734         }
735     }
736     boundingsphereradius = fast_sqrt(boundingsphereradius);
737 }
738
739 void Model::ScaleNormals(float xscale, float yscale, float zscale)
740 {
741     if (type != normaltype && type != decalstype) {
742         return;
743     }
744
745     for (int i = 0; i < vertexNum; i++) {
746         normals[i].x *= xscale;
747         normals[i].y *= yscale;
748         normals[i].z *= zscale;
749     }
750     for (unsigned int i = 0; i < Triangles.size(); i++) {
751         Triangles[i].facenormal.x *= xscale;
752         Triangles[i].facenormal.y *= yscale;
753         Triangles[i].facenormal.z *= zscale;
754     }
755     UpdateVertexArray();
756 }
757
758 void Model::Translate(float xtrans, float ytrans, float ztrans)
759 {
760     static int i;
761     for (i = 0; i < vertexNum; i++) {
762         vertex[i].x += xtrans;
763         vertex[i].y += ytrans;
764         vertex[i].z += ztrans;
765     }
766     UpdateVertexArray();
767
768     static int j;
769     boundingsphereradius = 0;
770     for (i = 0; i < vertexNum; i++) {
771         for (j = 0; j < vertexNum; j++) {
772             if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
773                 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
774                 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
775             }
776         }
777     }
778     boundingsphereradius = fast_sqrt(boundingsphereradius);
779 }
780
781 void Model::Rotate(float xang, float yang, float zang)
782 {
783     static int i;
784     for (i = 0; i < vertexNum; i++) {
785         vertex[i] = DoRotation(vertex[i], xang, yang, zang);
786     }
787     UpdateVertexArray();
788
789     static int j;
790     boundingsphereradius = 0;
791     for (i = 0; i < vertexNum; i++) {
792         for (j = 0; j < vertexNum; j++) {
793             if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
794                 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
795                 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
796             }
797         }
798     }
799     boundingsphereradius = fast_sqrt(boundingsphereradius);
800 }
801
802 void Model::CalculateNormals(bool facenormalise)
803 {
804     Game::LoadingScreen();
805
806     if (type != normaltype && type != decalstype) {
807         return;
808     }
809
810     for (int i = 0; i < vertexNum; i++) {
811         normals[i].x = 0;
812         normals[i].y = 0;
813         normals[i].z = 0;
814     }
815
816     for (unsigned int i = 0; i < Triangles.size(); i++) {
817         CrossProduct(vertex[Triangles[i].vertex[1]] - vertex[Triangles[i].vertex[0]], vertex[Triangles[i].vertex[2]] - vertex[Triangles[i].vertex[0]], &Triangles[i].facenormal);
818
819         normals[Triangles[i].vertex[0]].x += Triangles[i].facenormal.x;
820         normals[Triangles[i].vertex[0]].y += Triangles[i].facenormal.y;
821         normals[Triangles[i].vertex[0]].z += Triangles[i].facenormal.z;
822
823         normals[Triangles[i].vertex[1]].x += Triangles[i].facenormal.x;
824         normals[Triangles[i].vertex[1]].y += Triangles[i].facenormal.y;
825         normals[Triangles[i].vertex[1]].z += Triangles[i].facenormal.z;
826
827         normals[Triangles[i].vertex[2]].x += Triangles[i].facenormal.x;
828         normals[Triangles[i].vertex[2]].y += Triangles[i].facenormal.y;
829         normals[Triangles[i].vertex[2]].z += Triangles[i].facenormal.z;
830         if (facenormalise) {
831             Normalise(&Triangles[i].facenormal);
832         }
833     }
834     for (int i = 0; i < vertexNum; i++) {
835         Normalise(&normals[i]);
836         normals[i] *= -1;
837     }
838     UpdateVertexArrayNoTex();
839 }
840
841 void Model::drawimmediate()
842 {
843     textureptr.bind();
844     glBegin(GL_TRIANGLES);
845     for (unsigned int i = 0; i < Triangles.size(); i++) {
846         glTexCoord2f(Triangles[i].gx[0], Triangles[i].gy[0]);
847         if (color) {
848             glColor3f(normals[Triangles[i].vertex[0]].x, normals[Triangles[i].vertex[0]].y, normals[Triangles[i].vertex[0]].z);
849         } else if (flat) {
850             glNormal3f(Triangles[i].facenormal.x, Triangles[i].facenormal.y, Triangles[i].facenormal.y);
851         } else {
852             glNormal3f(normals[Triangles[i].vertex[0]].x, normals[Triangles[i].vertex[0]].y, normals[Triangles[i].vertex[0]].z);
853         }
854         glVertex3f(vertex[Triangles[i].vertex[0]].x, vertex[Triangles[i].vertex[0]].y, vertex[Triangles[i].vertex[0]].z);
855
856         glTexCoord2f(Triangles[i].gx[1], Triangles[i].gy[1]);
857         if (color) {
858             glColor3f(normals[Triangles[i].vertex[1]].x, normals[Triangles[i].vertex[1]].y, normals[Triangles[i].vertex[1]].z);
859         } else if (flat) {
860             glNormal3f(Triangles[i].facenormal.x, Triangles[i].facenormal.y, Triangles[i].facenormal.y);
861         } else {
862             glNormal3f(normals[Triangles[i].vertex[1]].x, normals[Triangles[i].vertex[1]].y, normals[Triangles[i].vertex[1]].z);
863         }
864         glVertex3f(vertex[Triangles[i].vertex[1]].x, vertex[Triangles[i].vertex[1]].y, vertex[Triangles[i].vertex[1]].z);
865
866         glTexCoord2f(Triangles[i].gx[2], Triangles[i].gy[2]);
867         if (color) {
868             glColor3f(normals[Triangles[i].vertex[2]].x, normals[Triangles[i].vertex[2]].y, normals[Triangles[i].vertex[2]].z);
869         } else if (flat) {
870             glNormal3f(Triangles[i].facenormal.x, Triangles[i].facenormal.y, Triangles[i].facenormal.y);
871         } else {
872             glNormal3f(normals[Triangles[i].vertex[2]].x, normals[Triangles[i].vertex[2]].y, normals[Triangles[i].vertex[2]].z);
873         }
874         glVertex3f(vertex[Triangles[i].vertex[2]].x, vertex[Triangles[i].vertex[2]].y, vertex[Triangles[i].vertex[2]].z);
875     }
876     glEnd();
877 }
878
879 void Model::draw()
880 {
881     if (type != normaltype && type != decalstype) {
882         return;
883     }
884
885     glEnableClientState(GL_NORMAL_ARRAY);
886     glEnableClientState(GL_VERTEX_ARRAY);
887     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
888
889     if (color) {
890         glInterleavedArrays(GL_T2F_C3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
891     } else {
892         glInterleavedArrays(GL_T2F_N3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
893     }
894     textureptr.bind();
895
896     glDrawArrays(GL_TRIANGLES, 0, Triangles.size() * 3);
897
898     if (color) {
899         glDisableClientState(GL_COLOR_ARRAY);
900     } else {
901         glDisableClientState(GL_NORMAL_ARRAY);
902     }
903     glDisableClientState(GL_VERTEX_ARRAY);
904     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
905 }
906
907 void Model::drawdifftex(Texture texture)
908 {
909     glEnableClientState(GL_NORMAL_ARRAY);
910     glEnableClientState(GL_VERTEX_ARRAY);
911     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
912     if (color) {
913         glInterleavedArrays(GL_T2F_C3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
914     } else {
915         glInterleavedArrays(GL_T2F_N3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
916     }
917
918     texture.bind();
919     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
920     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
921
922     glDrawArrays(GL_TRIANGLES, 0, Triangles.size() * 3);
923
924     if (color) {
925         glDisableClientState(GL_COLOR_ARRAY);
926     } else {
927         glDisableClientState(GL_NORMAL_ARRAY);
928     }
929     glDisableClientState(GL_VERTEX_ARRAY);
930     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
931 }
932
933 void Model::drawdecals(Texture shadowtexture, Texture bloodtexture, Texture bloodtexture2, Texture breaktexture)
934 {
935     if (decalstoggle) {
936         if (type != decalstype) {
937             return;
938         }
939
940         bool blend = true;
941         int lasttype = -1;
942
943         glEnable(GL_BLEND);
944         glDisable(GL_LIGHTING);
945         glDisable(GL_CULL_FACE);
946         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
947         glDepthMask(0);
948         for (unsigned int i = 0; i < decals.size(); i++) {
949             if (decals[i].type == blooddecalfast && decals[i].alivetime < 2) {
950                 decals[i].alivetime = 2;
951             }
952
953             if (decals[i].type != lasttype) {
954                 if (decals[i].type == shadowdecal) {
955                     shadowtexture.bind();
956                     if (!blend) {
957                         blend = 1;
958                         glAlphaFunc(GL_GREATER, 0.0001);
959                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
960                     }
961                 }
962                 if (decals[i].type == breakdecal) {
963                     breaktexture.bind();
964                     if (!blend) {
965                         blend = 1;
966                         glAlphaFunc(GL_GREATER, 0.0001);
967                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
968                     }
969                 }
970                 if (decals[i].type == blooddecal || decals[i].type == blooddecalslow) {
971                     bloodtexture.bind();
972                     if (blend) {
973                         blend = 0;
974                         glAlphaFunc(GL_GREATER, 0.15);
975                         glBlendFunc(GL_ONE, GL_ZERO);
976                     }
977                 }
978                 if (decals[i].type == blooddecalfast) {
979                     bloodtexture2.bind();
980                     if (blend) {
981                         blend = 0;
982                         glAlphaFunc(GL_GREATER, 0.15);
983                         glBlendFunc(GL_ONE, GL_ZERO);
984                     }
985                 }
986             }
987             if (decals[i].type == shadowdecal) {
988                 glColor4f(1, 1, 1, decals[i].opacity);
989             }
990             if (decals[i].type == breakdecal) {
991                 glColor4f(1, 1, 1, decals[i].opacity);
992                 if (decals[i].alivetime > 58) {
993                     glColor4f(1, 1, 1, decals[i].opacity * (60 - decals[i].alivetime) / 2);
994                 }
995             }
996             if ((decals[i].type == blooddecal || decals[i].type == blooddecalfast || decals[i].type == blooddecalslow)) {
997                 glColor4f(1, 1, 1, decals[i].opacity);
998                 if (decals[i].alivetime < 4) {
999                     glColor4f(1, 1, 1, decals[i].opacity * decals[i].alivetime * .25);
1000                 }
1001                 if (decals[i].alivetime > 58) {
1002                     glColor4f(1, 1, 1, decals[i].opacity * (60 - decals[i].alivetime) / 2);
1003                 }
1004             }
1005             lasttype = decals[i].type;
1006             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1007             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1008
1009             glMatrixMode(GL_MODELVIEW);
1010             glPushMatrix();
1011             glBegin(GL_TRIANGLES);
1012             for (int j = 0; j < 3; j++) {
1013                 glTexCoord2f(decals[i].texcoords[j][0], decals[i].texcoords[j][1]);
1014                 glVertex3f(decals[i].vertex[j].x, decals[i].vertex[j].y, decals[i].vertex[j].z);
1015             }
1016             glEnd();
1017             glPopMatrix();
1018         }
1019         for (int i = decals.size() - 1; i >= 0; i--) {
1020             decals[i].alivetime += multiplier;
1021             if (decals[i].type == blooddecalslow) {
1022                 decals[i].alivetime -= multiplier * 2 / 3;
1023             }
1024             if (decals[i].type == blooddecalfast) {
1025                 decals[i].alivetime += multiplier * 4;
1026             }
1027             if (decals[i].type == shadowdecal) {
1028                 DeleteDecal(i);
1029             }
1030             if ((decals[i].type == blooddecal || decals[i].type == blooddecalfast || decals[i].type == blooddecalslow) && decals[i].alivetime >= 60) {
1031                 DeleteDecal(i);
1032             }
1033         }
1034         glAlphaFunc(GL_GREATER, 0.0001);
1035         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1036     }
1037 }
1038
1039 void Model::DeleteDecal(int which)
1040 {
1041     if (decalstoggle) {
1042         if (type != decalstype) {
1043             return;
1044         }
1045         decals.erase(decals.begin() + which);
1046     }
1047 }
1048
1049 void Model::MakeDecal(decal_type atype, XYZ* where, float* size, float* opacity, float* rotation)
1050 {
1051     if (decalstoggle) {
1052         if (type != decalstype) {
1053             return;
1054         }
1055
1056         static XYZ rot;
1057         static float distance;
1058
1059         if (*opacity > 0) {
1060             if (distsq(where, &boundingspherecenter) < (boundingsphereradius + *size) * (boundingsphereradius + *size)) {
1061                 for (unsigned int i = 0; i < Triangles.size(); i++) {
1062                     if (Triangles[i].facenormal.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)) {
1063                         distance = abs(((Triangles[i].facenormal.x * where->x) + (Triangles[i].facenormal.y * where->y) + (Triangles[i].facenormal.z * where->z) - ((Triangles[i].facenormal.x * vertex[Triangles[i].vertex[0]].x) + (Triangles[i].facenormal.y * vertex[Triangles[i].vertex[0]].y) + (Triangles[i].facenormal.z * vertex[Triangles[i].vertex[0]].z))) / Triangles[i].facenormal.y);
1064
1065                         if ((*opacity - distance / 10) > 0) {
1066                             Decal decal(*where, atype, *opacity - distance / 10, *rotation, *size, *this, i, 0);
1067
1068                             if (!(decal.texcoords[0][0] < 0 && decal.texcoords[1][0] < 0 && decal.texcoords[2][0] < 0)) {
1069                                 if (!(decal.texcoords[0][1] < 0 && decal.texcoords[1][1] < 0 && decal.texcoords[2][1] < 0)) {
1070                                     if (!(decal.texcoords[0][0] > 1 && decal.texcoords[1][0] > 1 && decal.texcoords[2][0] > 1)) {
1071                                         if (!(decal.texcoords[0][1] > 1 && decal.texcoords[1][1] > 1 && decal.texcoords[2][1] > 1)) {
1072                                             if (decal.rotation) {
1073                                                 for (int j = 0; j < 3; j++) {
1074                                                     rot.y = 0;
1075                                                     rot.x = decal.texcoords[j][0] - .5;
1076                                                     rot.z = decal.texcoords[j][1] - .5;
1077                                                     rot = DoRotation(rot, 0, -decal.rotation, 0);
1078                                                     decal.texcoords[j][0] = rot.x + .5;
1079                                                     decal.texcoords[j][1] = rot.z + .5;
1080                                                 }
1081                                             }
1082                                             if (decals.size() < max_model_decals - 1) {
1083                                                 decals.push_back(decal);
1084                                             }
1085                                         }
1086                                     }
1087                                 }
1088                             }
1089                         }
1090                     }
1091                 }
1092             }
1093         }
1094     }
1095 }
1096
1097 void Model::MakeDecal(decal_type atype, XYZ where, float size, float opacity, float rotation)
1098 {
1099     if (decalstoggle) {
1100         if (type != decalstype) {
1101             return;
1102         }
1103
1104         static XYZ rot;
1105         static float distance;
1106
1107         if (opacity > 0) {
1108             if (distsq(&where, &boundingspherecenter) < (boundingsphereradius + size) * (boundingsphereradius + size)) {
1109                 for (unsigned int i = 0; i < Triangles.size(); i++) {
1110                     distance = abs(((Triangles[i].facenormal.x * where.x) + (Triangles[i].facenormal.y * where.y) + (Triangles[i].facenormal.z * where.z) - ((Triangles[i].facenormal.x * vertex[Triangles[i].vertex[0]].x) + (Triangles[i].facenormal.y * vertex[Triangles[i].vertex[0]].y) + (Triangles[i].facenormal.z * vertex[Triangles[i].vertex[0]].z))));
1111                     if (distance < .02 && abs(Triangles[i].facenormal.y) > abs(Triangles[i].facenormal.x) && abs(Triangles[i].facenormal.y) > abs(Triangles[i].facenormal.z)) {
1112                         if ((opacity - distance / 10) > 0) {
1113                             Decal decal(where, atype, opacity - distance / 10, rotation, size, *this, i, 0);
1114
1115                             if (!(decal.texcoords[0][0] < 0 && decal.texcoords[1][0] < 0 && decal.texcoords[2][0] < 0)) {
1116                                 if (!(decal.texcoords[0][1] < 0 && decal.texcoords[1][1] < 0 && decal.texcoords[2][1] < 0)) {
1117                                     if (!(decal.texcoords[0][0] > 1 && decal.texcoords[1][0] > 1 && decal.texcoords[2][0] > 1)) {
1118                                         if (!(decal.texcoords[0][1] > 1 && decal.texcoords[1][1] > 1 && decal.texcoords[2][1] > 1)) {
1119                                             if (decal.rotation) {
1120                                                 for (int j = 0; j < 3; j++) {
1121                                                     rot.y = 0;
1122                                                     rot.x = decal.texcoords[j][0] - .5;
1123                                                     rot.z = decal.texcoords[j][1] - .5;
1124                                                     rot = DoRotation(rot, 0, -decal.rotation, 0);
1125                                                     decal.texcoords[j][0] = rot.x + .5;
1126                                                     decal.texcoords[j][1] = rot.z + .5;
1127                                                 }
1128                                             }
1129                                             if (decals.size() < max_model_decals - 1) {
1130                                                 decals.push_back(decal);
1131                                             }
1132                                         }
1133                                     }
1134                                 }
1135                             }
1136                         }
1137                     } else if (distance < .02 && abs(Triangles[i].facenormal.x) > abs(Triangles[i].facenormal.y) && abs(Triangles[i].facenormal.x) > abs(Triangles[i].facenormal.z)) {
1138                         if ((opacity - distance / 10) > 0) {
1139                             Decal decal(where, atype, opacity - distance / 10, rotation, size, *this, i, 1);
1140
1141                             if (!(decal.texcoords[0][0] < 0 && decal.texcoords[1][0] < 0 && decal.texcoords[2][0] < 0)) {
1142                                 if (!(decal.texcoords[0][1] < 0 && decal.texcoords[1][1] < 0 && decal.texcoords[2][1] < 0)) {
1143                                     if (!(decal.texcoords[0][0] > 1 && decal.texcoords[1][0] > 1 && decal.texcoords[2][0] > 1)) {
1144                                         if (!(decal.texcoords[0][1] > 1 && decal.texcoords[1][1] > 1 && decal.texcoords[2][1] > 1)) {
1145                                             if (decal.rotation) {
1146                                                 for (int j = 0; j < 3; j++) {
1147                                                     rot.y = 0;
1148                                                     rot.x = decal.texcoords[j][0] - .5;
1149                                                     rot.z = decal.texcoords[j][1] - .5;
1150                                                     rot = DoRotation(rot, 0, -decal.rotation, 0);
1151                                                     decal.texcoords[j][0] = rot.x + .5;
1152                                                     decal.texcoords[j][1] = rot.z + .5;
1153                                                 }
1154                                             }
1155                                             if (decals.size() < max_model_decals - 1) {
1156                                                 decals.push_back(decal);
1157                                             }
1158                                         }
1159                                     }
1160                                 }
1161                             }
1162                         }
1163                     } else if (distance < .02 && abs(Triangles[i].facenormal.z) > abs(Triangles[i].facenormal.y) && abs(Triangles[i].facenormal.z) > abs(Triangles[i].facenormal.x)) {
1164                         if ((opacity - distance / 10) > 0) {
1165                             Decal decal(where, atype, opacity - distance / 10, rotation, size, *this, i, 2);
1166
1167                             if (!(decal.texcoords[0][0] < 0 && decal.texcoords[1][0] < 0 && decal.texcoords[2][0] < 0)) {
1168                                 if (!(decal.texcoords[0][1] < 0 && decal.texcoords[1][1] < 0 && decal.texcoords[2][1] < 0)) {
1169                                     if (!(decal.texcoords[0][0] > 1 && decal.texcoords[1][0] > 1 && decal.texcoords[2][0] > 1)) {
1170                                         if (!(decal.texcoords[0][1] > 1 && decal.texcoords[1][1] > 1 && decal.texcoords[2][1] > 1)) {
1171                                             if (decal.rotation) {
1172                                                 for (int j = 0; j < 3; j++) {
1173                                                     rot.y = 0;
1174                                                     rot.x = decal.texcoords[j][0] - .5;
1175                                                     rot.z = decal.texcoords[j][1] - .5;
1176                                                     rot = DoRotation(rot, 0, -decal.rotation, 0);
1177                                                     decal.texcoords[j][0] = rot.x + .5;
1178                                                     decal.texcoords[j][1] = rot.z + .5;
1179                                                 }
1180                                             }
1181                                             if (decals.size() < max_model_decals - 1) {
1182                                                 decals.push_back(decal);
1183                                             }
1184                                         }
1185                                     }
1186                                 }
1187                             }
1188                         }
1189                     }
1190                 }
1191             }
1192         }
1193     }
1194 }
1195
1196 const XYZ& Model::getTriangleVertex(unsigned triangleId, unsigned vertexId) const
1197 {
1198     return vertex[Triangles[triangleId].vertex[vertexId]];
1199 }
1200
1201 void Model::deleteDeadDecals()
1202 {
1203     for (int i = decals.size() - 1; i >= 0; i--) {
1204         if ((decals[i].type == blooddecal || decals[i].type == blooddecalslow) && decals[i].alivetime < 2) {
1205             DeleteDecal(i);
1206         }
1207     }
1208 }
1209
1210 Model::~Model()
1211 {
1212     deallocate();
1213 }
1214
1215 void Model::deallocate()
1216 {
1217     if (owner) {
1218         free(owner);
1219     }
1220     owner = 0;
1221
1222     if (vertex) {
1223         free(vertex);
1224     }
1225     vertex = 0;
1226
1227     if (normals) {
1228         free(normals);
1229     }
1230     normals = 0;
1231
1232     if (vArray) {
1233         free(vArray);
1234     }
1235     vArray = 0;
1236
1237     decals.clear();
1238 }
1239
1240 Model::Model()
1241     : vertexNum(0)
1242     , type(nothing)
1243     , owner(0)
1244     , vertex(0)
1245     , normals(0)
1246     , vArray(0)
1247     , color(0)
1248     , boundingspherecenter()
1249     , boundingsphereradius(0)
1250     , flat(false)
1251 {
1252     memset(&modelTexture, 0, sizeof(modelTexture));
1253 }