1 /*
2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2017 - Lugaru contributors (see AUTHORS file)
4
5 This file is part of Lugaru.
6
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.
11
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.
16
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/>.
19 */
20
21 #include "Graphic/Models.hpp"
22
23 #include "Game.hpp"
24 #include "Utils/Folders.hpp"
25
26 extern float multiplier;
27 extern float viewdistance;
28 extern XYZ viewer;
29 extern float fadestart;
30 extern float texdetail;
31 extern bool decalstoggle;
32
LineCheck(XYZ * p1,XYZ * p2,XYZ * p,XYZ * move,float * rotate)33 int Model::LineCheck(XYZ* p1, XYZ* p2, XYZ* p, XYZ* move, float* rotate)
34 {
35 static float distance;
36 static float olddistance;
37 static int intersecting;
38 static int firstintersecting;
39 static XYZ point;
40
41 *p1 = *p1 - *move;
42 *p2 = *p2 - *move;
43 if (*rotate) {
44 *p1 = DoRotation(*p1, 0, -*rotate, 0);
45 }
46 if (*rotate) {
47 *p2 = DoRotation(*p2, 0, -*rotate, 0);
48 }
49 if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius)) {
50 return -1;
51 }
52 firstintersecting = -1;
53
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;
60 *p = point;
61 }
62 }
63
64 if (*rotate) {
65 *p = DoRotation(*p, 0, *rotate, 0);
66 }
67 *p = *p + *move;
68 return firstintersecting;
69 }
70
LineCheckPossible(XYZ * p1,XYZ * p2,XYZ * p,XYZ * move,float * rotate)71 int Model::LineCheckPossible(XYZ* p1, XYZ* p2, XYZ* p, XYZ* move, float* rotate)
72 {
73 static float distance;
74 static float olddistance;
75 static int intersecting;
76 static int firstintersecting;
77 static XYZ point;
78
79 *p1 = *p1 - *move;
80 *p2 = *p2 - *move;
81 if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius)) {
82 return -1;
83 }
84 firstintersecting = -1;
85 if (*rotate) {
86 *p1 = DoRotation(*p1, 0, -*rotate, 0);
87 }
88 if (*rotate) {
89 *p2 = DoRotation(*p2, 0, -*rotate, 0);
90 }
91
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];
99 *p = point;
100 }
101 }
102 }
103
104 if (*rotate) {
105 *p = DoRotation(*p, 0, *rotate, 0);
106 }
107 *p = *p + *move;
108 return firstintersecting;
109 }
110
LineCheckSlidePossible(XYZ * p1,XYZ * p2,XYZ * move,float * rotate)111 int Model::LineCheckSlidePossible(XYZ* p1, XYZ* p2, XYZ* move, float* rotate)
112 {
113 static float distance;
114 static float olddistance;
115 static int intersecting;
116 static int firstintersecting;
117 static XYZ point;
118
119 *p1 = *p1 - *move;
120 *p2 = *p2 - *move;
121 if (!sphere_line_intersection(p1, p2, &boundingspherecenter, &boundingsphereradius)) {
122 return -1;
123 }
124 firstintersecting = -1;
125 if (*rotate) {
126 *p1 = DoRotation(*p1, 0, -*rotate, 0);
127 }
128 if (*rotate) {
129 *p2 = DoRotation(*p2, 0, -*rotate, 0);
130 }
131
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];
139 }
140 }
141 }
142
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;
146 }
147
148 if (*rotate) {
149 *p2 = DoRotation(*p2, 0, *rotate, 0);
150 }
151 *p2 = *p2 + *move;
152 return firstintersecting;
153 }
154
SphereCheck(XYZ * p1,float radius,XYZ * p,XYZ * move,float * rotate)155 int Model::SphereCheck(XYZ* p1, float radius, XYZ* p, XYZ* move, float* rotate)
156 {
157 static int i;
158 static float distance;
159 static float olddistance;
160 static int intersecting;
161 static int firstintersecting;
162 static XYZ point;
163 static XYZ oldp1;
164
165 firstintersecting = -1;
166
167 oldp1 = *p1;
168 *p1 = *p1 - *move;
169 if (*rotate) {
170 *p1 = DoRotation(*p1, 0, -*rotate, 0);
171 }
172 if (distsq(p1, &boundingspherecenter) > radius * radius + boundingsphereradius * boundingsphereradius) {
173 return -1;
174 }
175
176 for (i = 0; i < 4; i++) {
177 for (unsigned int j = 0; j < Triangles.size(); j++) {
178 intersecting = 0;
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]])) {
183 intersecting = 1;
184 }
185 if (!intersecting) {
186 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], p1, &radius);
187 }
188 if (!intersecting) {
189 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], p1, &radius);
190 }
191 if (!intersecting) {
192 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[2]], p1, &radius);
193 }
194 if (intersecting) {
195 *p1 += Triangles[j].facenormal * (distance - radius);
196 }
197 }
198 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
199 olddistance = distance;
200 firstintersecting = j;
201 *p = point;
202 }
203 }
204 }
205 if (*rotate) {
206 *p = DoRotation(*p, 0, *rotate, 0);
207 }
208 *p = *p + *move;
209 if (*rotate) {
210 *p1 = DoRotation(*p1, 0, *rotate, 0);
211 }
212 *p1 += *move;
213 return firstintersecting;
214 }
215
SphereCheckPossible(XYZ * p1,float radius,XYZ * move,float * rotate)216 int Model::SphereCheckPossible(XYZ* p1, float radius, XYZ* move, float* rotate)
217 {
218 static float distance;
219 static float olddistance;
220 static int intersecting;
221 static int firstintersecting;
222 static XYZ point;
223 static XYZ oldp1;
224
225 firstintersecting = -1;
226
227 oldp1 = *p1;
228 *p1 = *p1 - *move;
229
230 possible.clear();
231
232 if (*rotate) {
233 *p1 = DoRotation(*p1, 0, -*rotate, 0);
234 }
235 if (distsq(p1, &boundingspherecenter) > radius * radius + boundingsphereradius * boundingsphereradius) {
236 *p1 = oldp1;
237 return -1;
238 }
239
240 for (unsigned int j = 0; j < Triangles.size(); j++) {
241 intersecting = 0;
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]])) {
246 intersecting = 1;
247 }
248 if (!intersecting) {
249 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], p1, &radius);
250 }
251 if (!intersecting) {
252 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]], p1, &radius);
253 }
254 if (!intersecting) {
255 intersecting = sphere_line_intersection(&vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[2]], p1, &radius);
256 }
257 if (intersecting) {
258 possible.push_back(j);
259 }
260 }
261 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
262 olddistance = distance;
263 firstintersecting = j;
264 }
265 }
266 if (*rotate) {
267 *p1 = DoRotation(*p1, 0, *rotate, 0);
268 }
269 *p1 += *move;
270
271 return firstintersecting;
272 }
273
UpdateVertexArray()274 void Model::UpdateVertexArray()
275 {
276 if (type != normaltype && type != decalstype) {
277 return;
278 }
279
280 if (flat) {
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;
291
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;
300
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;
309 }
310 } else {
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;
321
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;
330
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;
339 }
340 }
341 }
342
UpdateVertexArrayNoTex()343 void Model::UpdateVertexArrayNoTex()
344 {
345 if (type != normaltype && type != decalstype) {
346 return;
347 }
348
349 if (flat) {
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;
358
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;
365
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;
372 }
373 } else {
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;
382
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;
389
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;
396 }
397 }
398 }
399
UpdateVertexArrayNoTexNoNorm()400 void Model::UpdateVertexArrayNoTexNoNorm()
401 {
402 if (type != normaltype && type != decalstype) {
403 return;
404 }
405
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;
411
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;
415
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;
419 }
420 }
421
loadnotex(const std::string & filename)422 bool Model::loadnotex(const std::string& filename)
423 {
424 FILE* tfile;
425 long i;
426 short triangleNum;
427
428 type = notextype;
429 color = 0;
430
431 tfile = Folders::openMandatoryFile(Folders::getResourcePath(filename), "rb");
432
433 // read model settings
434
435 fseek(tfile, 0, SEEK_SET);
436 funpackf(tfile, "Bs Bs", &vertexNum, &triangleNum);
437
438 // read the model data
439 deallocate();
440
441 possible.clear();
442
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);
447
448 for (i = 0; i < vertexNum; i++) {
449 funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
450 }
451
452 for (i = 0; i < triangleNum; i++) {
453 short vertex[6];
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]);
460 }
461
462 fclose(tfile);
463
464 UpdateVertexArray();
465
466 for (i = 0; i < vertexNum; i++) {
467 owner[i] = -1;
468 }
469
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;
476 }
477 }
478 }
479 boundingsphereradius = fast_sqrt(boundingsphereradius);
480
481 return true;
482 }
483
load(const std::string & filename)484 bool Model::load(const std::string& filename)
485 {
486 FILE* tfile;
487 long i;
488 short triangleNum;
489
490 LOGFUNC;
491
492 LOG(std::string("Loading model...") + filename);
493
494 Game::LoadingScreen();
495
496 type = normaltype;
497 color = 0;
498
499 tfile = Folders::openMandatoryFile(Folders::getResourcePath(filename), "rb");
500
501 // read model settings
502
503 fseek(tfile, 0, SEEK_SET);
504 funpackf(tfile, "Bs Bs", &vertexNum, &triangleNum);
505
506 // read the model data
507 deallocate();
508
509 possible.clear();
510
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);
516
517 for (i = 0; i < vertexNum; i++) {
518 funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
519 }
520
521 for (i = 0; i < triangleNum; i++) {
522 short vertex[6];
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]);
529 }
530
531 modelTexture.xsz = 0;
532
533 fclose(tfile);
534
535 UpdateVertexArray();
536
537 for (i = 0; i < vertexNum; i++) {
538 owner[i] = -1;
539 }
540
541 static int j;
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;
548 }
549 }
550 }
551 boundingsphereradius = fast_sqrt(boundingsphereradius);
552
553 return true;
554 }
555
loaddecal(const std::string & filename)556 bool Model::loaddecal(const std::string& filename)
557 {
558 FILE* tfile;
559 long i, j;
560 short triangleNum;
561
562 LOGFUNC;
563
564 LOG(std::string("Loading decal...") + Folders::getResourcePath(filename));
565
566 type = decalstype;
567 color = 0;
568
569 tfile = Folders::openMandatoryFile(Folders::getResourcePath(filename), "rb");
570
571 // read model settings
572
573 fseek(tfile, 0, SEEK_SET);
574 funpackf(tfile, "Bs Bs", &vertexNum, &triangleNum);
575
576 // read the model data
577
578 deallocate();
579
580 possible.clear();
581
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);
587
588 for (i = 0; i < vertexNum; i++) {
589 funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
590 }
591
592 for (i = 0; i < triangleNum; i++) {
593 short vertex[6];
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]);
600 }
601
602 modelTexture.xsz = 0;
603
604 fclose(tfile);
605
606 UpdateVertexArray();
607
608 for (i = 0; i < vertexNum; i++) {
609 owner[i] = -1;
610 }
611
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;
618 }
619 }
620 }
621 boundingsphereradius = fast_sqrt(boundingsphereradius);
622
623 return true;
624 }
625
loadraw(const std::string & filename)626 bool Model::loadraw(const std::string& filename)
627 {
628 FILE* tfile;
629 long i;
630 short triangleNum;
631
632 LOGFUNC;
633
634 LOG(std::string("Loading raw...") + filename);
635
636 type = rawtype;
637 color = 0;
638
639 tfile = Folders::openMandatoryFile(Folders::getResourcePath(filename), "rb");
640
641 // read model settings
642
643 fseek(tfile, 0, SEEK_SET);
644 funpackf(tfile, "Bs Bs", &vertexNum, &triangleNum);
645
646 // read the model data
647 deallocate();
648
649 possible.clear();
650
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);
655
656 for (i = 0; i < vertexNum; i++) {
657 funpackf(tfile, "Bf Bf Bf", &vertex[i].x, &vertex[i].y, &vertex[i].z);
658 }
659
660 for (i = 0; i < triangleNum; i++) {
661 short vertex[6];
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]);
668 }
669
670 fclose(tfile);
671
672 for (i = 0; i < vertexNum; i++) {
673 owner[i] = -1;
674 }
675
676 return true;
677 }
678
UniformTexCoords()679 void Model::UniformTexCoords()
680 {
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;
688 }
689 UpdateVertexArray();
690 }
691
FlipTexCoords()692 void Model::FlipTexCoords()
693 {
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];
698 }
699 UpdateVertexArray();
700 }
701
ScaleTexCoords(float howmuch)702 void Model::ScaleTexCoords(float howmuch)
703 {
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;
711 }
712 UpdateVertexArray();
713 }
714
Scale(float xscale,float yscale,float zscale)715 void Model::Scale(float xscale, float yscale, float zscale)
716 {
717 static int i;
718 for (i = 0; i < vertexNum; i++) {
719 vertex[i].x *= xscale;
720 vertex[i].y *= yscale;
721 vertex[i].z *= zscale;
722 }
723 UpdateVertexArray();
724
725 static int j;
726
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;
733 }
734 }
735 }
736 boundingsphereradius = fast_sqrt(boundingsphereradius);
737 }
738
ScaleNormals(float xscale,float yscale,float zscale)739 void Model::ScaleNormals(float xscale, float yscale, float zscale)
740 {
741 if (type != normaltype && type != decalstype) {
742 return;
743 }
744
745 for (int i = 0; i < vertexNum; i++) {
746 normals[i].x *= xscale;
747 normals[i].y *= yscale;
748 normals[i].z *= zscale;
749 }
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;
754 }
755 UpdateVertexArray();
756 }
757
Translate(float xtrans,float ytrans,float ztrans)758 void Model::Translate(float xtrans, float ytrans, float ztrans)
759 {
760 static int i;
761 for (i = 0; i < vertexNum; i++) {
762 vertex[i].x += xtrans;
763 vertex[i].y += ytrans;
764 vertex[i].z += ztrans;
765 }
766 UpdateVertexArray();
767
768 static int j;
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;
775 }
776 }
777 }
778 boundingsphereradius = fast_sqrt(boundingsphereradius);
779 }
780
Rotate(float xang,float yang,float zang)781 void Model::Rotate(float xang, float yang, float zang)
782 {
783 static int i;
784 for (i = 0; i < vertexNum; i++) {
785 vertex[i] = DoRotation(vertex[i], xang, yang, zang);
786 }
787 UpdateVertexArray();
788
789 static int j;
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;
796 }
797 }
798 }
799 boundingsphereradius = fast_sqrt(boundingsphereradius);
800 }
801
CalculateNormals(bool facenormalise)802 void Model::CalculateNormals(bool facenormalise)
803 {
804 Game::LoadingScreen();
805
806 if (type != normaltype && type != decalstype) {
807 return;
808 }
809
810 for (int i = 0; i < vertexNum; i++) {
811 normals[i].x = 0;
812 normals[i].y = 0;
813 normals[i].z = 0;
814 }
815
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);
818
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;
822
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;
826
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;
830 if (facenormalise) {
831 Normalise(&Triangles[i].facenormal);
832 }
833 }
834 for (int i = 0; i < vertexNum; i++) {
835 Normalise(&normals[i]);
836 normals[i] *= -1;
837 }
838 UpdateVertexArrayNoTex();
839 }
840
drawimmediate()841 void Model::drawimmediate()
842 {
843 textureptr.bind();
844 glBegin(GL_TRIANGLES);
845 for (unsigned int i = 0; i < Triangles.size(); i++) {
846 glTexCoord2f(Triangles[i].gx[0], Triangles[i].gy[0]);
847 if (color) {
848 glColor3f(normals[Triangles[i].vertex[0]].x, normals[Triangles[i].vertex[0]].y, normals[Triangles[i].vertex[0]].z);
849 } else if (flat) {
850 glNormal3f(Triangles[i].facenormal.x, Triangles[i].facenormal.y, Triangles[i].facenormal.y);
851 } else {
852 glNormal3f(normals[Triangles[i].vertex[0]].x, normals[Triangles[i].vertex[0]].y, normals[Triangles[i].vertex[0]].z);
853 }
854 glVertex3f(vertex[Triangles[i].vertex[0]].x, vertex[Triangles[i].vertex[0]].y, vertex[Triangles[i].vertex[0]].z);
855
856 glTexCoord2f(Triangles[i].gx[1], Triangles[i].gy[1]);
857 if (color) {
858 glColor3f(normals[Triangles[i].vertex[1]].x, normals[Triangles[i].vertex[1]].y, normals[Triangles[i].vertex[1]].z);
859 } else if (flat) {
860 glNormal3f(Triangles[i].facenormal.x, Triangles[i].facenormal.y, Triangles[i].facenormal.y);
861 } else {
862 glNormal3f(normals[Triangles[i].vertex[1]].x, normals[Triangles[i].vertex[1]].y, normals[Triangles[i].vertex[1]].z);
863 }
864 glVertex3f(vertex[Triangles[i].vertex[1]].x, vertex[Triangles[i].vertex[1]].y, vertex[Triangles[i].vertex[1]].z);
865
866 glTexCoord2f(Triangles[i].gx[2], Triangles[i].gy[2]);
867 if (color) {
868 glColor3f(normals[Triangles[i].vertex[2]].x, normals[Triangles[i].vertex[2]].y, normals[Triangles[i].vertex[2]].z);
869 } else if (flat) {
870 glNormal3f(Triangles[i].facenormal.x, Triangles[i].facenormal.y, Triangles[i].facenormal.y);
871 } else {
872 glNormal3f(normals[Triangles[i].vertex[2]].x, normals[Triangles[i].vertex[2]].y, normals[Triangles[i].vertex[2]].z);
873 }
874 glVertex3f(vertex[Triangles[i].vertex[2]].x, vertex[Triangles[i].vertex[2]].y, vertex[Triangles[i].vertex[2]].z);
875 }
876 glEnd();
877 }
878
draw()879 void Model::draw()
880 {
881 if (type != normaltype && type != decalstype) {
882 return;
883 }
884
885 glEnableClientState(GL_NORMAL_ARRAY);
886 glEnableClientState(GL_VERTEX_ARRAY);
887 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
888
889 if (color) {
890 glInterleavedArrays(GL_T2F_C3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
891 } else {
892 glInterleavedArrays(GL_T2F_N3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
893 }
894 textureptr.bind();
895
896 glDrawArrays(GL_TRIANGLES, 0, Triangles.size() * 3);
897
898 if (color) {
899 glDisableClientState(GL_COLOR_ARRAY);
900 } else {
901 glDisableClientState(GL_NORMAL_ARRAY);
902 }
903 glDisableClientState(GL_VERTEX_ARRAY);
904 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
905 }
906
drawdifftex(Texture texture)907 void Model::drawdifftex(Texture texture)
908 {
909 glEnableClientState(GL_NORMAL_ARRAY);
910 glEnableClientState(GL_VERTEX_ARRAY);
911 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
912 if (color) {
913 glInterleavedArrays(GL_T2F_C3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
914 } else {
915 glInterleavedArrays(GL_T2F_N3F_V3F, 8 * sizeof(GLfloat), &vArray[0]);
916 }
917
918 texture.bind();
919 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
920 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
921
922 glDrawArrays(GL_TRIANGLES, 0, Triangles.size() * 3);
923
924 if (color) {
925 glDisableClientState(GL_COLOR_ARRAY);
926 } else {
927 glDisableClientState(GL_NORMAL_ARRAY);
928 }
929 glDisableClientState(GL_VERTEX_ARRAY);
930 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
931 }
932
drawdecals(Texture shadowtexture,Texture bloodtexture,Texture bloodtexture2,Texture breaktexture)933 void Model::drawdecals(Texture shadowtexture, Texture bloodtexture, Texture bloodtexture2, Texture breaktexture)
934 {
935 if (decalstoggle) {
936 if (type != decalstype) {
937 return;
938 }
939
940 bool blend = true;
941 int lasttype = -1;
942
943 glEnable(GL_BLEND);
944 glDisable(GL_LIGHTING);
945 glDisable(GL_CULL_FACE);
946 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
947 glDepthMask(0);
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;
951 }
952
953 if (decals[i].type != lasttype) {
954 if (decals[i].type == shadowdecal) {
955 shadowtexture.bind();
956 if (!blend) {
957 blend = 1;
958 glAlphaFunc(GL_GREATER, 0.0001);
959 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
960 }
961 }
962 if (decals[i].type == breakdecal) {
963 breaktexture.bind();
964 if (!blend) {
965 blend = 1;
966 glAlphaFunc(GL_GREATER, 0.0001);
967 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
968 }
969 }
970 if (decals[i].type == blooddecal || decals[i].type == blooddecalslow) {
971 bloodtexture.bind();
972 if (blend) {
973 blend = 0;
974 glAlphaFunc(GL_GREATER, 0.15);
975 glBlendFunc(GL_ONE, GL_ZERO);
976 }
977 }
978 if (decals[i].type == blooddecalfast) {
979 bloodtexture2.bind();
980 if (blend) {
981 blend = 0;
982 glAlphaFunc(GL_GREATER, 0.15);
983 glBlendFunc(GL_ONE, GL_ZERO);
984 }
985 }
986 }
987 if (decals[i].type == shadowdecal) {
988 glColor4f(1, 1, 1, decals[i].opacity);
989 }
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);
994 }
995 }
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);
1000 }
1001 if (decals[i].alivetime > 58) {
1002 glColor4f(1, 1, 1, decals[i].opacity * (60 - decals[i].alivetime) / 2);
1003 }
1004 }
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);
1008
1009 glMatrixMode(GL_MODELVIEW);
1010 glPushMatrix();
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);
1015 }
1016 glEnd();
1017 glPopMatrix();
1018 }
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;
1023 }
1024 if (decals[i].type == blooddecalfast) {
1025 decals[i].alivetime += multiplier * 4;
1026 }
1027 if (decals[i].type == shadowdecal) {
1028 DeleteDecal(i);
1029 }
1030 if ((decals[i].type == blooddecal || decals[i].type == blooddecalfast || decals[i].type == blooddecalslow) && decals[i].alivetime >= 60) {
1031 DeleteDecal(i);
1032 }
1033 }
1034 glAlphaFunc(GL_GREATER, 0.0001);
1035 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1036 }
1037 }
1038
DeleteDecal(int which)1039 void Model::DeleteDecal(int which)
1040 {
1041 if (decalstoggle) {
1042 if (type != decalstype) {
1043 return;
1044 }
1045 decals.erase(decals.begin() + which);
1046 }
1047 }
1048
MakeDecal(decal_type atype,XYZ * where,float * size,float * opacity,float * rotation)1049 void Model::MakeDecal(decal_type atype, XYZ* where, float* size, float* opacity, float* rotation)
1050 {
1051 if (decalstoggle) {
1052 if (type != decalstype) {
1053 return;
1054 }
1055
1056 static XYZ rot;
1057 static float distance;
1058
1059 if (*opacity > 0) {
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);
1064
1065 if ((*opacity - distance / 10) > 0) {
1066 Decal decal(*where, atype, *opacity - distance / 10, *rotation, *size, *this, i, 0);
1067
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++) {
1074 rot.y = 0;
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;
1080 }
1081 }
1082 if (decals.size() < max_model_decals - 1) {
1083 decals.push_back(decal);
1084 }
1085 }
1086 }
1087 }
1088 }
1089 }
1090 }
1091 }
1092 }
1093 }
1094 }
1095 }
1096
MakeDecal(decal_type atype,XYZ where,float size,float opacity,float rotation)1097 void Model::MakeDecal(decal_type atype, XYZ where, float size, float opacity, float rotation)
1098 {
1099 if (decalstoggle) {
1100 if (type != decalstype) {
1101 return;
1102 }
1103
1104 static XYZ rot;
1105 static float distance;
1106
1107 if (opacity > 0) {
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);
1114
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++) {
1121 rot.y = 0;
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;
1127 }
1128 }
1129 if (decals.size() < max_model_decals - 1) {
1130 decals.push_back(decal);
1131 }
1132 }
1133 }
1134 }
1135 }
1136 }
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);
1140
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++) {
1147 rot.y = 0;
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;
1153 }
1154 }
1155 if (decals.size() < max_model_decals - 1) {
1156 decals.push_back(decal);
1157 }
1158 }
1159 }
1160 }
1161 }
1162 }
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);
1166
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++) {
1173 rot.y = 0;
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;
1179 }
1180 }
1181 if (decals.size() < max_model_decals - 1) {
1182 decals.push_back(decal);
1183 }
1184 }
1185 }
1186 }
1187 }
1188 }
1189 }
1190 }
1191 }
1192 }
1193 }
1194 }
1195
getTriangleVertex(unsigned triangleId,unsigned vertexId) const1196 const XYZ& Model::getTriangleVertex(unsigned triangleId, unsigned vertexId) const
1197 {
1198 return vertex[Triangles[triangleId].vertex[vertexId]];
1199 }
1200
deleteDeadDecals()1201 void Model::deleteDeadDecals()
1202 {
1203 for (int i = decals.size() - 1; i >= 0; i--) {
1204 if ((decals[i].type == blooddecal || decals[i].type == blooddecalslow) && decals[i].alivetime < 2) {
1205 DeleteDecal(i);
1206 }
1207 }
1208 }
1209
~Model()1210 Model::~Model()
1211 {
1212 deallocate();
1213 }
1214
deallocate()1215 void Model::deallocate()
1216 {
1217 if (owner) {
1218 free(owner);
1219 }
1220 owner = 0;
1221
1222 if (vertex) {
1223 free(vertex);
1224 }
1225 vertex = 0;
1226
1227 if (normals) {
1228 free(normals);
1229 }
1230 normals = 0;
1231
1232 if (vArray) {
1233 free(vArray);
1234 }
1235 vArray = 0;
1236
1237 decals.clear();
1238 }
1239
Model()1240 Model::Model()
1241 : vertexNum(0)
1242 , type(nothing)
1243 , owner(0)
1244 , vertex(0)
1245 , normals(0)
1246 , vArray(0)
1247 , color(0)
1248 , boundingspherecenter()
1249 , boundingsphereradius(0)
1250 , flat(false)
1251 {
1252 memset(&modelTexture, 0, sizeof(modelTexture));
1253 }
1254