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 for (unsigned int j = 0; j < possible.size(); j++) {
86 if (possible[j] < Triangles.size()) {
87 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);
88 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);
89 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
90 olddistance = distance;
91 firstintersecting = possible[j];
98 *p = DoRotation(*p, 0, *rotate, 0);
100 return firstintersecting;
103 int Model::LineCheckSlidePossible(XYZ* p1, XYZ* p2, XYZ* move, float* rotate)
105 static float distance;
106 static float olddistance;
107 static int intersecting;
108 static int firstintersecting;
113 if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius))
115 firstintersecting = -1;
117 *p1 = DoRotation(*p1, 0, -*rotate, 0);
119 *p2 = DoRotation(*p2, 0, -*rotate, 0);
121 for (unsigned int j = 0; j < possible.size(); j++) {
122 if (possible[j] < Triangles.size()) {
123 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);
124 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);
125 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
126 olddistance = distance;
127 firstintersecting = possible[j];
132 if (firstintersecting > 0) {
133 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)));
134 *p2 -= Triangles[firstintersecting].facenormal * distance;
138 *p2 = DoRotation(*p2, 0, *rotate, 0);
140 return firstintersecting;
143 int Model::SphereCheck(XYZ* p1, float radius, XYZ* p, XYZ* move, float* rotate)
146 static float distance;
147 static float olddistance;
148 static int intersecting;
149 static int firstintersecting;
153 firstintersecting = -1;
158 *p1 = DoRotation(*p1, 0, -*rotate, 0);
159 if (distsq(p1, &boundingspherecenter) > radius * radius + boundingsphereradius * boundingsphereradius)
162 for (i = 0; i < 4; i++) {
163 for (unsigned int j = 0; j < Triangles.size(); j++) {
165 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)));
166 if (distance < radius) {
167 point = *p1 - Triangles[j].facenormal * distance;
168 if (PointInTriangle(&point, Triangles[j].facenormal, &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]]))
171 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], p1, &radius);
173 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], p1, &radius);
175 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[2]], p1, &radius);
177 *p1 += Triangles[j].facenormal * (distance - radius);
180 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
181 olddistance = distance;
182 firstintersecting = j;
188 *p = DoRotation(*p, 0, *rotate, 0);
191 *p1 = DoRotation(*p1, 0, *rotate, 0);
193 return firstintersecting;
196 int Model::SphereCheckPossible(XYZ* p1, float radius, XYZ* move, float* rotate)
198 static float distance;
199 static float olddistance;
200 static int intersecting;
201 static int firstintersecting;
205 firstintersecting = -1;
213 *p1 = DoRotation(*p1, 0, -*rotate, 0);
214 if (distsq(p1, &boundingspherecenter) > radius * radius + boundingsphereradius * boundingsphereradius) {
219 for (unsigned int j = 0; j < Triangles.size(); j++) {
221 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)));
222 if (distance < radius) {
223 point = *p1 - Triangles[j].facenormal * distance;
224 if (PointInTriangle(&point, Triangles[j].facenormal, &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]]))
227 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], p1, &radius);
229 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], p1, &radius);
231 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[2]], p1, &radius);
233 possible.push_back(j);
236 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
237 olddistance = distance;
238 firstintersecting = j;
242 *p1 = DoRotation(*p1, 0, *rotate, 0);
245 return firstintersecting;
248 void Model::UpdateVertexArray()
250 if (type != normaltype && type != decalstype)
254 for (unsigned int i = 0; i < Triangles.size(); i++) {
255 unsigned int j = i * 24;
256 vArray[j + 0] = Triangles[i].gx[0];
257 vArray[j + 1] = Triangles[i].gy[0];
258 vArray[j + 2] = Triangles[i].facenormal.x * -1;
259 vArray[j + 3] = Triangles[i].facenormal.y * -1;
260 vArray[j + 4] = Triangles[i].facenormal.z * -1;
261 vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
262 vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
263 vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
265 vArray[j + 8] = Triangles[i].gx[1];
266 vArray[j + 9] = Triangles[i].gy[1];
267 vArray[j + 10] = Triangles[i].facenormal.x * -1;
268 vArray[j + 11] = Triangles[i].facenormal.y * -1;
269 vArray[j + 12] = Triangles[i].facenormal.z * -1;
270 vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
271 vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
272 vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
274 vArray[j + 16] = Triangles[i].gx[2];
275 vArray[j + 17] = Triangles[i].gy[2];
276 vArray[j + 18] = Triangles[i].facenormal.x * -1;
277 vArray[j + 19] = Triangles[i].facenormal.y * -1;
278 vArray[j + 20] = Triangles[i].facenormal.z * -1;
279 vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
280 vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
281 vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
284 for (unsigned int i = 0; i < Triangles.size(); i++) {
285 unsigned int j = i * 24;
286 vArray[j + 0] = Triangles[i].gx[0];
287 vArray[j + 1] = Triangles[i].gy[0];
288 vArray[j + 2] = normals[Triangles[i].vertex[0]].x;
289 vArray[j + 3] = normals[Triangles[i].vertex[0]].y;
290 vArray[j + 4] = normals[Triangles[i].vertex[0]].z;
291 vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
292 vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
293 vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
295 vArray[j + 8] = Triangles[i].gx[1];
296 vArray[j + 9] = Triangles[i].gy[1];
297 vArray[j + 10] = normals[Triangles[i].vertex[1]].x;
298 vArray[j + 11] = normals[Triangles[i].vertex[1]].y;
299 vArray[j + 12] = normals[Triangles[i].vertex[1]].z;
300 vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
301 vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
302 vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
304 vArray[j + 16] = Triangles[i].gx[2];
305 vArray[j + 17] = Triangles[i].gy[2];
306 vArray[j + 18] = normals[Triangles[i].vertex[2]].x;
307 vArray[j + 19] = normals[Triangles[i].vertex[2]].y;
308 vArray[j + 20] = normals[Triangles[i].vertex[2]].z;
309 vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
310 vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
311 vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
316 void Model::UpdateVertexArrayNoTex()
318 if (type != normaltype && type != decalstype)
322 for (unsigned int i = 0; i < Triangles.size(); i++) {
323 unsigned int j = i * 24;
324 vArray[j + 2] = Triangles[i].facenormal.x * -1;
325 vArray[j + 3] = Triangles[i].facenormal.y * -1;
326 vArray[j + 4] = Triangles[i].facenormal.z * -1;
327 vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
328 vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
329 vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
331 vArray[j + 10] = Triangles[i].facenormal.x * -1;
332 vArray[j + 11] = Triangles[i].facenormal.y * -1;
333 vArray[j + 12] = Triangles[i].facenormal.z * -1;
334 vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
335 vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
336 vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
338 vArray[j + 18] = Triangles[i].facenormal.x * -1;
339 vArray[j + 19] = Triangles[i].facenormal.y * -1;
340 vArray[j + 20] = Triangles[i].facenormal.z * -1;
341 vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
342 vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
343 vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
346 for (unsigned int i = 0; i < Triangles.size(); i++) {
347 unsigned int j = i * 24;
348 vArray[j + 2] = normals[Triangles[i].vertex[0]].x;
349 vArray[j + 3] = normals[Triangles[i].vertex[0]].y;
350 vArray[j + 4] = normals[Triangles[i].vertex[0]].z;
351 vArray[j + 5] = vertex[Triangles[i].vertex[0]].x;
352 vArray[j + 6] = vertex[Triangles[i].vertex[0]].y;
353 vArray[j + 7] = vertex[Triangles[i].vertex[0]].z;
355 vArray[j + 10] = normals[Triangles[i].vertex[1]].x;
356 vArray[j + 11] = normals[Triangles[i].vertex[1]].y;
357 vArray[j + 12] = normals[Triangles[i].vertex[1]].z;
358 vArray[j + 13] = vertex[Triangles[i].vertex[1]].x;
359 vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
360 vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
362 vArray[j + 18] = normals[Triangles[i].vertex[2]].x;
363 vArray[j + 19] = normals[Triangles[i].vertex[2]].y;
364 vArray[j + 20] = normals[Triangles[i].vertex[2]].z;
365 vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
366 vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
367 vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
372 void Model::UpdateVertexArrayNoTexNoNorm()
374 if (type != normaltype && type != decalstype)
377 for (unsigned int i = 0; i < Triangles.size(); i++) {
378 unsigned int j = i * 24;
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 + 13] = vertex[Triangles[i].vertex[1]].x;
384 vArray[j + 14] = vertex[Triangles[i].vertex[1]].y;
385 vArray[j + 15] = vertex[Triangles[i].vertex[1]].z;
387 vArray[j + 21] = vertex[Triangles[i].vertex[2]].x;
388 vArray[j + 22] = vertex[Triangles[i].vertex[2]].y;
389 vArray[j + 23] = vertex[Triangles[i].vertex[2]].z;
393 bool Model::loadnotex(const std::string& filename)
402 tfile = Folders::openMandatoryFile(Folders::getResourcePath(filename), "rb");
404 // read model settings
406 fseek(tfile, 0, SEEK_SET);
407 funpackf(tfile, "Bs Bs", &vertexNum, &triangleNum);
409 // read the model data
414 owner = (int*)malloc(sizeof(int) * vertexNum);
415 vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
416 Triangles.resize(triangleNum);
417 vArray = (GLfloat*)malloc(sizeof(GLfloat) * triangleNum * 24);
419 for (i = 0; i < vertexNum; i++) {
420 funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
423 for (i = 0; i < triangleNum; i++) {
425 funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[0], &vertex[1], &vertex[2], &vertex[3], &vertex[4], &vertex[5]);
426 Triangles[i].vertex[0] = vertex[0];
427 Triangles[i].vertex[1] = vertex[2];
428 Triangles[i].vertex[2] = vertex[4];
429 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
430 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
437 for (i = 0; i < vertexNum; i++) {
441 boundingsphereradius = 0;
442 for (i = 0; i < vertexNum; i++) {
443 for (int j = 0; j < vertexNum; j++) {
444 if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
445 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
446 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
450 boundingsphereradius = fast_sqrt(boundingsphereradius);
455 bool Model::load(const std::string& filename)
463 LOG(std::string("Loading model...") + filename);
465 Game::LoadingScreen();
470 tfile = Folders::openMandatoryFile(Folders::getResourcePath(filename), "rb");
472 // read model settings
474 fseek(tfile, 0, SEEK_SET);
475 funpackf(tfile, "Bs Bs", &vertexNum, &triangleNum);
477 // read the model data
482 owner = (int*)malloc(sizeof(int) * vertexNum);
483 vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
484 normals = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
485 Triangles.resize(triangleNum);
486 vArray = (GLfloat*)malloc(sizeof(GLfloat) * triangleNum * 24);
488 for (i = 0; i < vertexNum; i++) {
489 funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
492 for (i = 0; i < triangleNum; i++) {
494 funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[0], &vertex[1], &vertex[2], &vertex[3], &vertex[4], &vertex[5]);
495 Triangles[i].vertex[0] = vertex[0];
496 Triangles[i].vertex[1] = vertex[2];
497 Triangles[i].vertex[2] = vertex[4];
498 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
499 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
502 modelTexture.xsz = 0;
508 for (i = 0; i < vertexNum; i++) {
513 boundingsphereradius = 0;
514 for (i = 0; i < vertexNum; i++) {
515 for (j = 0; j < vertexNum; j++) {
516 if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
517 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
518 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
522 boundingsphereradius = fast_sqrt(boundingsphereradius);
527 bool Model::loaddecal(const std::string& filename)
535 LOG(std::string("Loading decal...") + Folders::getResourcePath(filename));
540 tfile = Folders::openMandatoryFile(Folders::getResourcePath(filename), "rb");
542 // read model settings
544 fseek(tfile, 0, SEEK_SET);
545 funpackf(tfile, "Bs Bs", &vertexNum, &triangleNum);
547 // read the model data
553 owner = (int*)malloc(sizeof(int) * vertexNum);
554 vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
555 normals = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
556 Triangles.resize(triangleNum);
557 vArray = (GLfloat*)malloc(sizeof(GLfloat) * triangleNum * 24);
559 for (i = 0; i < vertexNum; i++) {
560 funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
563 for (i = 0; i < triangleNum; i++) {
565 funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[0], &vertex[1], &vertex[2], &vertex[3], &vertex[4], &vertex[5]);
566 Triangles[i].vertex[0] = vertex[0];
567 Triangles[i].vertex[1] = vertex[2];
568 Triangles[i].vertex[2] = vertex[4];
569 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
570 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
573 modelTexture.xsz = 0;
579 for (i = 0; i < vertexNum; i++) {
583 boundingsphereradius = 0;
584 for (i = 0; i < vertexNum; i++) {
585 for (j = 0; j < vertexNum; j++) {
586 if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
587 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
588 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
592 boundingsphereradius = fast_sqrt(boundingsphereradius);
597 bool Model::loadraw(const std::string& filename)
605 LOG(std::string("Loading raw...") + filename);
610 tfile = Folders::openMandatoryFile(Folders::getResourcePath(filename), "rb");
612 // read model settings
614 fseek(tfile, 0, SEEK_SET);
615 funpackf(tfile, "Bs Bs", &vertexNum, &triangleNum);
617 // read the model data
622 owner = (int*)malloc(sizeof(int) * vertexNum);
623 vertex = (XYZ*)malloc(sizeof(XYZ) * vertexNum);
624 Triangles.resize(triangleNum);
625 vArray = (GLfloat*)malloc(sizeof(GLfloat) * triangleNum * 24);
627 for (i = 0; i < vertexNum; i++) {
628 funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
631 for (i = 0; i < triangleNum; i++) {
633 funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[0], &vertex[1], &vertex[2], &vertex[3], &vertex[4], &vertex[5]);
634 Triangles[i].vertex[0] = vertex[0];
635 Triangles[i].vertex[1] = vertex[2];
636 Triangles[i].vertex[2] = vertex[4];
637 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
638 funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
643 for (i = 0; i < vertexNum; i++) {
650 void Model::UniformTexCoords()
652 for (unsigned int i = 0; i < Triangles.size(); i++) {
653 Triangles[i].gy[0] = vertex[Triangles[i].vertex[0]].y;
654 Triangles[i].gy[1] = vertex[Triangles[i].vertex[1]].y;
655 Triangles[i].gy[2] = vertex[Triangles[i].vertex[2]].y;
656 Triangles[i].gx[0] = vertex[Triangles[i].vertex[0]].x;
657 Triangles[i].gx[1] = vertex[Triangles[i].vertex[1]].x;
658 Triangles[i].gx[2] = vertex[Triangles[i].vertex[2]].x;
663 void Model::FlipTexCoords()
665 for (unsigned int i = 0; i < Triangles.size(); i++) {
666 Triangles[i].gy[0] = -Triangles[i].gy[0];
667 Triangles[i].gy[1] = -Triangles[i].gy[1];
668 Triangles[i].gy[2] = -Triangles[i].gy[2];
673 void Model::ScaleTexCoords(float howmuch)
675 for (unsigned int i = 0; i < Triangles.size(); i++) {
676 Triangles[i].gx[0] *= howmuch;
677 Triangles[i].gx[1] *= howmuch;
678 Triangles[i].gx[2] *= howmuch;
679 Triangles[i].gy[0] *= howmuch;
680 Triangles[i].gy[1] *= howmuch;
681 Triangles[i].gy[2] *= howmuch;
686 void Model::Scale(float xscale, float yscale, float zscale)
689 for (i = 0; i < vertexNum; i++) {
690 vertex[i].x *= xscale;
691 vertex[i].y *= yscale;
692 vertex[i].z *= zscale;
698 boundingsphereradius = 0;
699 for (i = 0; i < vertexNum; i++) {
700 for (j = 0; j < vertexNum; j++) {
701 if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
702 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
703 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
707 boundingsphereradius = fast_sqrt(boundingsphereradius);
710 void Model::ScaleNormals(float xscale, float yscale, float zscale)
712 if (type != normaltype && type != decalstype)
715 for (int i = 0; i < vertexNum; i++) {
716 normals[i].x *= xscale;
717 normals[i].y *= yscale;
718 normals[i].z *= zscale;
720 for (unsigned int i = 0; i < Triangles.size(); i++) {
721 Triangles[i].facenormal.x *= xscale;
722 Triangles[i].facenormal.y *= yscale;
723 Triangles[i].facenormal.z *= zscale;
728 void Model::Translate(float xtrans, float ytrans, float ztrans)
731 for (i = 0; i < vertexNum; i++) {
732 vertex[i].x += xtrans;
733 vertex[i].y += ytrans;
734 vertex[i].z += ztrans;
739 boundingsphereradius = 0;
740 for (i = 0; i < vertexNum; i++) {
741 for (j = 0; j < vertexNum; j++) {
742 if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
743 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
744 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
748 boundingsphereradius = fast_sqrt(boundingsphereradius);
751 void Model::Rotate(float xang, float yang, float zang)
754 for (i = 0; i < vertexNum; i++) {
755 vertex[i] = DoRotation(vertex[i], xang, yang, zang);
760 boundingsphereradius = 0;
761 for (i = 0; i < vertexNum; i++) {
762 for (j = 0; j < vertexNum; j++) {
763 if (j != i && distsq(&vertex[j], &vertex[i]) / 2 > boundingsphereradius) {
764 boundingsphereradius = distsq(&vertex[j], &vertex[i]) / 2;
765 boundingspherecenter = (vertex[i] + vertex[j]) / 2;
769 boundingsphereradius = fast_sqrt(boundingsphereradius);
772 void Model::CalculateNormals(bool facenormalise)
774 Game::LoadingScreen();
776 if (type != normaltype && type != decalstype)
779 for (int i = 0; i < vertexNum; i++) {
785 for (unsigned int i = 0; i < Triangles.size(); i++) {
786 CrossProduct(vertex[Triangles[i].vertex[1]] - vertex[Triangles[i].vertex[0]], vertex[Triangles[i].vertex[2]] - vertex[Triangles[i].vertex[0]], &Triangles[i].facenormal);
788 normals[Triangles[i].vertex[0]].x += Triangles[i].facenormal.x;
789 normals[Triangles[i].vertex[0]].y += Triangles[i].facenormal.y;
790 normals[Triangles[i].vertex[0]].z += Triangles[i].facenormal.z;
792 normals[Triangles[i].vertex[1]].x += Triangles[i].facenormal.x;
793 normals[Triangles[i].vertex[1]].y += Triangles[i].facenormal.y;
794 normals[Triangles[i].vertex[1]].z += Triangles[i].facenormal.z;
796 normals[Triangles[i].vertex[2]].x += Triangles[i].facenormal.x;
797 normals[Triangles[i].vertex[2]].y += Triangles[i].facenormal.y;
798 normals[Triangles[i].vertex[2]].z += Triangles[i].facenormal.z;
800 Normalise(&Triangles[i].facenormal);
802 for (int i = 0; i < vertexNum; i++) {
803 Normalise(&normals[i]);
806 UpdateVertexArrayNoTex();
809 void Model::drawimmediate()
812 glBegin(GL_TRIANGLES);
813 for (unsigned int i = 0; i < Triangles.size(); i++) {
814 glTexCoord2f(Triangles[i].gx[0], Triangles[i].gy[0]);
816 glColor3f(normals[Triangles[i].vertex[0]].x, normals[Triangles[i].vertex[0]].y, normals[Triangles[i].vertex[0]].z);
818 glNormal3f(Triangles[i].facenormal.x, Triangles[i].facenormal.y, Triangles[i].facenormal.y);
820 glNormal3f(normals[Triangles[i].vertex[0]].x, normals[Triangles[i].vertex[0]].y, normals[Triangles[i].vertex[0]].z);
822 glVertex3f(vertex[Triangles[i].vertex[0]].x, vertex[Triangles[i].vertex[0]].y, vertex[Triangles[i].vertex[0]].z);
824 glTexCoord2f(Triangles[i].gx[1], Triangles[i].gy[1]);
826 glColor3f(normals[Triangles[i].vertex[1]].x, normals[Triangles[i].vertex[1]].y, normals[Triangles[i].vertex[1]].z);
828 glNormal3f(Triangles[i].facenormal.x, Triangles[i].facenormal.y, Triangles[i].facenormal.y);
830 glNormal3f(normals[Triangles[i].vertex[1]].x, normals[Triangles[i].vertex[1]].y, normals[Triangles[i].vertex[1]].z);
832 glVertex3f(vertex[Triangles[i].vertex[1]].x, vertex[Triangles[i].vertex[1]].y, vertex[Triangles[i].vertex[1]].z);
834 glTexCoord2f(Triangles[i].gx[2], Triangles[i].gy[2]);
836 glColor3f(normals[Triangles[i].vertex[2]].x, normals[Triangles[i].vertex[2]].y, normals[Triangles[i].vertex[2]].z);
838 glNormal3f(Triangles[i].facenormal.x, Triangles[i].facenormal.y, Triangles[i].facenormal.y);
840 glNormal3f(normals[Triangles[i].vertex[2]].x, normals[Triangles[i].vertex[2]].y, normals[Triangles[i].vertex[2]].z);
842 glVertex3f(vertex[Triangles[i].vertex[2]].x, vertex[Triangles[i].vertex[2]].y, vertex[Triangles[i].vertex[2]].z);
849 if (type != normaltype && type != decalstype)
852 glEnableClientState(GL_NORMAL_ARRAY);
853 glEnableClientState(GL_VERTEX_ARRAY);
854 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
857 glInterleavedArrays(GL_T2F_C3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
859 glInterleavedArrays(GL_T2F_N3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
863 glDrawArrays(GL_TRIANGLES, 0, Triangles.size() * 3);
866 glDisableClientState(GL_COLOR_ARRAY);
868 glDisableClientState(GL_NORMAL_ARRAY);
870 glDisableClientState(GL_VERTEX_ARRAY);
871 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
874 void Model::drawdifftex(Texture texture)
876 glEnableClientState(GL_NORMAL_ARRAY);
877 glEnableClientState(GL_VERTEX_ARRAY);
878 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
880 glInterleavedArrays(GL_T2F_C3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
882 glInterleavedArrays(GL_T2F_N3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
886 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
887 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
889 glDrawArrays(GL_TRIANGLES, 0, Triangles.size() * 3);
892 glDisableClientState(GL_COLOR_ARRAY);
894 glDisableClientState(GL_NORMAL_ARRAY);
896 glDisableClientState(GL_VERTEX_ARRAY);
897 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
900 void Model::drawdecals(Texture shadowtexture, Texture bloodtexture, Texture bloodtexture2, Texture breaktexture)
903 if (type != decalstype) {
911 glDisable(GL_LIGHTING);
912 glDisable(GL_CULL_FACE);
913 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
915 for (unsigned int i = 0; i < decals.size(); i++) {
916 if (decals[i].type == blooddecalfast && decals[i].alivetime < 2)
917 decals[i].alivetime = 2;
919 if (decals[i].type != lasttype) {
920 if (decals[i].type == shadowdecal) {
921 shadowtexture.bind();
924 glAlphaFunc(GL_GREATER, 0.0001);
925 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
928 if (decals[i].type == breakdecal) {
932 glAlphaFunc(GL_GREATER, 0.0001);
933 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
936 if (decals[i].type == blooddecal || decals[i].type == blooddecalslow) {
940 glAlphaFunc(GL_GREATER, 0.15);
941 glBlendFunc(GL_ONE, GL_ZERO);
944 if (decals[i].type == blooddecalfast) {
945 bloodtexture2.bind();
948 glAlphaFunc(GL_GREATER, 0.15);
949 glBlendFunc(GL_ONE, GL_ZERO);
953 if (decals[i].type == shadowdecal) {
954 glColor4f(1, 1, 1, decals[i].opacity);
956 if (decals[i].type == breakdecal) {
957 glColor4f(1, 1, 1, decals[i].opacity);
958 if (decals[i].alivetime > 58)
959 glColor4f(1, 1, 1, decals[i].opacity * (60 - decals[i].alivetime) / 2);
961 if ((decals[i].type == blooddecal || decals[i].type == blooddecalfast || decals[i].type == blooddecalslow)) {
962 glColor4f(1, 1, 1, decals[i].opacity);
963 if (decals[i].alivetime < 4)
964 glColor4f(1, 1, 1, decals[i].opacity * decals[i].alivetime * .25);
965 if (decals[i].alivetime > 58)
966 glColor4f(1, 1, 1, decals[i].opacity * (60 - decals[i].alivetime) / 2);
968 lasttype = decals[i].type;
969 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
970 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
972 glMatrixMode(GL_MODELVIEW);
974 glBegin(GL_TRIANGLES);
975 for (int j = 0; j < 3; j++) {
976 glTexCoord2f(decals[i].texcoords[j][0], decals[i].texcoords[j][1]);
977 glVertex3f(decals[i].vertex[j].x, decals[i].vertex[j].y, decals[i].vertex[j].z);
982 for (int i = decals.size() - 1; i >= 0; i--) {
983 decals[i].alivetime += multiplier;
984 if (decals[i].type == blooddecalslow)
985 decals[i].alivetime -= multiplier * 2 / 3;
986 if (decals[i].type == blooddecalfast)
987 decals[i].alivetime += multiplier * 4;
988 if (decals[i].type == shadowdecal)
990 if ((decals[i].type == blooddecal || decals[i].type == blooddecalfast || decals[i].type == blooddecalslow) && decals[i].alivetime >= 60)
993 glAlphaFunc(GL_GREATER, 0.0001);
994 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
998 void Model::DeleteDecal(int which)
1001 if (type != decalstype)
1003 decals.erase(decals.begin() + which);
1007 void Model::MakeDecal(decal_type atype, XYZ* where, float* size, float* opacity, float* rotation)
1010 if (type != decalstype)
1014 static float distance;
1017 if (distsq(where, &boundingspherecenter) < (boundingsphereradius + *size) * (boundingsphereradius + *size))
1018 for (unsigned int i = 0; i < Triangles.size(); i++) {
1019 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)) {
1020 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);
1022 if ((*opacity - distance / 10) > 0) {
1023 Decal decal(*where, atype, *opacity - distance / 10, *rotation, *size, *this, i, 0);
1025 if (!(decal.texcoords[0][0] < 0 && decal.texcoords[1][0] < 0 && decal.texcoords[2][0] < 0))
1026 if (!(decal.texcoords[0][1] < 0 && decal.texcoords[1][1] < 0 && decal.texcoords[2][1] < 0))
1027 if (!(decal.texcoords[0][0] > 1 && decal.texcoords[1][0] > 1 && decal.texcoords[2][0] > 1))
1028 if (!(decal.texcoords[0][1] > 1 && decal.texcoords[1][1] > 1 && decal.texcoords[2][1] > 1)) {
1029 if (decal.rotation) {
1030 for (int j = 0; j < 3; j++) {
1032 rot.x = decal.texcoords[j][0] - .5;
1033 rot.z = decal.texcoords[j][1] - .5;
1034 rot = DoRotation(rot, 0, -decal.rotation, 0);
1035 decal.texcoords[j][0] = rot.x + .5;
1036 decal.texcoords[j][1] = rot.z + .5;
1039 if (decals.size() < max_model_decals - 1) {
1040 decals.push_back(decal);
1049 void Model::MakeDecal(decal_type atype, XYZ where, float size, float opacity, float rotation)
1052 if (type != decalstype)
1056 static float distance;
1059 if (distsq(&where, &boundingspherecenter) < (boundingsphereradius + size) * (boundingsphereradius + size))
1060 for (unsigned int i = 0; i < Triangles.size(); i++) {
1061 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))));
1062 if (distance < .02 && abs(Triangles[i].facenormal.y) > abs(Triangles[i].facenormal.x) && abs(Triangles[i].facenormal.y) > abs(Triangles[i].facenormal.z)) {
1063 if ((opacity - distance / 10) > 0) {
1064 Decal decal(where, atype, opacity - distance / 10, rotation, size, *this, i, 0);
1066 if (!(decal.texcoords[0][0] < 0 && decal.texcoords[1][0] < 0 && decal.texcoords[2][0] < 0))
1067 if (!(decal.texcoords[0][1] < 0 && decal.texcoords[1][1] < 0 && decal.texcoords[2][1] < 0))
1068 if (!(decal.texcoords[0][0] > 1 && decal.texcoords[1][0] > 1 && decal.texcoords[2][0] > 1))
1069 if (!(decal.texcoords[0][1] > 1 && decal.texcoords[1][1] > 1 && decal.texcoords[2][1] > 1)) {
1070 if (decal.rotation) {
1071 for (int j = 0; j < 3; j++) {
1073 rot.x = decal.texcoords[j][0] - .5;
1074 rot.z = decal.texcoords[j][1] - .5;
1075 rot = DoRotation(rot, 0, -decal.rotation, 0);
1076 decal.texcoords[j][0] = rot.x + .5;
1077 decal.texcoords[j][1] = rot.z + .5;
1080 if (decals.size() < max_model_decals - 1) {
1081 decals.push_back(decal);
1085 } else if (distance < .02 && abs(Triangles[i].facenormal.x) > abs(Triangles[i].facenormal.y) && abs(Triangles[i].facenormal.x) > abs(Triangles[i].facenormal.z)) {
1086 if ((opacity - distance / 10) > 0) {
1087 Decal decal(where, atype, opacity - distance / 10, rotation, size, *this, i, 1);
1089 if (!(decal.texcoords[0][0] < 0 && decal.texcoords[1][0] < 0 && decal.texcoords[2][0] < 0))
1090 if (!(decal.texcoords[0][1] < 0 && decal.texcoords[1][1] < 0 && decal.texcoords[2][1] < 0))
1091 if (!(decal.texcoords[0][0] > 1 && decal.texcoords[1][0] > 1 && decal.texcoords[2][0] > 1))
1092 if (!(decal.texcoords[0][1] > 1 && decal.texcoords[1][1] > 1 && decal.texcoords[2][1] > 1)) {
1093 if (decal.rotation) {
1094 for (int j = 0; j < 3; j++) {
1096 rot.x = decal.texcoords[j][0] - .5;
1097 rot.z = decal.texcoords[j][1] - .5;
1098 rot = DoRotation(rot, 0, -decal.rotation, 0);
1099 decal.texcoords[j][0] = rot.x + .5;
1100 decal.texcoords[j][1] = rot.z + .5;
1103 if (decals.size() < max_model_decals - 1) {
1104 decals.push_back(decal);
1108 } else if (distance < .02 && abs(Triangles[i].facenormal.z) > abs(Triangles[i].facenormal.y) && abs(Triangles[i].facenormal.z) > abs(Triangles[i].facenormal.x)) {
1109 if ((opacity - distance / 10) > 0) {
1110 Decal decal(where, atype, opacity - distance / 10, rotation, size, *this, i, 2);
1112 if (!(decal.texcoords[0][0] < 0 && decal.texcoords[1][0] < 0 && decal.texcoords[2][0] < 0))
1113 if (!(decal.texcoords[0][1] < 0 && decal.texcoords[1][1] < 0 && decal.texcoords[2][1] < 0))
1114 if (!(decal.texcoords[0][0] > 1 && decal.texcoords[1][0] > 1 && decal.texcoords[2][0] > 1))
1115 if (!(decal.texcoords[0][1] > 1 && decal.texcoords[1][1] > 1 && decal.texcoords[2][1] > 1)) {
1116 if (decal.rotation) {
1117 for (int j = 0; j < 3; j++) {
1119 rot.x = decal.texcoords[j][0] - .5;
1120 rot.z = decal.texcoords[j][1] - .5;
1121 rot = DoRotation(rot, 0, -decal.rotation, 0);
1122 decal.texcoords[j][0] = rot.x + .5;
1123 decal.texcoords[j][1] = rot.z + .5;
1126 if (decals.size() < max_model_decals - 1) {
1127 decals.push_back(decal);
1136 const XYZ& Model::getTriangleVertex(unsigned triangleId, unsigned vertexId) const
1138 return vertex[Triangles[triangleId].vertex[vertexId]];
1141 void Model::deleteDeadDecals()
1143 for (int i = decals.size() - 1; i >= 0; i--) {
1144 if ((decals[i].type == blooddecal || decals[i].type == blooddecalslow) && decals[i].alivetime < 2) {
1155 void Model::deallocate()
1184 , boundingspherecenter()
1185 , boundingsphereradius(0)
1188 memset(&modelTexture, 0, sizeof(modelTexture));