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/>.
22 #include "Graphic/Models.h"
23 #include "Utils/Folders.h"
25 extern float multiplier;
26 extern float viewdistance;
28 extern float fadestart;
29 extern float texdetail;
32 extern bool visibleloading;
34 int Model::LineCheck(XYZ *p1, XYZ *p2, XYZ *p, XYZ *move, float *rotate)
37 static float distance;
38 static float olddistance;
39 static int intersecting;
40 static int firstintersecting;
46 *p1 = DoRotation(*p1, 0, -*rotate, 0);
48 *p2 = DoRotation(*p2, 0, -*rotate, 0);
49 if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius))
51 firstintersecting = -1;
53 for (j = 0; j < TriangleNum; j++) {
54 intersecting = LineFacetd(p1, p2, &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], &facenormals[j], &point);
55 distance = (point.x - p1->x) * (point.x - p1->x) + (point.y - p1->y) * (point.y - p1->y) + (point.z - p1->z) * (point.z - p1->z);
56 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
57 olddistance = distance;
58 firstintersecting = j;
64 *p = DoRotation(*p, 0, *rotate, 0);
66 return firstintersecting;
69 int Model::LineCheckPossible(XYZ *p1, XYZ *p2, XYZ *p, XYZ *move, float *rotate)
72 static float distance;
73 static float olddistance;
74 static int intersecting;
75 static int firstintersecting;
80 if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius))
82 firstintersecting = -1;
84 *p1 = DoRotation(*p1, 0, -*rotate, 0);
86 *p2 = DoRotation(*p2, 0, -*rotate, 0);
88 if (numpossible > 0 && numpossible < TriangleNum)
89 for (j = 0; j < numpossible; j++) {
90 if (possible[j] >= 0 && possible[j] < TriangleNum) {
91 intersecting = LineFacetd(p1, p2, &vertex[Triangles[possible[j]].vertex[0]], &vertex[Triangles[possible[j]].vertex[1]], &vertex[Triangles[possible[j]].vertex[2]], &facenormals[possible[j]], &point);
92 distance = (point.x - p1->x) * (point.x - p1->x) + (point.y - p1->y) * (point.y - p1->y) + (point.z - p1->z) * (point.z - p1->z);
93 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
94 olddistance = distance;
95 firstintersecting = possible[j];
102 *p = DoRotation(*p, 0, *rotate, 0);
104 return firstintersecting;
107 int Model::LineCheckSlidePossible(XYZ *p1, XYZ *p2, XYZ *p, XYZ *move, float *rotate)
110 static float distance;
111 static float olddistance;
112 static int intersecting;
113 static int firstintersecting;
118 if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius))
120 firstintersecting = -1;
122 *p1 = DoRotation(*p1, 0, -*rotate, 0);
124 *p2 = DoRotation(*p2, 0, -*rotate, 0);
127 for (j = 0; j < numpossible; j++) {
128 if (possible[j] >= 0 && possible[j] < TriangleNum) {
129 intersecting = LineFacetd(p1, p2, &vertex[Triangles[possible[j]].vertex[0]], &vertex[Triangles[possible[j]].vertex[1]], &vertex[Triangles[possible[j]].vertex[2]], &facenormals[possible[j]], &point);
130 distance = (point.x - p1->x) * (point.x - p1->x) + (point.y - p1->y) * (point.y - p1->y) + (point.z - p1->z) * (point.z - p1->z);
131 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
132 olddistance = distance;
133 firstintersecting = possible[j];
138 if (firstintersecting > 0) {
139 distance = abs((facenormals[firstintersecting].x * p2->x) + (facenormals[firstintersecting].y * p2->y) + (facenormals[firstintersecting].z * p2->z) - ((facenormals[firstintersecting].x * vertex[Triangles[firstintersecting].vertex[0]].x) + (facenormals[firstintersecting].y * vertex[Triangles[firstintersecting].vertex[0]].y) + (facenormals[firstintersecting].z * vertex[Triangles[firstintersecting].vertex[0]].z)));
140 *p2 -= facenormals[firstintersecting] * distance;
144 *p2 = DoRotation(*p2, 0, *rotate, 0);
146 return firstintersecting;
149 int Model::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate)
152 static float distance;
153 static float olddistance;
154 static int intersecting;
155 static int firstintersecting;
159 firstintersecting = -1;
164 *p1 = DoRotation(*p1, 0, -*rotate, 0);
165 if (distsq(p1, &boundingspherecenter) > radius * radius + boundingsphereradius * boundingsphereradius)
168 for (i = 0; i < 4; i++) {
169 for (j = 0; j < TriangleNum; j++) {
171 distance = abs((facenormals[j].x * p1->x) + (facenormals[j].y * p1->y) + (facenormals[j].z * p1->z) - ((facenormals[j].x * vertex[Triangles[j].vertex[0]].x) + (facenormals[j].y * vertex[Triangles[j].vertex[0]].y) + (facenormals[j].z * vertex[Triangles[j].vertex[0]].z)));
172 if (distance < radius) {
173 point = *p1 - facenormals[j] * distance;
174 if (PointInTriangle( &point, facenormals[j], &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]]))
177 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], p1, &radius);
179 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], p1, &radius);
181 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[2]], p1, &radius);
183 *p1 += facenormals[j] * (distance - radius);
186 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
187 olddistance = distance;
188 firstintersecting = j;
194 *p = DoRotation(*p, 0, *rotate, 0);
197 *p1 = DoRotation(*p1, 0, *rotate, 0);
199 return firstintersecting;
202 int Model::SphereCheckPossible(XYZ *p1, float radius, XYZ *move, float *rotate)
205 static float distance;
206 static float olddistance;
207 static int intersecting;
208 static int firstintersecting;
212 firstintersecting = -1;
220 *p1 = DoRotation(*p1, 0, -*rotate, 0);
221 if (distsq(p1, &boundingspherecenter) > radius * radius + boundingsphereradius * boundingsphereradius) {
226 for (j = 0; j < TriangleNum; j++) {
228 distance = abs((facenormals[j].x * p1->x) + (facenormals[j].y * p1->y) + (facenormals[j].z * p1->z) - ((facenormals[j].x * vertex[Triangles[j].vertex[0]].x) + (facenormals[j].y * vertex[Triangles[j].vertex[0]].y) + (facenormals[j].z * vertex[Triangles[j].vertex[0]].z)));
229 if (distance < radius) {
230 point = *p1 - facenormals[j] * distance;
231 if (PointInTriangle( &point, facenormals[j], &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]]))
234 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], p1, &radius);
236 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], p1, &radius);
238 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[2]], p1, &radius);
240 possible[numpossible] = j;
244 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
245 olddistance = distance;
246 firstintersecting = j;
250 *p1 = DoRotation(*p1, 0, *rotate, 0);
252 return firstintersecting;
256 void Model::UpdateVertexArray()
258 if (type != normaltype && type != decalstype)
263 for (i = 0; i < TriangleNum; i++) {
265 vArray[j + 0] = Triangles[i].gx[0];
266 vArray[j + 1] = Triangles[i].gy[0];
267 vArray[j + 2] = normals[Triangles[i].vertex[0]].x;
268 vArray[j + 3] = normals[Triangles[i].vertex[0]].y;
269 vArray[j + 4] = normals[Triangles[i].vertex[0]].z;
270 vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
271 vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
272 vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
274 vArray[j + 8] = Triangles[i].gx[1];
275 vArray[j + 9] = Triangles[i].gy[1];
276 vArray[j + 10] = normals[Triangles[i].vertex[1]].x;
277 vArray[j + 11] = normals[Triangles[i].vertex[1]].y;
278 vArray[j + 12] = normals[Triangles[i].vertex[1]].z;
279 vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
280 vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
281 vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
283 vArray[j + 16] = Triangles[i].gx[2];
284 vArray[j + 17] = Triangles[i].gy[2];
285 vArray[j + 18] = normals[Triangles[i].vertex[2]].x;
286 vArray[j + 19] = normals[Triangles[i].vertex[2]].y;
287 vArray[j + 20] = normals[Triangles[i].vertex[2]].z;
288 vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
289 vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
290 vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
293 for (i = 0; i < TriangleNum; i++) {
295 vArray[j + 0] = Triangles[i].gx[0];
296 vArray[j + 1] = Triangles[i].gy[0];
297 vArray[j + 2] = facenormals[i].x * -1;
298 vArray[j + 3] = facenormals[i].y * -1;
299 vArray[j + 4] = facenormals[i].z * -1;
300 vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
301 vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
302 vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
304 vArray[j + 8] = Triangles[i].gx[1];
305 vArray[j + 9] = Triangles[i].gy[1];
306 vArray[j + 10] = facenormals[i].x * -1;
307 vArray[j + 11] = facenormals[i].y * -1;
308 vArray[j + 12] = facenormals[i].z * -1;
309 vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
310 vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
311 vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
313 vArray[j + 16] = Triangles[i].gx[2];
314 vArray[j + 17] = Triangles[i].gy[2];
315 vArray[j + 18] = facenormals[i].x * -1;
316 vArray[j + 19] = facenormals[i].y * -1;
317 vArray[j + 20] = facenormals[i].z * -1;
318 vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
319 vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
320 vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
325 void Model::UpdateVertexArrayNoTex()
327 if (type != normaltype && type != decalstype)
332 for (i = 0; i < TriangleNum; i++) {
334 vArray[j + 2] = normals[Triangles[i].vertex[0]].x;
335 vArray[j + 3] = normals[Triangles[i].vertex[0]].y;
336 vArray[j + 4] = normals[Triangles[i].vertex[0]].z;
337 vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
338 vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
339 vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
341 vArray[j + 10] = normals[Triangles[i].vertex[1]].x;
342 vArray[j + 11] = normals[Triangles[i].vertex[1]].y;
343 vArray[j + 12] = normals[Triangles[i].vertex[1]].z;
344 vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
345 vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
346 vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
348 vArray[j + 18] = normals[Triangles[i].vertex[2]].x;
349 vArray[j + 19] = normals[Triangles[i].vertex[2]].y;
350 vArray[j + 20] = normals[Triangles[i].vertex[2]].z;
351 vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
352 vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
353 vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
356 for (i = 0; i < TriangleNum; i++) {
358 vArray[j + 2] = facenormals[i].x * -1;
359 vArray[j + 3] = facenormals[i].y * -1;
360 vArray[j + 4] = facenormals[i].z * -1;
361 vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
362 vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
363 vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
365 vArray[j + 10] = facenormals[i].x * -1;
366 vArray[j + 11] = facenormals[i].y * -1;
367 vArray[j + 12] = facenormals[i].z * -1;
368 vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
369 vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
370 vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
372 vArray[j + 18] = facenormals[i].x * -1;
373 vArray[j + 19] = facenormals[i].y * -1;
374 vArray[j + 20] = facenormals[i].z * -1;
375 vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
376 vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
377 vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
381 void Model::UpdateVertexArrayNoTexNoNorm()
383 if (type != normaltype && type != decalstype)
387 for (i = 0; i < TriangleNum; i++) {
389 vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
390 vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
391 vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
393 vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
394 vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
395 vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
397 vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
398 vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
399 vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
403 bool Model::loadnotex(const std::string& filename )
411 tfile = Folders::openMandatoryFile( Folders::getResourcePath(filename), "rb" );
413 // read model settings
415 fseek(tfile, 0, SEEK_SET);
416 funpackf(tfile, "Bs Bs", &vertexNum, &TriangleNum);
418 // read the model data
423 owner = (int*)malloc(sizeof(int) * vertexNum);
424 possible = (int*)malloc(sizeof(int) * TriangleNum);
425 vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
426 Triangles = (TexturedTriangle*)malloc(sizeof(TexturedTriangle) * TriangleNum);
427 vArray = (GLfloat*)malloc(sizeof(GLfloat) * TriangleNum * 24);
429 for (i = 0; i < vertexNum; i++) {
430 funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
433 for (i = 0; i < TriangleNum; i++) {
435 funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[ 0], &vertex[ 1], &vertex[ 2], &vertex[ 3], &vertex[ 4], &vertex[ 5]);
436 Triangles[i].vertex[ 0] = vertex[ 0];
437 Triangles[i].vertex[ 1] = vertex[ 2];
438 Triangles[i].vertex[ 2] = vertex[ 4];
439 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
440 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
447 for (i = 0; i < vertexNum; i++) {
452 boundingsphereradius = 0;
453 for (i = 0; i < vertexNum; i++) {
454 for (j = 0; j < vertexNum; j++) {
455 if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
456 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
457 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
461 boundingsphereradius = fast_sqrt(boundingsphereradius);
467 bool Model::load(const std::string& filename, bool texture )
474 LOG(std::string("Loading model...") + filename);
477 Game::LoadingScreen();
482 tfile = Folders::openMandatoryFile( Folders::getResourcePath(filename), "rb" );
484 // read model settings
486 fseek(tfile, 0, SEEK_SET);
487 funpackf(tfile, "Bs Bs", &vertexNum, &TriangleNum);
489 // read the model data
494 owner = (int*)malloc(sizeof(int) * vertexNum);
495 possible = (int*)malloc(sizeof(int) * TriangleNum);
496 vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
497 normals = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
498 facenormals = (XYZ*)malloc(sizeof(XYZ) * TriangleNum);
499 Triangles = (TexturedTriangle*)malloc(sizeof(TexturedTriangle) * TriangleNum);
500 vArray = (GLfloat*)malloc(sizeof(GLfloat) * TriangleNum * 24);
502 for (i = 0; i < vertexNum; i++) {
503 funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
506 for (i = 0; i < TriangleNum; i++) {
508 funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[ 0], &vertex[ 1], &vertex[ 2], &vertex[ 3], &vertex[ 4], &vertex[ 5]);
509 Triangles[i].vertex[ 0] = vertex[ 0];
510 Triangles[i].vertex[ 1] = vertex[ 2];
511 Triangles[i].vertex[ 2] = vertex[ 4];
512 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
513 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
516 modelTexture.xsz = 0;
522 for (i = 0; i < vertexNum; i++) {
527 boundingsphereradius = 0;
528 for (i = 0; i < vertexNum; i++) {
529 for (j = 0; j < vertexNum; j++) {
530 if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
531 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
532 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
536 boundingsphereradius = fast_sqrt(boundingsphereradius);
541 bool Model::loaddecal(const std::string& filename, bool texture )
548 LOG(std::string("Loading decal...") + Folders::getResourcePath(filename));
554 tfile = Folders::openMandatoryFile( Folders::getResourcePath(filename), "rb" );
556 // read model settings
558 fseek(tfile, 0, SEEK_SET);
559 funpackf(tfile, "Bs Bs", &vertexNum, &TriangleNum);
561 // read the model data
567 owner = (int*)malloc(sizeof(int) * vertexNum);
568 possible = (int*)malloc(sizeof(int) * TriangleNum);
569 vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
570 normals = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
571 facenormals = (XYZ*)malloc(sizeof(XYZ) * TriangleNum);
572 Triangles = (TexturedTriangle*)malloc(sizeof(TexturedTriangle) * TriangleNum);
573 vArray = (GLfloat*)malloc(sizeof(GLfloat) * TriangleNum * 24);
576 for (i = 0; i < vertexNum; i++) {
577 funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
580 for (i = 0; i < TriangleNum; i++) {
582 funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[ 0], &vertex[ 1], &vertex[ 2], &vertex[ 3], &vertex[ 4], &vertex[ 5]);
583 Triangles[i].vertex[ 0] = vertex[ 0];
584 Triangles[i].vertex[ 1] = vertex[ 2];
585 Triangles[i].vertex[ 2] = vertex[ 4];
586 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
587 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
591 modelTexture.xsz = 0;
597 for (i = 0; i < vertexNum; i++) {
601 boundingsphereradius = 0;
602 for (i = 0; i < vertexNum; i++) {
603 for (j = 0; j < vertexNum; j++) {
604 if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
605 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
606 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
610 boundingsphereradius = fast_sqrt(boundingsphereradius);
613 if (!decaltexcoords) {
614 decaltexcoords = (float***)malloc(sizeof(float**)*max_model_decals);
615 for (i = 0; i < max_model_decals; i++) {
616 decaltexcoords[i] = (float**)malloc(sizeof(float*) * 3);
617 for (j = 0; j < 3; j++) {
618 decaltexcoords[i][j] = (float*)malloc(sizeof(float) * 2);
621 decalvertex = (XYZ**)malloc(sizeof(XYZ*)*max_model_decals);
622 for (i = 0; i < max_model_decals; i++) {
623 decalvertex[i] = (XYZ*)malloc(sizeof(XYZ) * 3);
626 decaltype = (int*)malloc(sizeof(int) * max_model_decals);
627 decalopacity = (float*)malloc(sizeof(float) * max_model_decals);
628 decalrotation = (float*)malloc(sizeof(float) * max_model_decals);
629 decalalivetime = (float*)malloc(sizeof(float) * max_model_decals);
630 decalposition = (XYZ*)malloc(sizeof(XYZ) * max_model_decals);
636 bool Model::loadraw(const std::string& filename)
643 LOG(std::string("Loading raw...") + filename);
648 tfile = Folders::openMandatoryFile( Folders::getResourcePath(filename), "rb" );
650 // read model settings
652 fseek(tfile, 0, SEEK_SET);
653 funpackf(tfile, "Bs Bs", &vertexNum, &TriangleNum);
655 // read the model data
660 owner = (int*)malloc(sizeof(int) * vertexNum);
661 possible = (int*)malloc(sizeof(int) * TriangleNum);
662 vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
663 Triangles = (TexturedTriangle*)malloc(sizeof(TexturedTriangle) * TriangleNum);
664 vArray = (GLfloat*)malloc(sizeof(GLfloat) * TriangleNum * 24);
667 for (i = 0; i < vertexNum; i++) {
668 funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
671 for (i = 0; i < TriangleNum; i++) {
673 funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[ 0], &vertex[ 1], &vertex[ 2], &vertex[ 3], &vertex[ 4], &vertex[ 5]);
674 Triangles[i].vertex[ 0] = vertex[ 0];
675 Triangles[i].vertex[ 1] = vertex[ 2];
676 Triangles[i].vertex[ 2] = vertex[ 4];
677 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
678 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
684 for (i = 0; i < vertexNum; i++) {
692 void Model::UniformTexCoords()
695 for (i = 0; i < TriangleNum; i++) {
696 Triangles[i].gy[0] = vertex[Triangles[i].vertex[0]].y;
697 Triangles[i].gy[1] = vertex[Triangles[i].vertex[1]].y;
698 Triangles[i].gy[2] = vertex[Triangles[i].vertex[2]].y;
699 Triangles[i].gx[0] = vertex[Triangles[i].vertex[0]].x;
700 Triangles[i].gx[1] = vertex[Triangles[i].vertex[1]].x;
701 Triangles[i].gx[2] = vertex[Triangles[i].vertex[2]].x;
707 void Model::FlipTexCoords()
710 for (i = 0; i < TriangleNum; i++) {
711 Triangles[i].gy[0] = -Triangles[i].gy[0];
712 Triangles[i].gy[1] = -Triangles[i].gy[1];
713 Triangles[i].gy[2] = -Triangles[i].gy[2];
718 void Model::ScaleTexCoords(float howmuch)
721 for (i = 0; i < TriangleNum; i++) {
722 Triangles[i].gx[0] *= howmuch;
723 Triangles[i].gx[1] *= howmuch;
724 Triangles[i].gx[2] *= howmuch;
725 Triangles[i].gy[0] *= howmuch;
726 Triangles[i].gy[1] *= howmuch;
727 Triangles[i].gy[2] *= howmuch;
732 void Model::Scale(float xscale, float yscale, float zscale)
735 for (i = 0; i < vertexNum; i++) {
736 vertex[i].x *= xscale;
737 vertex[i].y *= yscale;
738 vertex[i].z *= zscale;
744 boundingsphereradius = 0;
745 for (i = 0; i < vertexNum; i++) {
746 for (j = 0; j < vertexNum; j++) {
747 if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
748 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
749 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
753 boundingsphereradius = fast_sqrt(boundingsphereradius);
756 void Model::ScaleNormals(float xscale, float yscale, float zscale)
758 if (type != normaltype && type != decalstype)
761 for (i = 0; i < vertexNum; i++) {
762 normals[i].x *= xscale;
763 normals[i].y *= yscale;
764 normals[i].z *= zscale;
766 for (i = 0; i < TriangleNum; i++) {
767 facenormals[i].x *= xscale;
768 facenormals[i].y *= yscale;
769 facenormals[i].z *= zscale;
774 void Model::Translate(float xtrans, float ytrans, float ztrans)
777 for (i = 0; i < vertexNum; i++) {
778 vertex[i].x += xtrans;
779 vertex[i].y += ytrans;
780 vertex[i].z += ztrans;
785 boundingsphereradius = 0;
786 for (i = 0; i < vertexNum; i++) {
787 for (j = 0; j < vertexNum; j++) {
788 if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
789 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
790 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
794 boundingsphereradius = fast_sqrt(boundingsphereradius);
797 void Model::Rotate(float xang, float yang, float zang)
800 for (i = 0; i < vertexNum; i++) {
801 vertex[i] = DoRotation(vertex[i], xang, yang, zang);
806 boundingsphereradius = 0;
807 for (i = 0; i < vertexNum; i++) {
808 for (j = 0; j < vertexNum; j++) {
809 if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
810 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
811 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
815 boundingsphereradius = fast_sqrt(boundingsphereradius);
819 void Model::CalculateNormals(bool facenormalise)
822 Game::LoadingScreen();
824 if (type != normaltype && type != decalstype)
827 for (i = 0; i < vertexNum; i++) {
833 for (i = 0; i < TriangleNum; i++) {
834 CrossProduct(vertex[Triangles[i].vertex[1]] - vertex[Triangles[i].vertex[0]], vertex[Triangles[i].vertex[2]] - vertex[Triangles[i].vertex[0]], &facenormals[i]);
836 normals[Triangles[i].vertex[0]].x += facenormals[i].x;
837 normals[Triangles[i].vertex[0]].y += facenormals[i].y;
838 normals[Triangles[i].vertex[0]].z += facenormals[i].z;
840 normals[Triangles[i].vertex[1]].x += facenormals[i].x;
841 normals[Triangles[i].vertex[1]].y += facenormals[i].y;
842 normals[Triangles[i].vertex[1]].z += facenormals[i].z;
844 normals[Triangles[i].vertex[2]].x += facenormals[i].x;
845 normals[Triangles[i].vertex[2]].y += facenormals[i].y;
846 normals[Triangles[i].vertex[2]].z += facenormals[i].z;
848 Normalise(&facenormals[i]);
850 for (i = 0; i < vertexNum; i++) {
851 Normalise(&normals[i]);
854 UpdateVertexArrayNoTex();
857 void Model::drawimmediate()
860 glBegin(GL_TRIANGLES);
861 for (int i = 0; i < TriangleNum; i++) {
862 glTexCoord2f(Triangles[i].gx[0], Triangles[i].gy[0]);
864 glColor3f(normals[Triangles[i].vertex[0]].x, normals[Triangles[i].vertex[0]].y, normals[Triangles[i].vertex[0]].z);
866 glNormal3f(normals[Triangles[i].vertex[0]].x, normals[Triangles[i].vertex[0]].y, normals[Triangles[i].vertex[0]].z);
868 glNormal3f(facenormals[i].x, facenormals[i].y, facenormals[i].y);
869 glVertex3f(vertex[Triangles[i].vertex[0]].x, vertex[Triangles[i].vertex[0]].y, vertex[Triangles[i].vertex[0]].z);
871 glTexCoord2f(Triangles[i].gx[1], Triangles[i].gy[1]);
873 glColor3f(normals[Triangles[i].vertex[1]].x, normals[Triangles[i].vertex[1]].y, normals[Triangles[i].vertex[1]].z);
875 glNormal3f(normals[Triangles[i].vertex[1]].x, normals[Triangles[i].vertex[1]].y, normals[Triangles[i].vertex[1]].z);
877 glNormal3f(facenormals[i].x, facenormals[i].y, facenormals[i].y);
878 glVertex3f(vertex[Triangles[i].vertex[1]].x, vertex[Triangles[i].vertex[1]].y, vertex[Triangles[i].vertex[1]].z);
880 glTexCoord2f(Triangles[i].gx[2], Triangles[i].gy[2]);
882 glColor3f(normals[Triangles[i].vertex[2]].x, normals[Triangles[i].vertex[2]].y, normals[Triangles[i].vertex[2]].z);
884 glNormal3f(normals[Triangles[i].vertex[2]].x, normals[Triangles[i].vertex[2]].y, normals[Triangles[i].vertex[2]].z);
886 glNormal3f(facenormals[i].x, facenormals[i].y, facenormals[i].y);
887 glVertex3f(vertex[Triangles[i].vertex[2]].x, vertex[Triangles[i].vertex[2]].y, vertex[Triangles[i].vertex[2]].z);
894 if (type != normaltype && type != decalstype)
897 glEnableClientState(GL_NORMAL_ARRAY);
898 glEnableClientState(GL_VERTEX_ARRAY);
899 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
902 glInterleavedArrays( GL_T2F_N3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
904 glInterleavedArrays( GL_T2F_C3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
907 glDrawArrays(GL_TRIANGLES, 0, TriangleNum * 3);
910 glDisableClientState(GL_NORMAL_ARRAY);
912 glDisableClientState(GL_COLOR_ARRAY);
913 glDisableClientState(GL_VERTEX_ARRAY);
914 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
917 //TODO: phase out in favor of Texture
918 void Model::drawdifftex(GLuint texture)
920 glEnableClientState(GL_NORMAL_ARRAY);
921 glEnableClientState(GL_VERTEX_ARRAY);
922 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
924 glInterleavedArrays( GL_T2F_N3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
926 glInterleavedArrays( GL_T2F_C3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
928 glBindTexture(GL_TEXTURE_2D, (unsigned long)texture);
929 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
930 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
934 glLockArraysEXT( 0, TriangleNum * 3);
936 glDrawArrays(GL_TRIANGLES, 0, TriangleNum * 3);
943 glDisableClientState(GL_NORMAL_ARRAY);
945 glDisableClientState(GL_COLOR_ARRAY);
946 glDisableClientState(GL_VERTEX_ARRAY);
947 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
950 void Model::drawdifftex(Texture texture)
952 glEnableClientState(GL_NORMAL_ARRAY);
953 glEnableClientState(GL_VERTEX_ARRAY);
954 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
956 glInterleavedArrays( GL_T2F_N3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
958 glInterleavedArrays( GL_T2F_C3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
961 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
962 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
966 glLockArraysEXT( 0, TriangleNum * 3);
968 glDrawArrays(GL_TRIANGLES, 0, TriangleNum * 3);
975 glDisableClientState(GL_NORMAL_ARRAY);
977 glDisableClientState(GL_COLOR_ARRAY);
978 glDisableClientState(GL_VERTEX_ARRAY);
979 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
982 void Model::drawdecals(Texture shadowtexture, Texture bloodtexture, Texture bloodtexture2, Texture breaktexture)
985 if (type != decalstype)
995 glDisable(GL_LIGHTING);
996 glDisable(GL_CULL_FACE);
997 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
999 if (numdecals > max_model_decals)
1000 numdecals = max_model_decals;
1001 for (i = 0; i < numdecals; i++) {
1002 if (decaltype[i] == blooddecalfast && decalalivetime[i] < 2)
1003 decalalivetime[i] = 2;
1005 if (decaltype[i] == shadowdecal && decaltype[i] != lasttype) {
1006 shadowtexture.bind();
1009 glAlphaFunc(GL_GREATER, 0.0001);
1010 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1013 if (decaltype[i] == breakdecal && decaltype[i] != lasttype) {
1014 breaktexture.bind();
1017 glAlphaFunc(GL_GREATER, 0.0001);
1018 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1021 if ((decaltype[i] == blooddecal || decaltype[i] == blooddecalslow) && decaltype[i] != lasttype) {
1022 bloodtexture.bind();
1025 glAlphaFunc(GL_GREATER, 0.15);
1026 glBlendFunc(GL_ONE, GL_ZERO);
1029 if ((decaltype[i] == blooddecalfast) && decaltype[i] != lasttype) {
1030 bloodtexture2.bind();
1033 glAlphaFunc(GL_GREATER, 0.15);
1034 glBlendFunc(GL_ONE, GL_ZERO);
1037 if (decaltype[i] == shadowdecal) {
1038 glColor4f(1, 1, 1, decalopacity[i]);
1040 if (decaltype[i] == breakdecal) {
1041 glColor4f(1, 1, 1, decalopacity[i]);
1042 if (decalalivetime[i] > 58)
1043 glColor4f(1, 1, 1, decalopacity[i] * (60 - decalalivetime[i]) / 2);
1045 if ((decaltype[i] == blooddecal || decaltype[i] == blooddecalfast || decaltype[i] == blooddecalslow)) {
1046 glColor4f(1, 1, 1, decalopacity[i]);
1047 if (decalalivetime[i] < 4)
1048 glColor4f(1, 1, 1, decalopacity[i]*decalalivetime[i]*.25);
1049 if (decalalivetime[i] > 58)
1050 glColor4f(1, 1, 1, decalopacity[i] * (60 - decalalivetime[i]) / 2);
1052 lasttype = decaltype[i];
1053 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1054 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1056 glMatrixMode(GL_MODELVIEW);
1058 glBegin(GL_TRIANGLES);
1059 for (int j = 0; j < 3; j++) {
1060 glTexCoord2f(decaltexcoords[i][j][0], decaltexcoords[i][j][1]);
1061 glVertex3f(decalvertex[i][j].x, decalvertex[i][j].y, decalvertex[i][j].z);
1066 for (i = numdecals - 1; i >= 0; i--) {
1067 decalalivetime[i] += multiplier;
1068 if (decaltype[i] == blooddecalslow)
1069 decalalivetime[i] -= multiplier * 2 / 3;
1070 if (decaltype[i] == blooddecalfast)
1071 decalalivetime[i] += multiplier * 4;
1072 if (decaltype[i] == shadowdecal)
1074 if ((decaltype[i] == blooddecal || decaltype[i] == blooddecalfast || decaltype[i] == blooddecalslow) && decalalivetime[i] >= 60)
1077 glAlphaFunc(GL_GREATER, 0.0001);
1078 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1082 void Model::DeleteDecal(int which)
1085 if (type != decalstype)
1087 decaltype[which] = decaltype[numdecals - 1];
1088 decalposition[which] = decalposition[numdecals - 1];
1089 for (int i = 0; i < 3; i++) {
1090 decalvertex[which][i] = decalvertex[numdecals - 1][i];
1091 decaltexcoords[which][i][0] = decaltexcoords[numdecals - 1][i][0];
1092 decaltexcoords[which][i][1] = decaltexcoords[numdecals - 1][i][1];
1094 decalrotation[which] = decalrotation[numdecals - 1];
1095 decalalivetime[which] = decalalivetime[numdecals - 1];
1096 decalopacity[which] = decalopacity[numdecals - 1];
1101 void Model::MakeDecal(int atype, XYZ *where, float *size, float *opacity, float *rotation)
1104 if (type != decalstype)
1107 static float placex, placez;
1109 static float distance;
1113 if (distsq(where, &boundingspherecenter) < (boundingsphereradius + *size) * (boundingsphereradius + *size))
1114 for (i = 0; i < TriangleNum; i++) {
1115 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)) {
1116 decalposition[numdecals] = *where;
1117 decaltype[numdecals] = atype;
1118 decalrotation[numdecals] = *rotation;
1119 decalalivetime[numdecals] = 0;
1120 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);
1121 decalopacity[numdecals] = *opacity - distance / 10;
1123 if (decalopacity[numdecals > 0]) {
1124 placex = vertex[Triangles[i].vertex[0]].x;
1125 placez = vertex[Triangles[i].vertex[0]].z;
1127 decaltexcoords[numdecals][0][0] = (placex - where->x) / (*size) / 2 + .5;
1128 decaltexcoords[numdecals][0][1] = (placez - where->z) / (*size) / 2 + .5;
1130 decalvertex[numdecals][0].x = placex;
1131 decalvertex[numdecals][0].z = placez;
1132 decalvertex[numdecals][0].y = vertex[Triangles[i].vertex[0]].y;
1135 placex = vertex[Triangles[i].vertex[1]].x;
1136 placez = vertex[Triangles[i].vertex[1]].z;
1138 decaltexcoords[numdecals][1][0] = (placex - where->x) / (*size) / 2 + .5;
1139 decaltexcoords[numdecals][1][1] = (placez - where->z) / (*size) / 2 + .5;
1141 decalvertex[numdecals][1].x = placex;
1142 decalvertex[numdecals][1].z = placez;
1143 decalvertex[numdecals][1].y = vertex[Triangles[i].vertex[1]].y;
1146 placex = vertex[Triangles[i].vertex[2]].x;
1147 placez = vertex[Triangles[i].vertex[2]].z;
1149 decaltexcoords[numdecals][2][0] = (placex - where->x) / (*size) / 2 + .5;
1150 decaltexcoords[numdecals][2][1] = (placez - where->z) / (*size) / 2 + .5;
1152 decalvertex[numdecals][2].x = placex;
1153 decalvertex[numdecals][2].z = placez;
1154 decalvertex[numdecals][2].y = vertex[Triangles[i].vertex[2]].y;
1156 if (!(decaltexcoords[numdecals][0][0] < 0 && decaltexcoords[numdecals][1][0] < 0 && decaltexcoords[numdecals][2][0] < 0))
1157 if (!(decaltexcoords[numdecals][0][1] < 0 && decaltexcoords[numdecals][1][1] < 0 && decaltexcoords[numdecals][2][1] < 0))
1158 if (!(decaltexcoords[numdecals][0][0] > 1 && decaltexcoords[numdecals][1][0] > 1 && decaltexcoords[numdecals][2][0] > 1))
1159 if (!(decaltexcoords[numdecals][0][1] > 1 && decaltexcoords[numdecals][1][1] > 1 && decaltexcoords[numdecals][2][1] > 1)) {
1160 if (decalrotation[numdecals]) {
1161 for (j = 0; j < 3; j++) {
1163 rot.x = decaltexcoords[numdecals][j][0] - .5;
1164 rot.z = decaltexcoords[numdecals][j][1] - .5;
1165 rot = DoRotation(rot, 0, -decalrotation[numdecals], 0);
1166 decaltexcoords[numdecals][j][0] = rot.x + .5;
1167 decaltexcoords[numdecals][j][1] = rot.z + .5;
1170 if (numdecals < max_model_decals - 1)
1179 void Model::MakeDecal(int atype, XYZ where, float size, float opacity, float rotation)
1182 if (type != decalstype)
1185 static float placex, placez;
1187 static float distance;
1191 if (distsq(&where, &boundingspherecenter) < (boundingsphereradius + size) * (boundingsphereradius + size))
1192 for (i = 0; i < TriangleNum; i++) {
1193 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))));
1194 if (distance < .02 && abs(facenormals[i].y) > abs(facenormals[i].x) && abs(facenormals[i].y) > abs(facenormals[i].z)) {
1195 decalposition[numdecals] = where;
1196 decaltype[numdecals] = atype;
1197 decalrotation[numdecals] = rotation;
1198 decalalivetime[numdecals] = 0;
1199 decalopacity[numdecals] = opacity - distance / 10;
1201 if (decalopacity[numdecals > 0]) {
1202 placex = vertex[Triangles[i].vertex[0]].x;
1203 placez = vertex[Triangles[i].vertex[0]].z;
1205 decaltexcoords[numdecals][0][0] = (placex - where.x) / (size) / 2 + .5;
1206 decaltexcoords[numdecals][0][1] = (placez - where.z) / (size) / 2 + .5;
1208 decalvertex[numdecals][0].x = placex;
1209 decalvertex[numdecals][0].z = placez;
1210 decalvertex[numdecals][0].y = vertex[Triangles[i].vertex[0]].y;
1213 placex = vertex[Triangles[i].vertex[1]].x;
1214 placez = vertex[Triangles[i].vertex[1]].z;
1216 decaltexcoords[numdecals][1][0] = (placex - where.x) / (size) / 2 + .5;
1217 decaltexcoords[numdecals][1][1] = (placez - where.z) / (size) / 2 + .5;
1219 decalvertex[numdecals][1].x = placex;
1220 decalvertex[numdecals][1].z = placez;
1221 decalvertex[numdecals][1].y = vertex[Triangles[i].vertex[1]].y;
1224 placex = vertex[Triangles[i].vertex[2]].x;
1225 placez = vertex[Triangles[i].vertex[2]].z;
1227 decaltexcoords[numdecals][2][0] = (placex - where.x) / (size) / 2 + .5;
1228 decaltexcoords[numdecals][2][1] = (placez - where.z) / (size) / 2 + .5;
1230 decalvertex[numdecals][2].x = placex;
1231 decalvertex[numdecals][2].z = placez;
1232 decalvertex[numdecals][2].y = vertex[Triangles[i].vertex[2]].y;
1234 if (!(decaltexcoords[numdecals][0][0] < 0 && decaltexcoords[numdecals][1][0] < 0 && decaltexcoords[numdecals][2][0] < 0))
1235 if (!(decaltexcoords[numdecals][0][1] < 0 && decaltexcoords[numdecals][1][1] < 0 && decaltexcoords[numdecals][2][1] < 0))
1236 if (!(decaltexcoords[numdecals][0][0] > 1 && decaltexcoords[numdecals][1][0] > 1 && decaltexcoords[numdecals][2][0] > 1))
1237 if (!(decaltexcoords[numdecals][0][1] > 1 && decaltexcoords[numdecals][1][1] > 1 && decaltexcoords[numdecals][2][1] > 1)) {
1238 if (decalrotation[numdecals]) {
1239 for (j = 0; j < 3; j++) {
1241 rot.x = decaltexcoords[numdecals][j][0] - .5;
1242 rot.z = decaltexcoords[numdecals][j][1] - .5;
1243 rot = DoRotation(rot, 0, -decalrotation[numdecals], 0);
1244 decaltexcoords[numdecals][j][0] = rot.x + .5;
1245 decaltexcoords[numdecals][j][1] = rot.z + .5;
1248 if (numdecals < max_model_decals - 1)
1252 } else if (distance < .02 && abs(facenormals[i].x) > abs(facenormals[i].y) && abs(facenormals[i].x) > abs(facenormals[i].z)) {
1253 decalposition[numdecals] = where;
1254 decaltype[numdecals] = atype;
1255 decalrotation[numdecals] = rotation;
1256 decalalivetime[numdecals] = 0;
1257 decalopacity[numdecals] = opacity - distance / 10;
1259 if (decalopacity[numdecals > 0]) {
1260 placex = vertex[Triangles[i].vertex[0]].y;
1261 placez = vertex[Triangles[i].vertex[0]].z;
1263 decaltexcoords[numdecals][0][0] = (placex - where.y) / (size) / 2 + .5;
1264 decaltexcoords[numdecals][0][1] = (placez - where.z) / (size) / 2 + .5;
1266 decalvertex[numdecals][0].x = vertex[Triangles[i].vertex[0]].x;
1267 decalvertex[numdecals][0].z = placez;
1268 decalvertex[numdecals][0].y = placex;
1271 placex = vertex[Triangles[i].vertex[1]].y;
1272 placez = vertex[Triangles[i].vertex[1]].z;
1274 decaltexcoords[numdecals][1][0] = (placex - where.y) / (size) / 2 + .5;
1275 decaltexcoords[numdecals][1][1] = (placez - where.z) / (size) / 2 + .5;
1277 decalvertex[numdecals][1].x = vertex[Triangles[i].vertex[1]].x;
1278 decalvertex[numdecals][1].z = placez;
1279 decalvertex[numdecals][1].y = placex;
1282 placex = vertex[Triangles[i].vertex[2]].y;
1283 placez = vertex[Triangles[i].vertex[2]].z;
1285 decaltexcoords[numdecals][2][0] = (placex - where.y) / (size) / 2 + .5;
1286 decaltexcoords[numdecals][2][1] = (placez - where.z) / (size) / 2 + .5;
1288 decalvertex[numdecals][2].x = vertex[Triangles[i].vertex[2]].x;
1289 decalvertex[numdecals][2].z = placez;
1290 decalvertex[numdecals][2].y = placex;
1292 if (!(decaltexcoords[numdecals][0][0] < 0 && decaltexcoords[numdecals][1][0] < 0 && decaltexcoords[numdecals][2][0] < 0))
1293 if (!(decaltexcoords[numdecals][0][1] < 0 && decaltexcoords[numdecals][1][1] < 0 && decaltexcoords[numdecals][2][1] < 0))
1294 if (!(decaltexcoords[numdecals][0][0] > 1 && decaltexcoords[numdecals][1][0] > 1 && decaltexcoords[numdecals][2][0] > 1))
1295 if (!(decaltexcoords[numdecals][0][1] > 1 && decaltexcoords[numdecals][1][1] > 1 && decaltexcoords[numdecals][2][1] > 1)) {
1296 if (decalrotation[numdecals]) {
1297 for (j = 0; j < 3; j++) {
1299 rot.x = decaltexcoords[numdecals][j][0] - .5;
1300 rot.z = decaltexcoords[numdecals][j][1] - .5;
1301 rot = DoRotation(rot, 0, -decalrotation[numdecals], 0);
1302 decaltexcoords[numdecals][j][0] = rot.x + .5;
1303 decaltexcoords[numdecals][j][1] = rot.z + .5;
1306 if (numdecals < max_model_decals - 1)
1310 } else if (distance < .02 && abs(facenormals[i].z) > abs(facenormals[i].y) && abs(facenormals[i].z) > abs(facenormals[i].x)) {
1311 decalposition[numdecals] = where;
1312 decaltype[numdecals] = atype;
1313 decalrotation[numdecals] = rotation;
1314 decalalivetime[numdecals] = 0;
1315 decalopacity[numdecals] = opacity - distance / 10;
1317 if (decalopacity[numdecals > 0]) {
1318 placex = vertex[Triangles[i].vertex[0]].x;
1319 placez = vertex[Triangles[i].vertex[0]].y;
1321 decaltexcoords[numdecals][0][0] = (placex - where.x) / (size) / 2 + .5;
1322 decaltexcoords[numdecals][0][1] = (placez - where.y) / (size) / 2 + .5;
1324 decalvertex[numdecals][0].x = placex;
1325 decalvertex[numdecals][0].z = vertex[Triangles[i].vertex[0]].z;
1326 decalvertex[numdecals][0].y = placez;
1329 placex = vertex[Triangles[i].vertex[1]].x;
1330 placez = vertex[Triangles[i].vertex[1]].y;
1332 decaltexcoords[numdecals][1][0] = (placex - where.x) / (size) / 2 + .5;
1333 decaltexcoords[numdecals][1][1] = (placez - where.y) / (size) / 2 + .5;
1335 decalvertex[numdecals][1].x = placex;
1336 decalvertex[numdecals][1].z = vertex[Triangles[i].vertex[1]].z;
1337 decalvertex[numdecals][1].y = placez;
1340 placex = vertex[Triangles[i].vertex[2]].x;
1341 placez = vertex[Triangles[i].vertex[2]].y;
1343 decaltexcoords[numdecals][2][0] = (placex - where.x) / (size) / 2 + .5;
1344 decaltexcoords[numdecals][2][1] = (placez - where.y) / (size) / 2 + .5;
1346 decalvertex[numdecals][2].x = placex;
1347 decalvertex[numdecals][2].z = vertex[Triangles[i].vertex[2]].z;
1348 decalvertex[numdecals][2].y = placez;
1350 if (!(decaltexcoords[numdecals][0][0] < 0 && decaltexcoords[numdecals][1][0] < 0 && decaltexcoords[numdecals][2][0] < 0))
1351 if (!(decaltexcoords[numdecals][0][1] < 0 && decaltexcoords[numdecals][1][1] < 0 && decaltexcoords[numdecals][2][1] < 0))
1352 if (!(decaltexcoords[numdecals][0][0] > 1 && decaltexcoords[numdecals][1][0] > 1 && decaltexcoords[numdecals][2][0] > 1))
1353 if (!(decaltexcoords[numdecals][0][1] > 1 && decaltexcoords[numdecals][1][1] > 1 && decaltexcoords[numdecals][2][1] > 1)) {
1354 if (decalrotation[numdecals]) {
1355 for (j = 0; j < 3; j++) {
1357 rot.x = decaltexcoords[numdecals][j][0] - .5;
1358 rot.z = decaltexcoords[numdecals][j][1] - .5;
1359 rot = DoRotation(rot, 0, -decalrotation[numdecals], 0);
1360 decaltexcoords[numdecals][j][0] = rot.x + .5;
1361 decaltexcoords[numdecals][j][1] = rot.z + .5;
1364 if (numdecals < max_model_decals - 1)
1376 textureptr.destroy();
1379 void Model::deallocate()
1413 if (decaltexcoords) {
1414 for (i = 0; i < max_model_decals; i++) {
1415 for (j = 0; j < 3; j++) {
1416 free(decaltexcoords[i][j]);
1418 free(decaltexcoords[i]);
1420 free(decaltexcoords);
1426 for (i = 0; i < max_model_decals; i++) {
1427 free(decalvertex[i]);
1440 free(decalrotation);
1443 free(decalalivetime);
1446 free(decalposition);
1453 vertexNum = 0, TriangleNum = 0;
1456 type = 0, oldtype = 0;
1466 memset(&modelTexture, 0, sizeof(modelTexture));
1470 boundingspherecenter = 0;
1471 boundingsphereradius = 0;