2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2016 - Lugaru contributors (see AUTHORS file)
5 This file is part of Lugaru.
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.
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.
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/>.
21 #include "Graphic/Models.hpp"
24 #include "Utils/Folders.hpp"
26 extern float multiplier;
27 extern float viewdistance;
29 extern float fadestart;
30 extern float texdetail;
33 extern bool visibleloading;
35 int Model::LineCheck(XYZ *p1, XYZ *p2, XYZ *p, XYZ *move, float *rotate)
38 static float distance;
39 static float olddistance;
40 static int intersecting;
41 static int firstintersecting;
47 *p1 = DoRotation(*p1, 0, -*rotate, 0);
49 *p2 = DoRotation(*p2, 0, -*rotate, 0);
50 if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius))
52 firstintersecting = -1;
54 for (j = 0; j < TriangleNum; j++) {
55 intersecting = LineFacetd(p1, p2, &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], &facenormals[j], &point);
56 distance = (point.x - p1->x) * (point.x - p1->x) + (point.y - p1->y) * (point.y - p1->y) + (point.z - p1->z) * (point.z - p1->z);
57 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
58 olddistance = distance;
59 firstintersecting = j;
65 *p = DoRotation(*p, 0, *rotate, 0);
67 return firstintersecting;
70 int Model::LineCheckPossible(XYZ *p1, XYZ *p2, XYZ *p, XYZ *move, float *rotate)
73 static float distance;
74 static float olddistance;
75 static int intersecting;
76 static int firstintersecting;
81 if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius))
83 firstintersecting = -1;
85 *p1 = DoRotation(*p1, 0, -*rotate, 0);
87 *p2 = DoRotation(*p2, 0, -*rotate, 0);
89 if (numpossible > 0 && numpossible < TriangleNum)
90 for (j = 0; j < numpossible; j++) {
91 if (possible[j] >= 0 && possible[j] < TriangleNum) {
92 intersecting = LineFacetd(p1, p2, &vertex[Triangles[possible[j]].vertex[0]], &vertex[Triangles[possible[j]].vertex[1]], &vertex[Triangles[possible[j]].vertex[2]], &facenormals[possible[j]], &point);
93 distance = (point.x - p1->x) * (point.x - p1->x) + (point.y - p1->y) * (point.y - p1->y) + (point.z - p1->z) * (point.z - p1->z);
94 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
95 olddistance = distance;
96 firstintersecting = possible[j];
103 *p = DoRotation(*p, 0, *rotate, 0);
105 return firstintersecting;
108 int Model::LineCheckSlidePossible(XYZ *p1, XYZ *p2, XYZ *p, XYZ *move, float *rotate)
111 static float distance;
112 static float olddistance;
113 static int intersecting;
114 static int firstintersecting;
119 if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius))
121 firstintersecting = -1;
123 *p1 = DoRotation(*p1, 0, -*rotate, 0);
125 *p2 = DoRotation(*p2, 0, -*rotate, 0);
128 for (j = 0; j < numpossible; j++) {
129 if (possible[j] >= 0 && possible[j] < TriangleNum) {
130 intersecting = LineFacetd(p1, p2, &vertex[Triangles[possible[j]].vertex[0]], &vertex[Triangles[possible[j]].vertex[1]], &vertex[Triangles[possible[j]].vertex[2]], &facenormals[possible[j]], &point);
131 distance = (point.x - p1->x) * (point.x - p1->x) + (point.y - p1->y) * (point.y - p1->y) + (point.z - p1->z) * (point.z - p1->z);
132 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
133 olddistance = distance;
134 firstintersecting = possible[j];
139 if (firstintersecting > 0) {
140 distance = abs((facenormals[firstintersecting].x * p2->x) + (facenormals[firstintersecting].y * p2->y) + (facenormals[firstintersecting].z * p2->z) - ((facenormals[firstintersecting].x * vertex[Triangles[firstintersecting].vertex[0]].x) + (facenormals[firstintersecting].y * vertex[Triangles[firstintersecting].vertex[0]].y) + (facenormals[firstintersecting].z * vertex[Triangles[firstintersecting].vertex[0]].z)));
141 *p2 -= facenormals[firstintersecting] * distance;
145 *p2 = DoRotation(*p2, 0, *rotate, 0);
147 return firstintersecting;
150 int Model::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate)
153 static float distance;
154 static float olddistance;
155 static int intersecting;
156 static int firstintersecting;
160 firstintersecting = -1;
165 *p1 = DoRotation(*p1, 0, -*rotate, 0);
166 if (distsq(p1, &boundingspherecenter) > radius * radius + boundingsphereradius * boundingsphereradius)
169 for (i = 0; i < 4; i++) {
170 for (j = 0; j < TriangleNum; j++) {
172 distance = abs((facenormals[j].x * p1->x) + (facenormals[j].y * p1->y) + (facenormals[j].z * p1->z) - ((facenormals[j].x * vertex[Triangles[j].vertex[0]].x) + (facenormals[j].y * vertex[Triangles[j].vertex[0]].y) + (facenormals[j].z * vertex[Triangles[j].vertex[0]].z)));
173 if (distance < radius) {
174 point = *p1 - facenormals[j] * distance;
175 if (PointInTriangle( &point, facenormals[j], &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]]))
178 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], p1, &radius);
180 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], p1, &radius);
182 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[2]], p1, &radius);
184 *p1 += facenormals[j] * (distance - radius);
187 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
188 olddistance = distance;
189 firstintersecting = j;
195 *p = DoRotation(*p, 0, *rotate, 0);
198 *p1 = DoRotation(*p1, 0, *rotate, 0);
200 return firstintersecting;
203 int Model::SphereCheckPossible(XYZ *p1, float radius, XYZ *move, float *rotate)
206 static float distance;
207 static float olddistance;
208 static int intersecting;
209 static int firstintersecting;
213 firstintersecting = -1;
221 *p1 = DoRotation(*p1, 0, -*rotate, 0);
222 if (distsq(p1, &boundingspherecenter) > radius * radius + boundingsphereradius * boundingsphereradius) {
227 for (j = 0; j < TriangleNum; j++) {
229 distance = abs((facenormals[j].x * p1->x) + (facenormals[j].y * p1->y) + (facenormals[j].z * p1->z) - ((facenormals[j].x * vertex[Triangles[j].vertex[0]].x) + (facenormals[j].y * vertex[Triangles[j].vertex[0]].y) + (facenormals[j].z * vertex[Triangles[j].vertex[0]].z)));
230 if (distance < radius) {
231 point = *p1 - facenormals[j] * distance;
232 if (PointInTriangle( &point, facenormals[j], &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]]))
235 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], p1, &radius);
237 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], p1, &radius);
239 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[2]], p1, &radius);
241 possible[numpossible] = j;
245 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
246 olddistance = distance;
247 firstintersecting = j;
251 *p1 = DoRotation(*p1, 0, *rotate, 0);
253 return firstintersecting;
257 void Model::UpdateVertexArray()
259 if (type != normaltype && type != decalstype)
264 for (i = 0; i < TriangleNum; i++) {
266 vArray[j + 0] = Triangles[i].gx[0];
267 vArray[j + 1] = Triangles[i].gy[0];
268 vArray[j + 2] = normals[Triangles[i].vertex[0]].x;
269 vArray[j + 3] = normals[Triangles[i].vertex[0]].y;
270 vArray[j + 4] = normals[Triangles[i].vertex[0]].z;
271 vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
272 vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
273 vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
275 vArray[j + 8] = Triangles[i].gx[1];
276 vArray[j + 9] = Triangles[i].gy[1];
277 vArray[j + 10] = normals[Triangles[i].vertex[1]].x;
278 vArray[j + 11] = normals[Triangles[i].vertex[1]].y;
279 vArray[j + 12] = normals[Triangles[i].vertex[1]].z;
280 vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
281 vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
282 vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
284 vArray[j + 16] = Triangles[i].gx[2];
285 vArray[j + 17] = Triangles[i].gy[2];
286 vArray[j + 18] = normals[Triangles[i].vertex[2]].x;
287 vArray[j + 19] = normals[Triangles[i].vertex[2]].y;
288 vArray[j + 20] = normals[Triangles[i].vertex[2]].z;
289 vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
290 vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
291 vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
294 for (i = 0; i < TriangleNum; i++) {
296 vArray[j + 0] = Triangles[i].gx[0];
297 vArray[j + 1] = Triangles[i].gy[0];
298 vArray[j + 2] = facenormals[i].x * -1;
299 vArray[j + 3] = facenormals[i].y * -1;
300 vArray[j + 4] = facenormals[i].z * -1;
301 vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
302 vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
303 vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
305 vArray[j + 8] = Triangles[i].gx[1];
306 vArray[j + 9] = Triangles[i].gy[1];
307 vArray[j + 10] = facenormals[i].x * -1;
308 vArray[j + 11] = facenormals[i].y * -1;
309 vArray[j + 12] = facenormals[i].z * -1;
310 vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
311 vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
312 vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
314 vArray[j + 16] = Triangles[i].gx[2];
315 vArray[j + 17] = Triangles[i].gy[2];
316 vArray[j + 18] = facenormals[i].x * -1;
317 vArray[j + 19] = facenormals[i].y * -1;
318 vArray[j + 20] = facenormals[i].z * -1;
319 vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
320 vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
321 vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
326 void Model::UpdateVertexArrayNoTex()
328 if (type != normaltype && type != decalstype)
333 for (i = 0; i < TriangleNum; i++) {
335 vArray[j + 2] = normals[Triangles[i].vertex[0]].x;
336 vArray[j + 3] = normals[Triangles[i].vertex[0]].y;
337 vArray[j + 4] = normals[Triangles[i].vertex[0]].z;
338 vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
339 vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
340 vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
342 vArray[j + 10] = normals[Triangles[i].vertex[1]].x;
343 vArray[j + 11] = normals[Triangles[i].vertex[1]].y;
344 vArray[j + 12] = normals[Triangles[i].vertex[1]].z;
345 vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
346 vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
347 vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
349 vArray[j + 18] = normals[Triangles[i].vertex[2]].x;
350 vArray[j + 19] = normals[Triangles[i].vertex[2]].y;
351 vArray[j + 20] = normals[Triangles[i].vertex[2]].z;
352 vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
353 vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
354 vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
357 for (i = 0; i < TriangleNum; i++) {
359 vArray[j + 2] = facenormals[i].x * -1;
360 vArray[j + 3] = facenormals[i].y * -1;
361 vArray[j + 4] = facenormals[i].z * -1;
362 vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
363 vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
364 vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
366 vArray[j + 10] = facenormals[i].x * -1;
367 vArray[j + 11] = facenormals[i].y * -1;
368 vArray[j + 12] = facenormals[i].z * -1;
369 vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
370 vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
371 vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
373 vArray[j + 18] = facenormals[i].x * -1;
374 vArray[j + 19] = facenormals[i].y * -1;
375 vArray[j + 20] = facenormals[i].z * -1;
376 vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
377 vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
378 vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
382 void Model::UpdateVertexArrayNoTexNoNorm()
384 if (type != normaltype && type != decalstype)
388 for (i = 0; i < TriangleNum; i++) {
390 vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
391 vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
392 vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
394 vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
395 vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
396 vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
398 vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
399 vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
400 vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
404 bool Model::loadnotex(const std::string& filename )
412 tfile = Folders::openMandatoryFile( Folders::getResourcePath(filename), "rb" );
414 // read model settings
416 fseek(tfile, 0, SEEK_SET);
417 funpackf(tfile, "Bs Bs", &vertexNum, &TriangleNum);
419 // read the model data
424 owner = (int*)malloc(sizeof(int) * vertexNum);
425 possible = (int*)malloc(sizeof(int) * TriangleNum);
426 vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
427 Triangles = (TexturedTriangle*)malloc(sizeof(TexturedTriangle) * TriangleNum);
428 vArray = (GLfloat*)malloc(sizeof(GLfloat) * TriangleNum * 24);
430 for (i = 0; i < vertexNum; i++) {
431 funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
434 for (i = 0; i < TriangleNum; i++) {
436 funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[ 0], &vertex[ 1], &vertex[ 2], &vertex[ 3], &vertex[ 4], &vertex[ 5]);
437 Triangles[i].vertex[ 0] = vertex[ 0];
438 Triangles[i].vertex[ 1] = vertex[ 2];
439 Triangles[i].vertex[ 2] = vertex[ 4];
440 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
441 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
448 for (i = 0; i < vertexNum; i++) {
453 boundingsphereradius = 0;
454 for (i = 0; i < vertexNum; i++) {
455 for (j = 0; j < vertexNum; j++) {
456 if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
457 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
458 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
462 boundingsphereradius = fast_sqrt(boundingsphereradius);
468 bool Model::load(const std::string& filename, bool texture )
475 LOG(std::string("Loading model...") + filename);
478 Game::LoadingScreen();
483 tfile = Folders::openMandatoryFile( Folders::getResourcePath(filename), "rb" );
485 // read model settings
487 fseek(tfile, 0, SEEK_SET);
488 funpackf(tfile, "Bs Bs", &vertexNum, &TriangleNum);
490 // read the model data
495 owner = (int*)malloc(sizeof(int) * vertexNum);
496 possible = (int*)malloc(sizeof(int) * TriangleNum);
497 vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
498 normals = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
499 facenormals = (XYZ*)malloc(sizeof(XYZ) * TriangleNum);
500 Triangles = (TexturedTriangle*)malloc(sizeof(TexturedTriangle) * TriangleNum);
501 vArray = (GLfloat*)malloc(sizeof(GLfloat) * TriangleNum * 24);
503 for (i = 0; i < vertexNum; i++) {
504 funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
507 for (i = 0; i < TriangleNum; i++) {
509 funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[ 0], &vertex[ 1], &vertex[ 2], &vertex[ 3], &vertex[ 4], &vertex[ 5]);
510 Triangles[i].vertex[ 0] = vertex[ 0];
511 Triangles[i].vertex[ 1] = vertex[ 2];
512 Triangles[i].vertex[ 2] = vertex[ 4];
513 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
514 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
517 modelTexture.xsz = 0;
523 for (i = 0; i < vertexNum; i++) {
528 boundingsphereradius = 0;
529 for (i = 0; i < vertexNum; i++) {
530 for (j = 0; j < vertexNum; j++) {
531 if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
532 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
533 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
537 boundingsphereradius = fast_sqrt(boundingsphereradius);
542 bool Model::loaddecal(const std::string& filename, bool texture )
549 LOG(std::string("Loading decal...") + Folders::getResourcePath(filename));
555 tfile = Folders::openMandatoryFile( Folders::getResourcePath(filename), "rb" );
557 // read model settings
559 fseek(tfile, 0, SEEK_SET);
560 funpackf(tfile, "Bs Bs", &vertexNum, &TriangleNum);
562 // read the model data
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);
577 for (i = 0; i < vertexNum; i++) {
578 funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
581 for (i = 0; i < TriangleNum; i++) {
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]);
592 modelTexture.xsz = 0;
598 for (i = 0; i < vertexNum; i++) {
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;
611 boundingsphereradius = fast_sqrt(boundingsphereradius);
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);
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);
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);
637 bool Model::loadraw(const std::string& filename)
644 LOG(std::string("Loading raw...") + filename);
649 tfile = Folders::openMandatoryFile( Folders::getResourcePath(filename), "rb" );
651 // read model settings
653 fseek(tfile, 0, SEEK_SET);
654 funpackf(tfile, "Bs Bs", &vertexNum, &TriangleNum);
656 // read the model data
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);
668 for (i = 0; i < vertexNum; i++) {
669 funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
672 for (i = 0; i < TriangleNum; i++) {
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]);
685 for (i = 0; i < vertexNum; i++) {
693 void Model::UniformTexCoords()
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;
708 void Model::FlipTexCoords()
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];
719 void Model::ScaleTexCoords(float howmuch)
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;
733 void Model::Scale(float xscale, float yscale, float zscale)
736 for (i = 0; i < vertexNum; i++) {
737 vertex[i].x *= xscale;
738 vertex[i].y *= yscale;
739 vertex[i].z *= zscale;
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;
754 boundingsphereradius = fast_sqrt(boundingsphereradius);
757 void Model::ScaleNormals(float xscale, float yscale, float zscale)
759 if (type != normaltype && type != decalstype)
762 for (i = 0; i < vertexNum; i++) {
763 normals[i].x *= xscale;
764 normals[i].y *= yscale;
765 normals[i].z *= zscale;
767 for (i = 0; i < TriangleNum; i++) {
768 facenormals[i].x *= xscale;
769 facenormals[i].y *= yscale;
770 facenormals[i].z *= zscale;
775 void Model::Translate(float xtrans, float ytrans, float ztrans)
778 for (i = 0; i < vertexNum; i++) {
779 vertex[i].x += xtrans;
780 vertex[i].y += ytrans;
781 vertex[i].z += ztrans;
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;
795 boundingsphereradius = fast_sqrt(boundingsphereradius);
798 void Model::Rotate(float xang, float yang, float zang)
801 for (i = 0; i < vertexNum; i++) {
802 vertex[i] = DoRotation(vertex[i], xang, yang, zang);
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;
816 boundingsphereradius = fast_sqrt(boundingsphereradius);
820 void Model::CalculateNormals(bool facenormalise)
823 Game::LoadingScreen();
825 if (type != normaltype && type != decalstype)
828 for (i = 0; i < vertexNum; i++) {
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]);
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;
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;
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;
849 Normalise(&facenormals[i]);
851 for (i = 0; i < vertexNum; i++) {
852 Normalise(&normals[i]);
855 UpdateVertexArrayNoTex();
858 void Model::drawimmediate()
861 glBegin(GL_TRIANGLES);
862 for (int i = 0; i < TriangleNum; i++) {
863 glTexCoord2f(Triangles[i].gx[0], Triangles[i].gy[0]);
865 glColor3f(normals[Triangles[i].vertex[0]].x, normals[Triangles[i].vertex[0]].y, normals[Triangles[i].vertex[0]].z);
867 glNormal3f(normals[Triangles[i].vertex[0]].x, normals[Triangles[i].vertex[0]].y, normals[Triangles[i].vertex[0]].z);
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);
872 glTexCoord2f(Triangles[i].gx[1], Triangles[i].gy[1]);
874 glColor3f(normals[Triangles[i].vertex[1]].x, normals[Triangles[i].vertex[1]].y, normals[Triangles[i].vertex[1]].z);
876 glNormal3f(normals[Triangles[i].vertex[1]].x, normals[Triangles[i].vertex[1]].y, normals[Triangles[i].vertex[1]].z);
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);
881 glTexCoord2f(Triangles[i].gx[2], Triangles[i].gy[2]);
883 glColor3f(normals[Triangles[i].vertex[2]].x, normals[Triangles[i].vertex[2]].y, normals[Triangles[i].vertex[2]].z);
885 glNormal3f(normals[Triangles[i].vertex[2]].x, normals[Triangles[i].vertex[2]].y, normals[Triangles[i].vertex[2]].z);
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);
895 if (type != normaltype && type != decalstype)
898 glEnableClientState(GL_NORMAL_ARRAY);
899 glEnableClientState(GL_VERTEX_ARRAY);
900 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
903 glInterleavedArrays( GL_T2F_N3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
905 glInterleavedArrays( GL_T2F_C3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
908 glDrawArrays(GL_TRIANGLES, 0, TriangleNum * 3);
911 glDisableClientState(GL_NORMAL_ARRAY);
913 glDisableClientState(GL_COLOR_ARRAY);
914 glDisableClientState(GL_VERTEX_ARRAY);
915 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
918 //TODO: phase out in favor of Texture
919 void Model::drawdifftex(GLuint texture)
921 glEnableClientState(GL_NORMAL_ARRAY);
922 glEnableClientState(GL_VERTEX_ARRAY);
923 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
925 glInterleavedArrays( GL_T2F_N3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
927 glInterleavedArrays( GL_T2F_C3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
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 );
935 glLockArraysEXT( 0, TriangleNum * 3);
937 glDrawArrays(GL_TRIANGLES, 0, TriangleNum * 3);
944 glDisableClientState(GL_NORMAL_ARRAY);
946 glDisableClientState(GL_COLOR_ARRAY);
947 glDisableClientState(GL_VERTEX_ARRAY);
948 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
951 void Model::drawdifftex(Texture texture)
953 glEnableClientState(GL_NORMAL_ARRAY);
954 glEnableClientState(GL_VERTEX_ARRAY);
955 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
957 glInterleavedArrays( GL_T2F_N3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
959 glInterleavedArrays( GL_T2F_C3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
962 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
963 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
967 glLockArraysEXT( 0, TriangleNum * 3);
969 glDrawArrays(GL_TRIANGLES, 0, TriangleNum * 3);
976 glDisableClientState(GL_NORMAL_ARRAY);
978 glDisableClientState(GL_COLOR_ARRAY);
979 glDisableClientState(GL_VERTEX_ARRAY);
980 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
983 void Model::drawdecals(Texture shadowtexture, Texture bloodtexture, Texture bloodtexture2, Texture breaktexture)
986 if (type != decalstype)
996 glDisable(GL_LIGHTING);
997 glDisable(GL_CULL_FACE);
998 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
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;
1006 if (decaltype[i] == shadowdecal && decaltype[i] != lasttype) {
1007 shadowtexture.bind();
1010 glAlphaFunc(GL_GREATER, 0.0001);
1011 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1014 if (decaltype[i] == breakdecal && decaltype[i] != lasttype) {
1015 breaktexture.bind();
1018 glAlphaFunc(GL_GREATER, 0.0001);
1019 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1022 if ((decaltype[i] == blooddecal || decaltype[i] == blooddecalslow) && decaltype[i] != lasttype) {
1023 bloodtexture.bind();
1026 glAlphaFunc(GL_GREATER, 0.15);
1027 glBlendFunc(GL_ONE, GL_ZERO);
1030 if ((decaltype[i] == blooddecalfast) && decaltype[i] != lasttype) {
1031 bloodtexture2.bind();
1034 glAlphaFunc(GL_GREATER, 0.15);
1035 glBlendFunc(GL_ONE, GL_ZERO);
1038 if (decaltype[i] == shadowdecal) {
1039 glColor4f(1, 1, 1, decalopacity[i]);
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);
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);
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);
1057 glMatrixMode(GL_MODELVIEW);
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);
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)
1075 if ((decaltype[i] == blooddecal || decaltype[i] == blooddecalfast || decaltype[i] == blooddecalslow) && decalalivetime[i] >= 60)
1078 glAlphaFunc(GL_GREATER, 0.0001);
1079 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1083 void Model::DeleteDecal(int which)
1086 if (type != decalstype)
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];
1095 decalrotation[which] = decalrotation[numdecals - 1];
1096 decalalivetime[which] = decalalivetime[numdecals - 1];
1097 decalopacity[which] = decalopacity[numdecals - 1];
1102 void Model::MakeDecal(int atype, XYZ *where, float *size, float *opacity, float *rotation)
1105 if (type != decalstype)
1108 static float placex, placez;
1110 static float distance;
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;
1124 if (decalopacity[numdecals > 0]) {
1125 placex = vertex[Triangles[i].vertex[0]].x;
1126 placez = vertex[Triangles[i].vertex[0]].z;
1128 decaltexcoords[numdecals][0][0] = (placex - where->x) / (*size) / 2 + .5;
1129 decaltexcoords[numdecals][0][1] = (placez - where->z) / (*size) / 2 + .5;
1131 decalvertex[numdecals][0].x = placex;
1132 decalvertex[numdecals][0].z = placez;
1133 decalvertex[numdecals][0].y = vertex[Triangles[i].vertex[0]].y;
1136 placex = vertex[Triangles[i].vertex[1]].x;
1137 placez = vertex[Triangles[i].vertex[1]].z;
1139 decaltexcoords[numdecals][1][0] = (placex - where->x) / (*size) / 2 + .5;
1140 decaltexcoords[numdecals][1][1] = (placez - where->z) / (*size) / 2 + .5;
1142 decalvertex[numdecals][1].x = placex;
1143 decalvertex[numdecals][1].z = placez;
1144 decalvertex[numdecals][1].y = vertex[Triangles[i].vertex[1]].y;
1147 placex = vertex[Triangles[i].vertex[2]].x;
1148 placez = vertex[Triangles[i].vertex[2]].z;
1150 decaltexcoords[numdecals][2][0] = (placex - where->x) / (*size) / 2 + .5;
1151 decaltexcoords[numdecals][2][1] = (placez - where->z) / (*size) / 2 + .5;
1153 decalvertex[numdecals][2].x = placex;
1154 decalvertex[numdecals][2].z = placez;
1155 decalvertex[numdecals][2].y = vertex[Triangles[i].vertex[2]].y;
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++) {
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;
1171 if (numdecals < max_model_decals - 1)
1180 void Model::MakeDecal(int atype, XYZ where, float size, float opacity, float rotation)
1183 if (type != decalstype)
1186 static float placex, placez;
1188 static float distance;
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;
1202 if (decalopacity[numdecals > 0]) {
1203 placex = vertex[Triangles[i].vertex[0]].x;
1204 placez = vertex[Triangles[i].vertex[0]].z;
1206 decaltexcoords[numdecals][0][0] = (placex - where.x) / (size) / 2 + .5;
1207 decaltexcoords[numdecals][0][1] = (placez - where.z) / (size) / 2 + .5;
1209 decalvertex[numdecals][0].x = placex;
1210 decalvertex[numdecals][0].z = placez;
1211 decalvertex[numdecals][0].y = vertex[Triangles[i].vertex[0]].y;
1214 placex = vertex[Triangles[i].vertex[1]].x;
1215 placez = vertex[Triangles[i].vertex[1]].z;
1217 decaltexcoords[numdecals][1][0] = (placex - where.x) / (size) / 2 + .5;
1218 decaltexcoords[numdecals][1][1] = (placez - where.z) / (size) / 2 + .5;
1220 decalvertex[numdecals][1].x = placex;
1221 decalvertex[numdecals][1].z = placez;
1222 decalvertex[numdecals][1].y = vertex[Triangles[i].vertex[1]].y;
1225 placex = vertex[Triangles[i].vertex[2]].x;
1226 placez = vertex[Triangles[i].vertex[2]].z;
1228 decaltexcoords[numdecals][2][0] = (placex - where.x) / (size) / 2 + .5;
1229 decaltexcoords[numdecals][2][1] = (placez - where.z) / (size) / 2 + .5;
1231 decalvertex[numdecals][2].x = placex;
1232 decalvertex[numdecals][2].z = placez;
1233 decalvertex[numdecals][2].y = vertex[Triangles[i].vertex[2]].y;
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++) {
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;
1249 if (numdecals < max_model_decals - 1)
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;
1260 if (decalopacity[numdecals > 0]) {
1261 placex = vertex[Triangles[i].vertex[0]].y;
1262 placez = vertex[Triangles[i].vertex[0]].z;
1264 decaltexcoords[numdecals][0][0] = (placex - where.y) / (size) / 2 + .5;
1265 decaltexcoords[numdecals][0][1] = (placez - where.z) / (size) / 2 + .5;
1267 decalvertex[numdecals][0].x = vertex[Triangles[i].vertex[0]].x;
1268 decalvertex[numdecals][0].z = placez;
1269 decalvertex[numdecals][0].y = placex;
1272 placex = vertex[Triangles[i].vertex[1]].y;
1273 placez = vertex[Triangles[i].vertex[1]].z;
1275 decaltexcoords[numdecals][1][0] = (placex - where.y) / (size) / 2 + .5;
1276 decaltexcoords[numdecals][1][1] = (placez - where.z) / (size) / 2 + .5;
1278 decalvertex[numdecals][1].x = vertex[Triangles[i].vertex[1]].x;
1279 decalvertex[numdecals][1].z = placez;
1280 decalvertex[numdecals][1].y = placex;
1283 placex = vertex[Triangles[i].vertex[2]].y;
1284 placez = vertex[Triangles[i].vertex[2]].z;
1286 decaltexcoords[numdecals][2][0] = (placex - where.y) / (size) / 2 + .5;
1287 decaltexcoords[numdecals][2][1] = (placez - where.z) / (size) / 2 + .5;
1289 decalvertex[numdecals][2].x = vertex[Triangles[i].vertex[2]].x;
1290 decalvertex[numdecals][2].z = placez;
1291 decalvertex[numdecals][2].y = placex;
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++) {
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;
1307 if (numdecals < max_model_decals - 1)
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;
1318 if (decalopacity[numdecals > 0]) {
1319 placex = vertex[Triangles[i].vertex[0]].x;
1320 placez = vertex[Triangles[i].vertex[0]].y;
1322 decaltexcoords[numdecals][0][0] = (placex - where.x) / (size) / 2 + .5;
1323 decaltexcoords[numdecals][0][1] = (placez - where.y) / (size) / 2 + .5;
1325 decalvertex[numdecals][0].x = placex;
1326 decalvertex[numdecals][0].z = vertex[Triangles[i].vertex[0]].z;
1327 decalvertex[numdecals][0].y = placez;
1330 placex = vertex[Triangles[i].vertex[1]].x;
1331 placez = vertex[Triangles[i].vertex[1]].y;
1333 decaltexcoords[numdecals][1][0] = (placex - where.x) / (size) / 2 + .5;
1334 decaltexcoords[numdecals][1][1] = (placez - where.y) / (size) / 2 + .5;
1336 decalvertex[numdecals][1].x = placex;
1337 decalvertex[numdecals][1].z = vertex[Triangles[i].vertex[1]].z;
1338 decalvertex[numdecals][1].y = placez;
1341 placex = vertex[Triangles[i].vertex[2]].x;
1342 placez = vertex[Triangles[i].vertex[2]].y;
1344 decaltexcoords[numdecals][2][0] = (placex - where.x) / (size) / 2 + .5;
1345 decaltexcoords[numdecals][2][1] = (placez - where.y) / (size) / 2 + .5;
1347 decalvertex[numdecals][2].x = placex;
1348 decalvertex[numdecals][2].z = vertex[Triangles[i].vertex[2]].z;
1349 decalvertex[numdecals][2].y = placez;
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++) {
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;
1365 if (numdecals < max_model_decals - 1)
1377 textureptr.destroy();
1380 void Model::deallocate()
1414 if (decaltexcoords) {
1415 for (i = 0; i < max_model_decals; i++) {
1416 for (j = 0; j < 3; j++) {
1417 free(decaltexcoords[i][j]);
1419 free(decaltexcoords[i]);
1421 free(decaltexcoords);
1427 for (i = 0; i < max_model_decals; i++) {
1428 free(decalvertex[i]);
1441 free(decalrotation);
1444 free(decalalivetime);
1447 free(decalposition);
1454 vertexNum = 0, TriangleNum = 0;
1457 type = 0, oldtype = 0;
1467 memset(&modelTexture, 0, sizeof(modelTexture));
1471 boundingspherecenter = 0;
1472 boundingsphereradius = 0;