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);
47 *p2 = DoRotation(*p2, 0, -*rotate, 0);
49 if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius)) {
52 firstintersecting = -1;
54 for (unsigned int j = 0; j < Triangles.size(); j++) {
55 intersecting = LineFacetd(p1, p2, &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], &Triangles[j].facenormal, &point);
56 distance = (point.x - p1->x) * (point.x - p1->x) + (point.y - p1->y) * (point.y - p1->y) + (point.z - p1->z) * (point.z - p1->z);
57 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
58 olddistance = distance;
59 firstintersecting = j;
65 *p = DoRotation(*p, 0, *rotate, 0);
68 return firstintersecting;
71 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)) {
84 firstintersecting = -1;
86 *p1 = DoRotation(*p1, 0, -*rotate, 0);
89 *p2 = DoRotation(*p2, 0, -*rotate, 0);
92 for (unsigned int j = 0; j < possible.size(); j++) {
93 if (possible[j] < Triangles.size()) {
94 intersecting = LineFacetd(p1, p2, &vertex[Triangles[possible[j]].vertex[0]], &vertex[Triangles[possible[j]].vertex[1]], &vertex[Triangles[possible[j]].vertex[2]], &Triangles[possible[j]].facenormal, &point);
95 distance = (point.x - p1->x) * (point.x - p1->x) + (point.y - p1->y) * (point.y - p1->y) + (point.z - p1->z) * (point.z - p1->z);
96 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
97 olddistance = distance;
98 firstintersecting = possible[j];
105 *p = DoRotation(*p, 0, *rotate, 0);
108 return firstintersecting;
111 int Model::LineCheckSlidePossible(XYZ* p1, XYZ* p2, XYZ* move, float* rotate)
113 static float distance;
114 static float olddistance;
115 static int intersecting;
116 static int firstintersecting;
121 if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius)) {
124 firstintersecting = -1;
126 *p1 = DoRotation(*p1, 0, -*rotate, 0);
129 *p2 = DoRotation(*p2, 0, -*rotate, 0);
132 for (unsigned int j = 0; j < possible.size(); j++) {
133 if (possible[j] < Triangles.size()) {
134 intersecting = LineFacetd(p1, p2, &vertex[Triangles[possible[j]].vertex[0]], &vertex[Triangles[possible[j]].vertex[1]], &vertex[Triangles[possible[j]].vertex[2]], &Triangles[possible[j]].facenormal, &point);
135 distance = (point.x - p1->x) * (point.x - p1->x) + (point.y - p1->y) * (point.y - p1->y) + (point.z - p1->z) * (point.z - p1->z);
136 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
137 olddistance = distance;
138 firstintersecting = possible[j];
143 if (firstintersecting > 0) {
144 distance = abs((Triangles[firstintersecting].facenormal.x * p2->x) + (Triangles[firstintersecting].facenormal.y * p2->y) + (Triangles[firstintersecting].facenormal.z * p2->z) - ((Triangles[firstintersecting].facenormal.x * vertex[Triangles[firstintersecting].vertex[0]].x) + (Triangles[firstintersecting].facenormal.y * vertex[Triangles[firstintersecting].vertex[0]].y) + (Triangles[firstintersecting].facenormal.z * vertex[Triangles[firstintersecting].vertex[0]].z)));
145 *p2 -= Triangles[firstintersecting].facenormal * distance;
149 *p2 = DoRotation(*p2, 0, *rotate, 0);
152 return firstintersecting;
155 int Model::SphereCheck(XYZ* p1, float radius, XYZ* p, XYZ* move, float* rotate)
158 static float distance;
159 static float olddistance;
160 static int intersecting;
161 static int firstintersecting;
165 firstintersecting = -1;
170 *p1 = DoRotation(*p1, 0, -*rotate, 0);
172 if (distsq(p1, &boundingspherecenter) > radius * radius + boundingsphereradius * boundingsphereradius) {
176 for (i = 0; i < 4; i++) {
177 for (unsigned int j = 0; j < Triangles.size(); j++) {
179 distance = abs((Triangles[j].facenormal.x * p1->x) + (Triangles[j].facenormal.y * p1->y) + (Triangles[j].facenormal.z * p1->z) - ((Triangles[j].facenormal.x * vertex[Triangles[j].vertex[0]].x) + (Triangles[j].facenormal.y * vertex[Triangles[j].vertex[0]].y) + (Triangles[j].facenormal.z * vertex[Triangles[j].vertex[0]].z)));
180 if (distance < radius) {
181 point = *p1 - Triangles[j].facenormal * distance;
182 if (PointInTriangle(&point, Triangles[j].facenormal, &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]])) {
186 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], p1, &radius);
189 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], p1, &radius);
192 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[2]], p1, &radius);
195 *p1 += Triangles[j].facenormal * (distance - radius);
198 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
199 olddistance = distance;
200 firstintersecting = j;
206 *p = DoRotation(*p, 0, *rotate, 0);
210 *p1 = DoRotation(*p1, 0, *rotate, 0);
213 return firstintersecting;
216 int Model::SphereCheckPossible(XYZ* p1, float radius, XYZ* move, float* rotate)
218 static float distance;
219 static float olddistance;
220 static int intersecting;
221 static int firstintersecting;
225 firstintersecting = -1;
233 *p1 = DoRotation(*p1, 0, -*rotate, 0);
235 if (distsq(p1, &boundingspherecenter) > radius * radius + boundingsphereradius * boundingsphereradius) {
240 for (unsigned int j = 0; j < Triangles.size(); j++) {
242 distance = abs((Triangles[j].facenormal.x * p1->x) + (Triangles[j].facenormal.y * p1->y) + (Triangles[j].facenormal.z * p1->z) - ((Triangles[j].facenormal.x * vertex[Triangles[j].vertex[0]].x) + (Triangles[j].facenormal.y * vertex[Triangles[j].vertex[0]].y) + (Triangles[j].facenormal.z * vertex[Triangles[j].vertex[0]].z)));
243 if (distance < radius) {
244 point = *p1 - Triangles[j].facenormal * distance;
245 if (PointInTriangle(&point, Triangles[j].facenormal, &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]])) {
249 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], p1, &radius);
252 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], p1, &radius);
255 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[2]], p1, &radius);
258 possible.push_back(j);
261 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
262 olddistance = distance;
263 firstintersecting = j;
267 *p1 = DoRotation(*p1, 0, *rotate, 0);
271 return firstintersecting;
274 void Model::UpdateVertexArray()
276 if (type != normaltype && type != decalstype) {
281 for (unsigned int i = 0; i < Triangles.size(); i++) {
282 unsigned int j = i * 24;
283 vArray[j + 0] = Triangles[i].gx[0];
284 vArray[j + 1] = Triangles[i].gy[0];
285 vArray[j + 2] = Triangles[i].facenormal.x * -1;
286 vArray[j + 3] = Triangles[i].facenormal.y * -1;
287 vArray[j + 4] = Triangles[i].facenormal.z * -1;
288 vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
289 vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
290 vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
292 vArray[j + 8] = Triangles[i].gx[1];
293 vArray[j + 9] = Triangles[i].gy[1];
294 vArray[j + 10] = Triangles[i].facenormal.x * -1;
295 vArray[j + 11] = Triangles[i].facenormal.y * -1;
296 vArray[j + 12] = Triangles[i].facenormal.z * -1;
297 vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
298 vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
299 vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
301 vArray[j + 16] = Triangles[i].gx[2];
302 vArray[j + 17] = Triangles[i].gy[2];
303 vArray[j + 18] = Triangles[i].facenormal.x * -1;
304 vArray[j + 19] = Triangles[i].facenormal.y * -1;
305 vArray[j + 20] = Triangles[i].facenormal.z * -1;
306 vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
307 vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
308 vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
311 for (unsigned int i = 0; i < Triangles.size(); i++) {
312 unsigned int j = i * 24;
313 vArray[j + 0] = Triangles[i].gx[0];
314 vArray[j + 1] = Triangles[i].gy[0];
315 vArray[j + 2] = normals[Triangles[i].vertex[0]].x;
316 vArray[j + 3] = normals[Triangles[i].vertex[0]].y;
317 vArray[j + 4] = normals[Triangles[i].vertex[0]].z;
318 vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
319 vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
320 vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
322 vArray[j + 8] = Triangles[i].gx[1];
323 vArray[j + 9] = Triangles[i].gy[1];
324 vArray[j + 10] = normals[Triangles[i].vertex[1]].x;
325 vArray[j + 11] = normals[Triangles[i].vertex[1]].y;
326 vArray[j + 12] = normals[Triangles[i].vertex[1]].z;
327 vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
328 vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
329 vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
331 vArray[j + 16] = Triangles[i].gx[2];
332 vArray[j + 17] = Triangles[i].gy[2];
333 vArray[j + 18] = normals[Triangles[i].vertex[2]].x;
334 vArray[j + 19] = normals[Triangles[i].vertex[2]].y;
335 vArray[j + 20] = normals[Triangles[i].vertex[2]].z;
336 vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
337 vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
338 vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
343 void Model::UpdateVertexArrayNoTex()
345 if (type != normaltype && type != decalstype) {
350 for (unsigned int i = 0; i < Triangles.size(); i++) {
351 unsigned int j = i * 24;
352 vArray[j + 2] = Triangles[i].facenormal.x * -1;
353 vArray[j + 3] = Triangles[i].facenormal.y * -1;
354 vArray[j + 4] = Triangles[i].facenormal.z * -1;
355 vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
356 vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
357 vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
359 vArray[j + 10] = Triangles[i].facenormal.x * -1;
360 vArray[j + 11] = Triangles[i].facenormal.y * -1;
361 vArray[j + 12] = Triangles[i].facenormal.z * -1;
362 vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
363 vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
364 vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
366 vArray[j + 18] = Triangles[i].facenormal.x * -1;
367 vArray[j + 19] = Triangles[i].facenormal.y * -1;
368 vArray[j + 20] = Triangles[i].facenormal.z * -1;
369 vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
370 vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
371 vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
374 for (unsigned int i = 0; i < Triangles.size(); i++) {
375 unsigned int j = i * 24;
376 vArray[j + 2] = normals[Triangles[i].vertex[0]].x;
377 vArray[j + 3] = normals[Triangles[i].vertex[0]].y;
378 vArray[j + 4] = normals[Triangles[i].vertex[0]].z;
379 vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
380 vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
381 vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
383 vArray[j + 10] = normals[Triangles[i].vertex[1]].x;
384 vArray[j + 11] = normals[Triangles[i].vertex[1]].y;
385 vArray[j + 12] = normals[Triangles[i].vertex[1]].z;
386 vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
387 vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
388 vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
390 vArray[j + 18] = normals[Triangles[i].vertex[2]].x;
391 vArray[j + 19] = normals[Triangles[i].vertex[2]].y;
392 vArray[j + 20] = normals[Triangles[i].vertex[2]].z;
393 vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
394 vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
395 vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
400 void Model::UpdateVertexArrayNoTexNoNorm()
402 if (type != normaltype && type != decalstype) {
406 for (unsigned int i = 0; i < Triangles.size(); i++) {
407 unsigned int j = i * 24;
408 vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
409 vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
410 vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
412 vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
413 vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
414 vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
416 vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
417 vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
418 vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
422 bool Model::loadnotex(const std::string& filename)
431 tfile = Folders::openMandatoryFile(Folders::getResourcePath(filename), "rb");
433 // read model settings
435 fseek(tfile, 0, SEEK_SET);
436 funpackf(tfile, "Bs Bs", &vertexNum, &triangleNum);
438 // read the model data
443 owner = (int*)malloc(sizeof(int) * vertexNum);
444 vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
445 Triangles.resize(triangleNum);
446 vArray = (GLfloat*)malloc(sizeof(GLfloat) * triangleNum * 24);
448 for (i = 0; i < vertexNum; i++) {
449 funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
452 for (i = 0; i < triangleNum; i++) {
454 funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[0], &vertex[1], &vertex[2], &vertex[3], &vertex[4], &vertex[5]);
455 Triangles[i].vertex[0] = vertex[0];
456 Triangles[i].vertex[1] = vertex[2];
457 Triangles[i].vertex[2] = vertex[4];
458 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
459 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
466 for (i = 0; i < vertexNum; i++) {
470 boundingsphereradius = 0;
471 for (i = 0; i < vertexNum; i++) {
472 for (int j = 0; j < vertexNum; j++) {
473 if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
474 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
475 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
479 boundingsphereradius = fast_sqrt(boundingsphereradius);
484 bool Model::load(const std::string& filename)
492 LOG(std::string("Loading model...") + filename);
494 Game::LoadingScreen();
499 tfile = Folders::openMandatoryFile(Folders::getResourcePath(filename), "rb");
501 // read model settings
503 fseek(tfile, 0, SEEK_SET);
504 funpackf(tfile, "Bs Bs", &vertexNum, &triangleNum);
506 // read the model data
511 owner = (int*)malloc(sizeof(int) * vertexNum);
512 vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
513 normals = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
514 Triangles.resize(triangleNum);
515 vArray = (GLfloat*)malloc(sizeof(GLfloat) * triangleNum * 24);
517 for (i = 0; i < vertexNum; i++) {
518 funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
521 for (i = 0; i < triangleNum; i++) {
523 funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[0], &vertex[1], &vertex[2], &vertex[3], &vertex[4], &vertex[5]);
524 Triangles[i].vertex[0] = vertex[0];
525 Triangles[i].vertex[1] = vertex[2];
526 Triangles[i].vertex[2] = vertex[4];
527 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
528 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
531 modelTexture.xsz = 0;
537 for (i = 0; i < vertexNum; i++) {
542 boundingsphereradius = 0;
543 for (i = 0; i < vertexNum; i++) {
544 for (j = 0; j < vertexNum; j++) {
545 if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
546 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
547 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
551 boundingsphereradius = fast_sqrt(boundingsphereradius);
556 bool Model::loaddecal(const std::string& filename)
564 LOG(std::string("Loading decal...") + Folders::getResourcePath(filename));
569 tfile = Folders::openMandatoryFile(Folders::getResourcePath(filename), "rb");
571 // read model settings
573 fseek(tfile, 0, SEEK_SET);
574 funpackf(tfile, "Bs Bs", &vertexNum, &triangleNum);
576 // read the model data
582 owner = (int*)malloc(sizeof(int) * vertexNum);
583 vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
584 normals = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
585 Triangles.resize(triangleNum);
586 vArray = (GLfloat*)malloc(sizeof(GLfloat) * triangleNum * 24);
588 for (i = 0; i < vertexNum; i++) {
589 funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
592 for (i = 0; i < triangleNum; i++) {
594 funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[0], &vertex[1], &vertex[2], &vertex[3], &vertex[4], &vertex[5]);
595 Triangles[i].vertex[0] = vertex[0];
596 Triangles[i].vertex[1] = vertex[2];
597 Triangles[i].vertex[2] = vertex[4];
598 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
599 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
602 modelTexture.xsz = 0;
608 for (i = 0; i < vertexNum; i++) {
612 boundingsphereradius = 0;
613 for (i = 0; i < vertexNum; i++) {
614 for (j = 0; j < vertexNum; j++) {
615 if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
616 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
617 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
621 boundingsphereradius = fast_sqrt(boundingsphereradius);
626 bool Model::loadraw(const std::string& filename)
634 LOG(std::string("Loading raw...") + filename);
639 tfile = Folders::openMandatoryFile(Folders::getResourcePath(filename), "rb");
641 // read model settings
643 fseek(tfile, 0, SEEK_SET);
644 funpackf(tfile, "Bs Bs", &vertexNum, &triangleNum);
646 // read the model data
651 owner = (int*)malloc(sizeof(int) * vertexNum);
652 vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
653 Triangles.resize(triangleNum);
654 vArray = (GLfloat*)malloc(sizeof(GLfloat) * triangleNum * 24);
656 for (i = 0; i < vertexNum; i++) {
657 funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
660 for (i = 0; i < triangleNum; i++) {
662 funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[0], &vertex[1], &vertex[2], &vertex[3], &vertex[4], &vertex[5]);
663 Triangles[i].vertex[0] = vertex[0];
664 Triangles[i].vertex[1] = vertex[2];
665 Triangles[i].vertex[2] = vertex[4];
666 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
667 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
672 for (i = 0; i < vertexNum; i++) {
679 void Model::UniformTexCoords()
681 for (unsigned int i = 0; i < Triangles.size(); i++) {
682 Triangles[i].gy[0] = vertex[Triangles[i].vertex[0]].y;
683 Triangles[i].gy[1] = vertex[Triangles[i].vertex[1]].y;
684 Triangles[i].gy[2] = vertex[Triangles[i].vertex[2]].y;
685 Triangles[i].gx[0] = vertex[Triangles[i].vertex[0]].x;
686 Triangles[i].gx[1] = vertex[Triangles[i].vertex[1]].x;
687 Triangles[i].gx[2] = vertex[Triangles[i].vertex[2]].x;
692 void Model::FlipTexCoords()
694 for (unsigned int i = 0; i < Triangles.size(); i++) {
695 Triangles[i].gy[0] = -Triangles[i].gy[0];
696 Triangles[i].gy[1] = -Triangles[i].gy[1];
697 Triangles[i].gy[2] = -Triangles[i].gy[2];
702 void Model::ScaleTexCoords(float howmuch)
704 for (unsigned int i = 0; i < Triangles.size(); i++) {
705 Triangles[i].gx[0] *= howmuch;
706 Triangles[i].gx[1] *= howmuch;
707 Triangles[i].gx[2] *= howmuch;
708 Triangles[i].gy[0] *= howmuch;
709 Triangles[i].gy[1] *= howmuch;
710 Triangles[i].gy[2] *= howmuch;
715 void Model::Scale(float xscale, float yscale, float zscale)
718 for (i = 0; i < vertexNum; i++) {
719 vertex[i].x *= xscale;
720 vertex[i].y *= yscale;
721 vertex[i].z *= zscale;
727 boundingsphereradius = 0;
728 for (i = 0; i < vertexNum; i++) {
729 for (j = 0; j < vertexNum; j++) {
730 if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
731 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
732 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
736 boundingsphereradius = fast_sqrt(boundingsphereradius);
739 void Model::ScaleNormals(float xscale, float yscale, float zscale)
741 if (type != normaltype && type != decalstype) {
745 for (int i = 0; i < vertexNum; i++) {
746 normals[i].x *= xscale;
747 normals[i].y *= yscale;
748 normals[i].z *= zscale;
750 for (unsigned int i = 0; i < Triangles.size(); i++) {
751 Triangles[i].facenormal.x *= xscale;
752 Triangles[i].facenormal.y *= yscale;
753 Triangles[i].facenormal.z *= zscale;
758 void Model::Translate(float xtrans, float ytrans, float ztrans)
761 for (i = 0; i < vertexNum; i++) {
762 vertex[i].x += xtrans;
763 vertex[i].y += ytrans;
764 vertex[i].z += ztrans;
769 boundingsphereradius = 0;
770 for (i = 0; i < vertexNum; i++) {
771 for (j = 0; j < vertexNum; j++) {
772 if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
773 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
774 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
778 boundingsphereradius = fast_sqrt(boundingsphereradius);
781 void Model::Rotate(float xang, float yang, float zang)
784 for (i = 0; i < vertexNum; i++) {
785 vertex[i] = DoRotation(vertex[i], xang, yang, zang);
790 boundingsphereradius = 0;
791 for (i = 0; i < vertexNum; i++) {
792 for (j = 0; j < vertexNum; j++) {
793 if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
794 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
795 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
799 boundingsphereradius = fast_sqrt(boundingsphereradius);
802 void Model::CalculateNormals(bool facenormalise)
804 Game::LoadingScreen();
806 if (type != normaltype && type != decalstype) {
810 for (int i = 0; i < vertexNum; i++) {
816 for (unsigned int i = 0; i < Triangles.size(); i++) {
817 CrossProduct(vertex[Triangles[i].vertex[1]] - vertex[Triangles[i].vertex[0]], vertex[Triangles[i].vertex[2]] - vertex[Triangles[i].vertex[0]], &Triangles[i].facenormal);
819 normals[Triangles[i].vertex[0]].x += Triangles[i].facenormal.x;
820 normals[Triangles[i].vertex[0]].y += Triangles[i].facenormal.y;
821 normals[Triangles[i].vertex[0]].z += Triangles[i].facenormal.z;
823 normals[Triangles[i].vertex[1]].x += Triangles[i].facenormal.x;
824 normals[Triangles[i].vertex[1]].y += Triangles[i].facenormal.y;
825 normals[Triangles[i].vertex[1]].z += Triangles[i].facenormal.z;
827 normals[Triangles[i].vertex[2]].x += Triangles[i].facenormal.x;
828 normals[Triangles[i].vertex[2]].y += Triangles[i].facenormal.y;
829 normals[Triangles[i].vertex[2]].z += Triangles[i].facenormal.z;
831 Normalise(&Triangles[i].facenormal);
834 for (int i = 0; i < vertexNum; i++) {
835 Normalise(&normals[i]);
838 UpdateVertexArrayNoTex();
841 void Model::drawimmediate()
844 glBegin(GL_TRIANGLES);
845 for (unsigned int i = 0; i < Triangles.size(); i++) {
846 glTexCoord2f(Triangles[i].gx[0], Triangles[i].gy[0]);
848 glColor3f(normals[Triangles[i].vertex[0]].x, normals[Triangles[i].vertex[0]].y, normals[Triangles[i].vertex[0]].z);
850 glNormal3f(Triangles[i].facenormal.x, Triangles[i].facenormal.y, Triangles[i].facenormal.y);
852 glNormal3f(normals[Triangles[i].vertex[0]].x, normals[Triangles[i].vertex[0]].y, normals[Triangles[i].vertex[0]].z);
854 glVertex3f(vertex[Triangles[i].vertex[0]].x, vertex[Triangles[i].vertex[0]].y, vertex[Triangles[i].vertex[0]].z);
856 glTexCoord2f(Triangles[i].gx[1], Triangles[i].gy[1]);
858 glColor3f(normals[Triangles[i].vertex[1]].x, normals[Triangles[i].vertex[1]].y, normals[Triangles[i].vertex[1]].z);
860 glNormal3f(Triangles[i].facenormal.x, Triangles[i].facenormal.y, Triangles[i].facenormal.y);
862 glNormal3f(normals[Triangles[i].vertex[1]].x, normals[Triangles[i].vertex[1]].y, normals[Triangles[i].vertex[1]].z);
864 glVertex3f(vertex[Triangles[i].vertex[1]].x, vertex[Triangles[i].vertex[1]].y, vertex[Triangles[i].vertex[1]].z);
866 glTexCoord2f(Triangles[i].gx[2], Triangles[i].gy[2]);
868 glColor3f(normals[Triangles[i].vertex[2]].x, normals[Triangles[i].vertex[2]].y, normals[Triangles[i].vertex[2]].z);
870 glNormal3f(Triangles[i].facenormal.x, Triangles[i].facenormal.y, Triangles[i].facenormal.y);
872 glNormal3f(normals[Triangles[i].vertex[2]].x, normals[Triangles[i].vertex[2]].y, normals[Triangles[i].vertex[2]].z);
874 glVertex3f(vertex[Triangles[i].vertex[2]].x, vertex[Triangles[i].vertex[2]].y, vertex[Triangles[i].vertex[2]].z);
881 if (type != normaltype && type != decalstype) {
885 glEnableClientState(GL_NORMAL_ARRAY);
886 glEnableClientState(GL_VERTEX_ARRAY);
887 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
890 glInterleavedArrays(GL_T2F_C3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
892 glInterleavedArrays(GL_T2F_N3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
896 glDrawArrays(GL_TRIANGLES, 0, Triangles.size() * 3);
899 glDisableClientState(GL_COLOR_ARRAY);
901 glDisableClientState(GL_NORMAL_ARRAY);
903 glDisableClientState(GL_VERTEX_ARRAY);
904 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
907 void Model::drawdifftex(Texture texture)
909 glEnableClientState(GL_NORMAL_ARRAY);
910 glEnableClientState(GL_VERTEX_ARRAY);
911 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
913 glInterleavedArrays(GL_T2F_C3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
915 glInterleavedArrays(GL_T2F_N3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
919 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
920 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
922 glDrawArrays(GL_TRIANGLES, 0, Triangles.size() * 3);
925 glDisableClientState(GL_COLOR_ARRAY);
927 glDisableClientState(GL_NORMAL_ARRAY);
929 glDisableClientState(GL_VERTEX_ARRAY);
930 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
933 void Model::drawdecals(Texture shadowtexture, Texture bloodtexture, Texture bloodtexture2, Texture breaktexture)
936 if (type != decalstype) {
944 glDisable(GL_LIGHTING);
945 glDisable(GL_CULL_FACE);
946 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
948 for (unsigned int i = 0; i < decals.size(); i++) {
949 if (decals[i].type == blooddecalfast && decals[i].alivetime < 2) {
950 decals[i].alivetime = 2;
953 if (decals[i].type != lasttype) {
954 if (decals[i].type == shadowdecal) {
955 shadowtexture.bind();
958 glAlphaFunc(GL_GREATER, 0.0001);
959 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
962 if (decals[i].type == breakdecal) {
966 glAlphaFunc(GL_GREATER, 0.0001);
967 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
970 if (decals[i].type == blooddecal || decals[i].type == blooddecalslow) {
974 glAlphaFunc(GL_GREATER, 0.15);
975 glBlendFunc(GL_ONE, GL_ZERO);
978 if (decals[i].type == blooddecalfast) {
979 bloodtexture2.bind();
982 glAlphaFunc(GL_GREATER, 0.15);
983 glBlendFunc(GL_ONE, GL_ZERO);
987 if (decals[i].type == shadowdecal) {
988 glColor4f(1, 1, 1, decals[i].opacity);
990 if (decals[i].type == breakdecal) {
991 glColor4f(1, 1, 1, decals[i].opacity);
992 if (decals[i].alivetime > 58) {
993 glColor4f(1, 1, 1, decals[i].opacity * (60 - decals[i].alivetime) / 2);
996 if ((decals[i].type == blooddecal || decals[i].type == blooddecalfast || decals[i].type == blooddecalslow)) {
997 glColor4f(1, 1, 1, decals[i].opacity);
998 if (decals[i].alivetime < 4) {
999 glColor4f(1, 1, 1, decals[i].opacity * decals[i].alivetime * .25);
1001 if (decals[i].alivetime > 58) {
1002 glColor4f(1, 1, 1, decals[i].opacity * (60 - decals[i].alivetime) / 2);
1005 lasttype = decals[i].type;
1006 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1007 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1009 glMatrixMode(GL_MODELVIEW);
1011 glBegin(GL_TRIANGLES);
1012 for (int j = 0; j < 3; j++) {
1013 glTexCoord2f(decals[i].texcoords[j][0], decals[i].texcoords[j][1]);
1014 glVertex3f(decals[i].vertex[j].x, decals[i].vertex[j].y, decals[i].vertex[j].z);
1019 for (int i = decals.size() - 1; i >= 0; i--) {
1020 decals[i].alivetime += multiplier;
1021 if (decals[i].type == blooddecalslow) {
1022 decals[i].alivetime -= multiplier * 2 / 3;
1024 if (decals[i].type == blooddecalfast) {
1025 decals[i].alivetime += multiplier * 4;
1027 if (decals[i].type == shadowdecal) {
1030 if ((decals[i].type == blooddecal || decals[i].type == blooddecalfast || decals[i].type == blooddecalslow) && decals[i].alivetime >= 60) {
1034 glAlphaFunc(GL_GREATER, 0.0001);
1035 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1039 void Model::DeleteDecal(int which)
1042 if (type != decalstype) {
1045 decals.erase(decals.begin() + which);
1049 void Model::MakeDecal(decal_type atype, XYZ* where, float* size, float* opacity, float* rotation)
1052 if (type != decalstype) {
1057 static float distance;
1060 if (distsq(where, &boundingspherecenter) < (boundingsphereradius + *size) * (boundingsphereradius + *size)) {
1061 for (unsigned int i = 0; i < Triangles.size(); i++) {
1062 if (Triangles[i].facenormal.y < -.1 && (vertex[Triangles[i].vertex[0]].y < where->y || vertex[Triangles[i].vertex[1]].y < where->y || vertex[Triangles[i].vertex[2]].y < where->y)) {
1063 distance = abs(((Triangles[i].facenormal.x * where->x) + (Triangles[i].facenormal.y * where->y) + (Triangles[i].facenormal.z * where->z) - ((Triangles[i].facenormal.x * vertex[Triangles[i].vertex[0]].x) + (Triangles[i].facenormal.y * vertex[Triangles[i].vertex[0]].y) + (Triangles[i].facenormal.z * vertex[Triangles[i].vertex[0]].z))) / Triangles[i].facenormal.y);
1065 if ((*opacity - distance / 10) > 0) {
1066 Decal decal(*where, atype, *opacity - distance / 10, *rotation, *size, *this, i, 0);
1068 if (!(decal.texcoords[0][0] < 0 && decal.texcoords[1][0] < 0 && decal.texcoords[2][0] < 0)) {
1069 if (!(decal.texcoords[0][1] < 0 && decal.texcoords[1][1] < 0 && decal.texcoords[2][1] < 0)) {
1070 if (!(decal.texcoords[0][0] > 1 && decal.texcoords[1][0] > 1 && decal.texcoords[2][0] > 1)) {
1071 if (!(decal.texcoords[0][1] > 1 && decal.texcoords[1][1] > 1 && decal.texcoords[2][1] > 1)) {
1072 if (decal.rotation) {
1073 for (int j = 0; j < 3; j++) {
1075 rot.x = decal.texcoords[j][0] - .5;
1076 rot.z = decal.texcoords[j][1] - .5;
1077 rot = DoRotation(rot, 0, -decal.rotation, 0);
1078 decal.texcoords[j][0] = rot.x + .5;
1079 decal.texcoords[j][1] = rot.z + .5;
1082 if (decals.size() < max_model_decals - 1) {
1083 decals.push_back(decal);
1097 void Model::MakeDecal(decal_type atype, XYZ where, float size, float opacity, float rotation)
1100 if (type != decalstype) {
1105 static float distance;
1108 if (distsq(&where, &boundingspherecenter) < (boundingsphereradius + size) * (boundingsphereradius + size)) {
1109 for (unsigned int i = 0; i < Triangles.size(); i++) {
1110 distance = abs(((Triangles[i].facenormal.x * where.x) + (Triangles[i].facenormal.y * where.y) + (Triangles[i].facenormal.z * where.z) - ((Triangles[i].facenormal.x * vertex[Triangles[i].vertex[0]].x) + (Triangles[i].facenormal.y * vertex[Triangles[i].vertex[0]].y) + (Triangles[i].facenormal.z * vertex[Triangles[i].vertex[0]].z))));
1111 if (distance < .02 && abs(Triangles[i].facenormal.y) > abs(Triangles[i].facenormal.x) && abs(Triangles[i].facenormal.y) > abs(Triangles[i].facenormal.z)) {
1112 if ((opacity - distance / 10) > 0) {
1113 Decal decal(where, atype, opacity - distance / 10, rotation, size, *this, i, 0);
1115 if (!(decal.texcoords[0][0] < 0 && decal.texcoords[1][0] < 0 && decal.texcoords[2][0] < 0)) {
1116 if (!(decal.texcoords[0][1] < 0 && decal.texcoords[1][1] < 0 && decal.texcoords[2][1] < 0)) {
1117 if (!(decal.texcoords[0][0] > 1 && decal.texcoords[1][0] > 1 && decal.texcoords[2][0] > 1)) {
1118 if (!(decal.texcoords[0][1] > 1 && decal.texcoords[1][1] > 1 && decal.texcoords[2][1] > 1)) {
1119 if (decal.rotation) {
1120 for (int j = 0; j < 3; j++) {
1122 rot.x = decal.texcoords[j][0] - .5;
1123 rot.z = decal.texcoords[j][1] - .5;
1124 rot = DoRotation(rot, 0, -decal.rotation, 0);
1125 decal.texcoords[j][0] = rot.x + .5;
1126 decal.texcoords[j][1] = rot.z + .5;
1129 if (decals.size() < max_model_decals - 1) {
1130 decals.push_back(decal);
1137 } else if (distance < .02 && abs(Triangles[i].facenormal.x) > abs(Triangles[i].facenormal.y) && abs(Triangles[i].facenormal.x) > abs(Triangles[i].facenormal.z)) {
1138 if ((opacity - distance / 10) > 0) {
1139 Decal decal(where, atype, opacity - distance / 10, rotation, size, *this, i, 1);
1141 if (!(decal.texcoords[0][0] < 0 && decal.texcoords[1][0] < 0 && decal.texcoords[2][0] < 0)) {
1142 if (!(decal.texcoords[0][1] < 0 && decal.texcoords[1][1] < 0 && decal.texcoords[2][1] < 0)) {
1143 if (!(decal.texcoords[0][0] > 1 && decal.texcoords[1][0] > 1 && decal.texcoords[2][0] > 1)) {
1144 if (!(decal.texcoords[0][1] > 1 && decal.texcoords[1][1] > 1 && decal.texcoords[2][1] > 1)) {
1145 if (decal.rotation) {
1146 for (int j = 0; j < 3; j++) {
1148 rot.x = decal.texcoords[j][0] - .5;
1149 rot.z = decal.texcoords[j][1] - .5;
1150 rot = DoRotation(rot, 0, -decal.rotation, 0);
1151 decal.texcoords[j][0] = rot.x + .5;
1152 decal.texcoords[j][1] = rot.z + .5;
1155 if (decals.size() < max_model_decals - 1) {
1156 decals.push_back(decal);
1163 } else if (distance < .02 && abs(Triangles[i].facenormal.z) > abs(Triangles[i].facenormal.y) && abs(Triangles[i].facenormal.z) > abs(Triangles[i].facenormal.x)) {
1164 if ((opacity - distance / 10) > 0) {
1165 Decal decal(where, atype, opacity - distance / 10, rotation, size, *this, i, 2);
1167 if (!(decal.texcoords[0][0] < 0 && decal.texcoords[1][0] < 0 && decal.texcoords[2][0] < 0)) {
1168 if (!(decal.texcoords[0][1] < 0 && decal.texcoords[1][1] < 0 && decal.texcoords[2][1] < 0)) {
1169 if (!(decal.texcoords[0][0] > 1 && decal.texcoords[1][0] > 1 && decal.texcoords[2][0] > 1)) {
1170 if (!(decal.texcoords[0][1] > 1 && decal.texcoords[1][1] > 1 && decal.texcoords[2][1] > 1)) {
1171 if (decal.rotation) {
1172 for (int j = 0; j < 3; j++) {
1174 rot.x = decal.texcoords[j][0] - .5;
1175 rot.z = decal.texcoords[j][1] - .5;
1176 rot = DoRotation(rot, 0, -decal.rotation, 0);
1177 decal.texcoords[j][0] = rot.x + .5;
1178 decal.texcoords[j][1] = rot.z + .5;
1181 if (decals.size() < max_model_decals - 1) {
1182 decals.push_back(decal);
1196 const XYZ& Model::getTriangleVertex(unsigned triangleId, unsigned vertexId) const
1198 return vertex[Triangles[triangleId].vertex[vertexId]];
1201 void Model::deleteDeadDecals()
1203 for (int i = decals.size() - 1; i >= 0; i--) {
1204 if ((decals[i].type == blooddecal || decals[i].type == blooddecalslow) && decals[i].alivetime < 2) {
1215 void Model::deallocate()
1248 , boundingspherecenter()
1249 , boundingsphereradius(0)
1252 memset(&modelTexture, 0, sizeof(modelTexture));