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;
31 extern bool decalstoggle;
33 int Model::LineCheck(XYZ *p1, XYZ *p2, XYZ *p, XYZ *move, float *rotate)
35 static float distance;
36 static float olddistance;
37 static int intersecting;
38 static int firstintersecting;
44 *p1 = DoRotation(*p1, 0, -*rotate, 0);
46 *p2 = DoRotation(*p2, 0, -*rotate, 0);
47 if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius))
49 firstintersecting = -1;
51 for (unsigned int j = 0; j < Triangles.size(); j++) {
52 intersecting = LineFacetd(p1, p2, &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], &Triangles[j].facenormal, &point);
53 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);
54 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
55 olddistance = distance;
56 firstintersecting = j;
62 *p = DoRotation(*p, 0, *rotate, 0);
64 return firstintersecting;
67 int Model::LineCheckPossible(XYZ *p1, XYZ *p2, XYZ *p, XYZ *move, float *rotate)
69 static float distance;
70 static float olddistance;
71 static int intersecting;
72 static int firstintersecting;
77 if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius))
79 firstintersecting = -1;
81 *p1 = DoRotation(*p1, 0, -*rotate, 0);
83 *p2 = DoRotation(*p2, 0, -*rotate, 0);
85 if (numpossible > 0 && numpossible < int(Triangles.size())) {
86 for (unsigned int j = 0; int(j) < numpossible; j++) {
87 if ((possible[j] >= 0) && possible[j] < int(Triangles.size())) {
88 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);
89 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);
90 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
91 olddistance = distance;
92 firstintersecting = possible[j];
100 *p = DoRotation(*p, 0, *rotate, 0);
102 return firstintersecting;
105 int Model::LineCheckSlidePossible(XYZ *p1, XYZ *p2, XYZ *move, float *rotate)
108 static float distance;
109 static float olddistance;
110 static int intersecting;
111 static int firstintersecting;
116 if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius))
118 firstintersecting = -1;
120 *p1 = DoRotation(*p1, 0, -*rotate, 0);
122 *p2 = DoRotation(*p2, 0, -*rotate, 0);
125 for (j = 0; j < numpossible; j++) {
126 if (possible[j] >= 0 && possible[j] < int(Triangles.size())) {
127 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);
128 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);
129 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
130 olddistance = distance;
131 firstintersecting = possible[j];
136 if (firstintersecting > 0) {
137 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)));
138 *p2 -= Triangles[firstintersecting].facenormal * distance;
142 *p2 = DoRotation(*p2, 0, *rotate, 0);
144 return firstintersecting;
147 int Model::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate)
150 static float distance;
151 static float olddistance;
152 static int intersecting;
153 static int firstintersecting;
157 firstintersecting = -1;
162 *p1 = DoRotation(*p1, 0, -*rotate, 0);
163 if (distsq(p1, &boundingspherecenter) > radius * radius + boundingsphereradius * boundingsphereradius)
166 for (i = 0; i < 4; i++) {
167 for (unsigned int j = 0; j < Triangles.size(); j++) {
169 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)));
170 if (distance < radius) {
171 point = *p1 - Triangles[j].facenormal * distance;
172 if (PointInTriangle( &point, Triangles[j].facenormal, &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]]))
175 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], p1, &radius);
177 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], p1, &radius);
179 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[2]], p1, &radius);
181 *p1 += Triangles[j].facenormal * (distance - radius);
184 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
185 olddistance = distance;
186 firstintersecting = j;
192 *p = DoRotation(*p, 0, *rotate, 0);
195 *p1 = DoRotation(*p1, 0, *rotate, 0);
197 return firstintersecting;
200 int Model::SphereCheckPossible(XYZ *p1, float radius, XYZ *move, float *rotate)
202 static float distance;
203 static float olddistance;
204 static int intersecting;
205 static int firstintersecting;
209 firstintersecting = -1;
217 *p1 = DoRotation(*p1, 0, -*rotate, 0);
218 if (distsq(p1, &boundingspherecenter) > radius * radius + boundingsphereradius * boundingsphereradius) {
223 for (unsigned int j = 0; j < Triangles.size(); j++) {
225 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)));
226 if (distance < radius) {
227 point = *p1 - Triangles[j].facenormal * distance;
228 if (PointInTriangle( &point, Triangles[j].facenormal, &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]]))
231 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], p1, &radius);
233 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], p1, &radius);
235 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[2]], p1, &radius);
237 possible[numpossible] = j;
241 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
242 olddistance = distance;
243 firstintersecting = j;
247 *p1 = DoRotation(*p1, 0, *rotate, 0);
249 return firstintersecting;
253 void Model::UpdateVertexArray()
255 if (type != normaltype && type != decalstype)
259 for (unsigned int i = 0; i < Triangles.size(); i++) {
260 unsigned int j = i * 24;
261 vArray[j + 0] = Triangles[i].gx[0];
262 vArray[j + 1] = Triangles[i].gy[0];
263 vArray[j + 2] = Triangles[i].facenormal.x * -1;
264 vArray[j + 3] = Triangles[i].facenormal.y * -1;
265 vArray[j + 4] = Triangles[i].facenormal.z * -1;
266 vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
267 vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
268 vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
270 vArray[j + 8] = Triangles[i].gx[1];
271 vArray[j + 9] = Triangles[i].gy[1];
272 vArray[j + 10] = Triangles[i].facenormal.x * -1;
273 vArray[j + 11] = Triangles[i].facenormal.y * -1;
274 vArray[j + 12] = Triangles[i].facenormal.z * -1;
275 vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
276 vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
277 vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
279 vArray[j + 16] = Triangles[i].gx[2];
280 vArray[j + 17] = Triangles[i].gy[2];
281 vArray[j + 18] = Triangles[i].facenormal.x * -1;
282 vArray[j + 19] = Triangles[i].facenormal.y * -1;
283 vArray[j + 20] = Triangles[i].facenormal.z * -1;
284 vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
285 vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
286 vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
289 for (unsigned int i = 0; i < Triangles.size(); i++) {
290 unsigned int j = i * 24;
291 vArray[j + 0] = Triangles[i].gx[0];
292 vArray[j + 1] = Triangles[i].gy[0];
293 vArray[j + 2] = normals[Triangles[i].vertex[0]].x;
294 vArray[j + 3] = normals[Triangles[i].vertex[0]].y;
295 vArray[j + 4] = normals[Triangles[i].vertex[0]].z;
296 vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
297 vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
298 vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
300 vArray[j + 8] = Triangles[i].gx[1];
301 vArray[j + 9] = Triangles[i].gy[1];
302 vArray[j + 10] = normals[Triangles[i].vertex[1]].x;
303 vArray[j + 11] = normals[Triangles[i].vertex[1]].y;
304 vArray[j + 12] = normals[Triangles[i].vertex[1]].z;
305 vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
306 vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
307 vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
309 vArray[j + 16] = Triangles[i].gx[2];
310 vArray[j + 17] = Triangles[i].gy[2];
311 vArray[j + 18] = normals[Triangles[i].vertex[2]].x;
312 vArray[j + 19] = normals[Triangles[i].vertex[2]].y;
313 vArray[j + 20] = normals[Triangles[i].vertex[2]].z;
314 vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
315 vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
316 vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
321 void Model::UpdateVertexArrayNoTex()
323 if (type != normaltype && type != decalstype)
327 for (unsigned int i = 0; i < Triangles.size(); i++) {
328 unsigned int j = i * 24;
329 vArray[j + 2] = Triangles[i].facenormal.x * -1;
330 vArray[j + 3] = Triangles[i].facenormal.y * -1;
331 vArray[j + 4] = Triangles[i].facenormal.z * -1;
332 vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
333 vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
334 vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
336 vArray[j + 10] = Triangles[i].facenormal.x * -1;
337 vArray[j + 11] = Triangles[i].facenormal.y * -1;
338 vArray[j + 12] = Triangles[i].facenormal.z * -1;
339 vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
340 vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
341 vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
343 vArray[j + 18] = Triangles[i].facenormal.x * -1;
344 vArray[j + 19] = Triangles[i].facenormal.y * -1;
345 vArray[j + 20] = Triangles[i].facenormal.z * -1;
346 vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
347 vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
348 vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
351 for (unsigned int i = 0; i < Triangles.size(); i++) {
352 unsigned int j = i * 24;
353 vArray[j + 2] = normals[Triangles[i].vertex[0]].x;
354 vArray[j + 3] = normals[Triangles[i].vertex[0]].y;
355 vArray[j + 4] = normals[Triangles[i].vertex[0]].z;
356 vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
357 vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
358 vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
360 vArray[j + 10] = normals[Triangles[i].vertex[1]].x;
361 vArray[j + 11] = normals[Triangles[i].vertex[1]].y;
362 vArray[j + 12] = normals[Triangles[i].vertex[1]].z;
363 vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
364 vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
365 vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
367 vArray[j + 18] = normals[Triangles[i].vertex[2]].x;
368 vArray[j + 19] = normals[Triangles[i].vertex[2]].y;
369 vArray[j + 20] = normals[Triangles[i].vertex[2]].z;
370 vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
371 vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
372 vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
377 void Model::UpdateVertexArrayNoTexNoNorm()
379 if (type != normaltype && type != decalstype)
382 for (unsigned int i = 0; i < Triangles.size(); i++) {
383 unsigned int j = i * 24;
384 vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
385 vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
386 vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
388 vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
389 vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
390 vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
392 vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
393 vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
394 vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
398 bool Model::loadnotex(const std::string& filename)
407 tfile = Folders::openMandatoryFile( Folders::getResourcePath(filename), "rb" );
409 // read model settings
411 fseek(tfile, 0, SEEK_SET);
412 funpackf(tfile, "Bs Bs", &vertexNum, &TriangleNum);
414 // read the model data
419 owner = (int*)malloc(sizeof(int) * vertexNum);
420 possible = (int*)malloc(sizeof(int) * TriangleNum);
421 vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
422 Triangles.resize(TriangleNum);
423 vArray = (GLfloat*)malloc(sizeof(GLfloat) * TriangleNum * 24);
425 for (i = 0; i < vertexNum; i++) {
426 funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
429 for (i = 0; i < TriangleNum; i++) {
431 funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[0], &vertex[1], &vertex[2], &vertex[3], &vertex[4], &vertex[5]);
432 Triangles[i].vertex[0] = vertex[0];
433 Triangles[i].vertex[1] = vertex[2];
434 Triangles[i].vertex[2] = vertex[4];
435 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
436 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
443 for (i = 0; i < vertexNum; i++) {
447 boundingsphereradius = 0;
448 for (i = 0; i < vertexNum; i++) {
449 for (int j = 0; j < vertexNum; j++) {
450 if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
451 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
452 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
456 boundingsphereradius = fast_sqrt(boundingsphereradius);
462 bool Model::load(const std::string& filename)
470 LOG(std::string("Loading model...") + filename);
472 Game::LoadingScreen();
477 tfile = Folders::openMandatoryFile( Folders::getResourcePath(filename), "rb" );
479 // read model settings
481 fseek(tfile, 0, SEEK_SET);
482 funpackf(tfile, "Bs Bs", &vertexNum, &TriangleNum);
484 // read the model data
489 owner = (int*)malloc(sizeof(int) * vertexNum);
490 possible = (int*)malloc(sizeof(int) * TriangleNum);
491 vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
492 normals = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
493 Triangles.resize(TriangleNum);
494 vArray = (GLfloat*)malloc(sizeof(GLfloat) * TriangleNum * 24);
496 for (i = 0; i < vertexNum; i++) {
497 funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
500 for (i = 0; i < TriangleNum; i++) {
502 funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[0], &vertex[1], &vertex[2], &vertex[3], &vertex[4], &vertex[5]);
503 Triangles[i].vertex[0] = vertex[0];
504 Triangles[i].vertex[1] = vertex[2];
505 Triangles[i].vertex[2] = vertex[4];
506 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
507 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
510 modelTexture.xsz = 0;
516 for (i = 0; i < vertexNum; i++) {
521 boundingsphereradius = 0;
522 for (i = 0; i < vertexNum; i++) {
523 for (j = 0; j < vertexNum; j++) {
524 if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
525 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
526 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
530 boundingsphereradius = fast_sqrt(boundingsphereradius);
535 bool Model::loaddecal(const std::string& filename)
543 LOG(std::string("Loading decal...") + Folders::getResourcePath(filename));
549 tfile = Folders::openMandatoryFile( Folders::getResourcePath(filename), "rb" );
551 // read model settings
553 fseek(tfile, 0, SEEK_SET);
554 funpackf(tfile, "Bs Bs", &vertexNum, &TriangleNum);
556 // read the model data
562 owner = (int*)malloc(sizeof(int) * vertexNum);
563 possible = (int*)malloc(sizeof(int) * TriangleNum);
564 vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
565 normals = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
566 Triangles.resize(TriangleNum);
567 vArray = (GLfloat*)malloc(sizeof(GLfloat) * TriangleNum * 24);
569 for (i = 0; i < vertexNum; i++) {
570 funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
573 for (i = 0; i < TriangleNum; i++) {
575 funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[0], &vertex[1], &vertex[2], &vertex[3], &vertex[4], &vertex[5]);
576 Triangles[i].vertex[0] = vertex[0];
577 Triangles[i].vertex[1] = vertex[2];
578 Triangles[i].vertex[2] = vertex[4];
579 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
580 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
584 modelTexture.xsz = 0;
590 for (i = 0; i < vertexNum; i++) {
594 boundingsphereradius = 0;
595 for (i = 0; i < vertexNum; i++) {
596 for (j = 0; j < vertexNum; j++) {
597 if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
598 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
599 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
603 boundingsphereradius = fast_sqrt(boundingsphereradius);
608 bool Model::loadraw(const std::string& filename)
616 LOG(std::string("Loading raw...") + filename);
621 tfile = Folders::openMandatoryFile( Folders::getResourcePath(filename), "rb" );
623 // read model settings
625 fseek(tfile, 0, SEEK_SET);
626 funpackf(tfile, "Bs Bs", &vertexNum, &TriangleNum);
628 // read the model data
633 owner = (int*)malloc(sizeof(int) * vertexNum);
634 possible = (int*)malloc(sizeof(int) * TriangleNum);
635 vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
636 Triangles.resize(TriangleNum);
637 vArray = (GLfloat*)malloc(sizeof(GLfloat) * TriangleNum * 24);
640 for (i = 0; i < vertexNum; i++) {
641 funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
644 for (i = 0; i < TriangleNum; i++) {
646 funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[0], &vertex[1], &vertex[2], &vertex[3], &vertex[4], &vertex[5]);
647 Triangles[i].vertex[0] = vertex[0];
648 Triangles[i].vertex[1] = vertex[2];
649 Triangles[i].vertex[2] = vertex[4];
650 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
651 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
657 for (i = 0; i < vertexNum; i++) {
665 void Model::UniformTexCoords()
667 for (unsigned int i = 0; i < Triangles.size(); i++) {
668 Triangles[i].gy[0] = vertex[Triangles[i].vertex[0]].y;
669 Triangles[i].gy[1] = vertex[Triangles[i].vertex[1]].y;
670 Triangles[i].gy[2] = vertex[Triangles[i].vertex[2]].y;
671 Triangles[i].gx[0] = vertex[Triangles[i].vertex[0]].x;
672 Triangles[i].gx[1] = vertex[Triangles[i].vertex[1]].x;
673 Triangles[i].gx[2] = vertex[Triangles[i].vertex[2]].x;
679 void Model::FlipTexCoords()
681 for (unsigned int i = 0; i < Triangles.size(); i++) {
682 Triangles[i].gy[0] = -Triangles[i].gy[0];
683 Triangles[i].gy[1] = -Triangles[i].gy[1];
684 Triangles[i].gy[2] = -Triangles[i].gy[2];
689 void Model::ScaleTexCoords(float howmuch)
691 for (unsigned int i = 0; i < Triangles.size(); i++) {
692 Triangles[i].gx[0] *= howmuch;
693 Triangles[i].gx[1] *= howmuch;
694 Triangles[i].gx[2] *= howmuch;
695 Triangles[i].gy[0] *= howmuch;
696 Triangles[i].gy[1] *= howmuch;
697 Triangles[i].gy[2] *= howmuch;
702 void Model::Scale(float xscale, float yscale, float zscale)
705 for (i = 0; i < vertexNum; i++) {
706 vertex[i].x *= xscale;
707 vertex[i].y *= yscale;
708 vertex[i].z *= zscale;
714 boundingsphereradius = 0;
715 for (i = 0; i < vertexNum; i++) {
716 for (j = 0; j < vertexNum; j++) {
717 if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
718 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
719 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
723 boundingsphereradius = fast_sqrt(boundingsphereradius);
726 void Model::ScaleNormals(float xscale, float yscale, float zscale)
728 if (type != normaltype && type != decalstype)
731 for (int i = 0; i < vertexNum; i++) {
732 normals[i].x *= xscale;
733 normals[i].y *= yscale;
734 normals[i].z *= zscale;
736 for (unsigned int i = 0; i < Triangles.size(); i++) {
737 Triangles[i].facenormal.x *= xscale;
738 Triangles[i].facenormal.y *= yscale;
739 Triangles[i].facenormal.z *= zscale;
744 void Model::Translate(float xtrans, float ytrans, float ztrans)
747 for (i = 0; i < vertexNum; i++) {
748 vertex[i].x += xtrans;
749 vertex[i].y += ytrans;
750 vertex[i].z += ztrans;
755 boundingsphereradius = 0;
756 for (i = 0; i < vertexNum; i++) {
757 for (j = 0; j < vertexNum; j++) {
758 if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
759 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
760 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
764 boundingsphereradius = fast_sqrt(boundingsphereradius);
767 void Model::Rotate(float xang, float yang, float zang)
770 for (i = 0; i < vertexNum; i++) {
771 vertex[i] = DoRotation(vertex[i], xang, yang, zang);
776 boundingsphereradius = 0;
777 for (i = 0; i < vertexNum; i++) {
778 for (j = 0; j < vertexNum; j++) {
779 if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
780 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
781 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
785 boundingsphereradius = fast_sqrt(boundingsphereradius);
789 void Model::CalculateNormals(bool facenormalise)
791 Game::LoadingScreen();
793 if (type != normaltype && type != decalstype)
796 for (int i = 0; i < vertexNum; i++) {
802 for (unsigned int i = 0; i < Triangles.size(); i++) {
803 CrossProduct(vertex[Triangles[i].vertex[1]] - vertex[Triangles[i].vertex[0]], vertex[Triangles[i].vertex[2]] - vertex[Triangles[i].vertex[0]], &Triangles[i].facenormal);
805 normals[Triangles[i].vertex[0]].x += Triangles[i].facenormal.x;
806 normals[Triangles[i].vertex[0]].y += Triangles[i].facenormal.y;
807 normals[Triangles[i].vertex[0]].z += Triangles[i].facenormal.z;
809 normals[Triangles[i].vertex[1]].x += Triangles[i].facenormal.x;
810 normals[Triangles[i].vertex[1]].y += Triangles[i].facenormal.y;
811 normals[Triangles[i].vertex[1]].z += Triangles[i].facenormal.z;
813 normals[Triangles[i].vertex[2]].x += Triangles[i].facenormal.x;
814 normals[Triangles[i].vertex[2]].y += Triangles[i].facenormal.y;
815 normals[Triangles[i].vertex[2]].z += Triangles[i].facenormal.z;
817 Normalise(&Triangles[i].facenormal);
819 for (int i = 0; i < vertexNum; i++) {
820 Normalise(&normals[i]);
823 UpdateVertexArrayNoTex();
826 void Model::drawimmediate()
829 glBegin(GL_TRIANGLES);
830 for (unsigned int i = 0; i < Triangles.size(); i++) {
831 glTexCoord2f(Triangles[i].gx[0], Triangles[i].gy[0]);
833 glColor3f(normals[Triangles[i].vertex[0]].x, normals[Triangles[i].vertex[0]].y, normals[Triangles[i].vertex[0]].z);
835 glNormal3f(normals[Triangles[i].vertex[0]].x, normals[Triangles[i].vertex[0]].y, normals[Triangles[i].vertex[0]].z);
837 glNormal3f(Triangles[i].facenormal.x, Triangles[i].facenormal.y, Triangles[i].facenormal.y);
838 glVertex3f(vertex[Triangles[i].vertex[0]].x, vertex[Triangles[i].vertex[0]].y, vertex[Triangles[i].vertex[0]].z);
840 glTexCoord2f(Triangles[i].gx[1], Triangles[i].gy[1]);
842 glColor3f(normals[Triangles[i].vertex[1]].x, normals[Triangles[i].vertex[1]].y, normals[Triangles[i].vertex[1]].z);
844 glNormal3f(normals[Triangles[i].vertex[1]].x, normals[Triangles[i].vertex[1]].y, normals[Triangles[i].vertex[1]].z);
846 glNormal3f(Triangles[i].facenormal.x, Triangles[i].facenormal.y, Triangles[i].facenormal.y);
847 glVertex3f(vertex[Triangles[i].vertex[1]].x, vertex[Triangles[i].vertex[1]].y, vertex[Triangles[i].vertex[1]].z);
849 glTexCoord2f(Triangles[i].gx[2], Triangles[i].gy[2]);
851 glColor3f(normals[Triangles[i].vertex[2]].x, normals[Triangles[i].vertex[2]].y, normals[Triangles[i].vertex[2]].z);
853 glNormal3f(normals[Triangles[i].vertex[2]].x, normals[Triangles[i].vertex[2]].y, normals[Triangles[i].vertex[2]].z);
855 glNormal3f(Triangles[i].facenormal.x, Triangles[i].facenormal.y, Triangles[i].facenormal.y);
856 glVertex3f(vertex[Triangles[i].vertex[2]].x, vertex[Triangles[i].vertex[2]].y, vertex[Triangles[i].vertex[2]].z);
863 if (type != normaltype && type != decalstype)
866 glEnableClientState(GL_NORMAL_ARRAY);
867 glEnableClientState(GL_VERTEX_ARRAY);
868 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
871 glInterleavedArrays( GL_T2F_N3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
873 glInterleavedArrays( GL_T2F_C3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
876 glDrawArrays(GL_TRIANGLES, 0, Triangles.size() * 3);
879 glDisableClientState(GL_NORMAL_ARRAY);
881 glDisableClientState(GL_COLOR_ARRAY);
882 glDisableClientState(GL_VERTEX_ARRAY);
883 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
886 //TODO: phase out in favor of Texture
887 void Model::drawdifftex(GLuint texture)
889 glEnableClientState(GL_NORMAL_ARRAY);
890 glEnableClientState(GL_VERTEX_ARRAY);
891 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
893 glInterleavedArrays( GL_T2F_N3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
895 glInterleavedArrays( GL_T2F_C3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
897 glBindTexture(GL_TEXTURE_2D, (unsigned long)texture);
898 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
899 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
901 glDrawArrays(GL_TRIANGLES, 0, Triangles.size() * 3);
904 glDisableClientState(GL_NORMAL_ARRAY);
906 glDisableClientState(GL_COLOR_ARRAY);
907 glDisableClientState(GL_VERTEX_ARRAY);
908 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
911 void Model::drawdifftex(Texture texture)
913 glEnableClientState(GL_NORMAL_ARRAY);
914 glEnableClientState(GL_VERTEX_ARRAY);
915 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
917 glInterleavedArrays( GL_T2F_N3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
919 glInterleavedArrays( GL_T2F_C3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
922 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
923 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
925 glDrawArrays(GL_TRIANGLES, 0, Triangles.size() * 3);
928 glDisableClientState(GL_NORMAL_ARRAY);
930 glDisableClientState(GL_COLOR_ARRAY);
931 glDisableClientState(GL_VERTEX_ARRAY);
932 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
935 void Model::drawdecals(Texture shadowtexture, Texture bloodtexture, Texture bloodtexture2, Texture breaktexture)
938 if (type != decalstype)
947 glDisable(GL_LIGHTING);
948 glDisable(GL_CULL_FACE);
949 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
951 for (unsigned int i = 0; i < decals.size(); i++) {
952 if (decals[i].type == blooddecalfast && decals[i].alivetime < 2)
953 decals[i].alivetime = 2;
955 if (decals[i].type != lasttype) {
956 if (decals[i].type == shadowdecal) {
957 shadowtexture.bind();
960 glAlphaFunc(GL_GREATER, 0.0001);
961 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
964 if (decals[i].type == breakdecal) {
968 glAlphaFunc(GL_GREATER, 0.0001);
969 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
972 if (decals[i].type == blooddecal || decals[i].type == blooddecalslow) {
976 glAlphaFunc(GL_GREATER, 0.15);
977 glBlendFunc(GL_ONE, GL_ZERO);
980 if (decals[i].type == blooddecalfast) {
981 bloodtexture2.bind();
984 glAlphaFunc(GL_GREATER, 0.15);
985 glBlendFunc(GL_ONE, GL_ZERO);
989 if (decals[i].type == shadowdecal) {
990 glColor4f(1, 1, 1, decals[i].opacity);
992 if (decals[i].type == breakdecal) {
993 glColor4f(1, 1, 1, decals[i].opacity);
994 if (decals[i].alivetime > 58)
995 glColor4f(1, 1, 1, decals[i].opacity * (60 - decals[i].alivetime) / 2);
997 if ((decals[i].type == blooddecal || decals[i].type == blooddecalfast || decals[i].type == blooddecalslow)) {
998 glColor4f(1, 1, 1, decals[i].opacity);
999 if (decals[i].alivetime < 4)
1000 glColor4f(1, 1, 1, decals[i].opacity*decals[i].alivetime*.25);
1001 if (decals[i].alivetime > 58)
1002 glColor4f(1, 1, 1, decals[i].opacity * (60 - decals[i].alivetime) / 2);
1004 lasttype = decals[i].type;
1005 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1006 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1008 glMatrixMode(GL_MODELVIEW);
1010 glBegin(GL_TRIANGLES);
1011 for (int j = 0; j < 3; j++) {
1012 glTexCoord2f(decals[i].texcoords[j][0], decals[i].texcoords[j][1]);
1013 glVertex3f(decals[i].vertex[j].x, decals[i].vertex[j].y, decals[i].vertex[j].z);
1018 for (int i = decals.size() - 1; i >= 0; i--) {
1019 decals[i].alivetime += multiplier;
1020 if (decals[i].type == blooddecalslow)
1021 decals[i].alivetime -= multiplier * 2 / 3;
1022 if (decals[i].type == blooddecalfast)
1023 decals[i].alivetime += multiplier * 4;
1024 if (decals[i].type == shadowdecal)
1026 if ((decals[i].type == blooddecal || decals[i].type == blooddecalfast || decals[i].type == blooddecalslow) && decals[i].alivetime >= 60)
1029 glAlphaFunc(GL_GREATER, 0.0001);
1030 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1034 void Model::DeleteDecal(int which)
1037 if (type != decalstype)
1039 decals.erase(decals.begin() + which);
1043 void Model::MakeDecal(decal_type atype, XYZ *where, float *size, float *opacity, float *rotation)
1046 if (type != decalstype)
1050 static float distance;
1053 if (distsq(where, &boundingspherecenter) < (boundingsphereradius + *size) * (boundingsphereradius + *size))
1054 for (unsigned int i = 0; i < Triangles.size(); i++) {
1055 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)) {
1056 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);
1058 if (*opacity - distance / 10 > 0) {
1059 Decal decal(*where, atype, *opacity - distance / 10, *rotation, *size, *this, i, 0);
1061 if (!(decal.texcoords[0][0] < 0 && decal.texcoords[1][0] < 0 && decal.texcoords[2][0] < 0))
1062 if (!(decal.texcoords[0][1] < 0 && decal.texcoords[1][1] < 0 && decal.texcoords[2][1] < 0))
1063 if (!(decal.texcoords[0][0] > 1 && decal.texcoords[1][0] > 1 && decal.texcoords[2][0] > 1))
1064 if (!(decal.texcoords[0][1] > 1 && decal.texcoords[1][1] > 1 && decal.texcoords[2][1] > 1)) {
1065 if (decal.rotation) {
1066 for (int j = 0; j < 3; j++) {
1068 rot.x = decal.texcoords[j][0] - .5;
1069 rot.z = decal.texcoords[j][1] - .5;
1070 rot = DoRotation(rot, 0, -decal.rotation, 0);
1071 decal.texcoords[j][0] = rot.x + .5;
1072 decal.texcoords[j][1] = rot.z + .5;
1075 if (decals.size() < max_model_decals - 1) {
1076 decals.push_back(decal);
1085 void Model::MakeDecal(decal_type atype, XYZ where, float size, float opacity, float rotation)
1088 if (type != decalstype)
1092 static float distance;
1095 if (distsq(&where, &boundingspherecenter) < (boundingsphereradius + size) * (boundingsphereradius + size))
1096 for (unsigned int i = 0; i < Triangles.size(); i++) {
1097 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))));
1098 if (distance < .02 && abs(Triangles[i].facenormal.y) > abs(Triangles[i].facenormal.x) && abs(Triangles[i].facenormal.y) > abs(Triangles[i].facenormal.z)) {
1099 if (opacity - distance / 10 > 0) {
1100 Decal decal(where, atype, opacity - distance / 10, rotation, size, *this, i, 0);
1102 if (!(decal.texcoords[0][0] < 0 && decal.texcoords[1][0] < 0 && decal.texcoords[2][0] < 0))
1103 if (!(decal.texcoords[0][1] < 0 && decal.texcoords[1][1] < 0 && decal.texcoords[2][1] < 0))
1104 if (!(decal.texcoords[0][0] > 1 && decal.texcoords[1][0] > 1 && decal.texcoords[2][0] > 1))
1105 if (!(decal.texcoords[0][1] > 1 && decal.texcoords[1][1] > 1 && decal.texcoords[2][1] > 1)) {
1106 if (decal.rotation) {
1107 for (int j = 0; j < 3; j++) {
1109 rot.x = decal.texcoords[j][0] - .5;
1110 rot.z = decal.texcoords[j][1] - .5;
1111 rot = DoRotation(rot, 0, -decal.rotation, 0);
1112 decal.texcoords[j][0] = rot.x + .5;
1113 decal.texcoords[j][1] = rot.z + .5;
1116 if (decals.size() < max_model_decals - 1) {
1117 decals.push_back(decal);
1121 } else if (distance < .02 && abs(Triangles[i].facenormal.x) > abs(Triangles[i].facenormal.y) && abs(Triangles[i].facenormal.x) > abs(Triangles[i].facenormal.z)) {
1122 if (opacity - distance / 10 > 0) {
1123 Decal decal(where, atype, opacity - distance / 10, rotation, size, *this, i, 1);
1125 if (!(decal.texcoords[0][0] < 0 && decal.texcoords[1][0] < 0 && decal.texcoords[2][0] < 0))
1126 if (!(decal.texcoords[0][1] < 0 && decal.texcoords[1][1] < 0 && decal.texcoords[2][1] < 0))
1127 if (!(decal.texcoords[0][0] > 1 && decal.texcoords[1][0] > 1 && decal.texcoords[2][0] > 1))
1128 if (!(decal.texcoords[0][1] > 1 && decal.texcoords[1][1] > 1 && decal.texcoords[2][1] > 1)) {
1129 if (decal.rotation) {
1130 for (int j = 0; j < 3; j++) {
1132 rot.x = decal.texcoords[j][0] - .5;
1133 rot.z = decal.texcoords[j][1] - .5;
1134 rot = DoRotation(rot, 0, -decal.rotation, 0);
1135 decal.texcoords[j][0] = rot.x + .5;
1136 decal.texcoords[j][1] = rot.z + .5;
1139 if (decals.size() < max_model_decals - 1) {
1140 decals.push_back(decal);
1144 } else if (distance < .02 && abs(Triangles[i].facenormal.z) > abs(Triangles[i].facenormal.y) && abs(Triangles[i].facenormal.z) > abs(Triangles[i].facenormal.x)) {
1145 if (opacity - distance / 10 > 0) {
1146 Decal decal(where, atype, opacity - distance / 10, rotation, size, *this, i, 2);
1148 if (!(decal.texcoords[0][0] < 0 && decal.texcoords[1][0] < 0 && decal.texcoords[2][0] < 0))
1149 if (!(decal.texcoords[0][1] < 0 && decal.texcoords[1][1] < 0 && decal.texcoords[2][1] < 0))
1150 if (!(decal.texcoords[0][0] > 1 && decal.texcoords[1][0] > 1 && decal.texcoords[2][0] > 1))
1151 if (!(decal.texcoords[0][1] > 1 && decal.texcoords[1][1] > 1 && decal.texcoords[2][1] > 1)) {
1152 if (decal.rotation) {
1153 for (int j = 0; j < 3; j++) {
1155 rot.x = decal.texcoords[j][0] - .5;
1156 rot.z = decal.texcoords[j][1] - .5;
1157 rot = DoRotation(rot, 0, -decal.rotation, 0);
1158 decal.texcoords[j][0] = rot.x + .5;
1159 decal.texcoords[j][1] = rot.z + .5;
1162 if (decals.size() < max_model_decals - 1) {
1163 decals.push_back(decal);
1172 void Model::deleteDeadDecals()
1174 for (int i = decals.size() - 1; i >= 0; i--) {
1175 if ((decals[i].type == blooddecal || decals[i].type == blooddecalslow) && decals[i].alivetime < 2) {
1186 void Model::deallocate()
1212 type(0), oldtype(0),
1219 memset(&modelTexture, 0, sizeof(modelTexture));
1223 boundingspherecenter = 0;
1224 boundingsphereradius = 0;