6584f7978727f206fa84546b3286c47bb3452e3a
[tar-legacy.git] / MCDV / vmf.hpp
1 #pragma once
2 #include <iostream>
3 #include <fstream>
4 #include <glm\glm.hpp>
5 #include <glm\gtc\matrix_transform.hpp>
6 #include <glm\gtc\type_ptr.hpp>
7
8 #include <sstream>
9 #include <vector>
10 #include <map>
11 #include <regex>
12
13 #include "Util.h"
14 #include "vdf.hpp"
15 #include "plane.h"
16 #include "Mesh.hpp"
17 #include "convexPolytope.h"
18 #include "fuzzy_select.h"
19 #include "interpolation.h"
20
21 #include <algorithm>
22
23 #include <chrono>
24
25 namespace vmf_parse {
26 //Pass Vector3
27 bool Vector3f(std::string str, glm::vec3* vec)
28 {
29 str = sutil::removeChar(str, '(');
30 str = sutil::removeChar(str, ')');
31
32 std::vector<std::string> elems = split(str, ' ');
33 std::vector<float> pelems;
34
35 for (int i = 0; i < elems.size(); i++) {
36 std::string f = sutil::trim(elems[i]);
37
38 //TODO: error check against invalid values here
39 float e = ::atof(f.c_str());
40 pelems.push_back(e);
41 }
42
43 if (pelems.size() == 3) {
44 *vec = glm::vec3(pelems[0], pelems[1], pelems[2]);
45 return true;
46 }
47
48 return false;
49 }
50
51 //Parse Vector 3 with square barackets. Thanks again, valve
52 bool Vector3fS(std::string str, glm::vec3* vec)
53 {
54 str = sutil::removeChar(str, '[');
55 str = sutil::removeChar(str, ']');
56
57 std::vector<std::string> elems = split(str, ' ');
58 std::vector<float> pelems;
59
60 for (int i = 0; i < elems.size(); i++) {
61 std::string f = sutil::trim(elems[i]);
62
63 //TODO: error check against invalid values here
64 float e = ::atof(f.c_str());
65 pelems.push_back(e);
66 }
67
68 if (pelems.size() == 3) {
69 *vec = glm::vec3(pelems[0], pelems[1], pelems[2]);
70 return true;
71 }
72
73 return false;
74 }
75
76 //Parse plane from standard 3 point notation (ax, ay, az) (bx, by, bz) ...
77 bool plane(std::string str, Plane* plane)
78 {
79 std::vector<std::string> points = split(str, '(');
80
81 if (points.size() != 4) { return false; }
82
83 glm::vec3 A, B, C;
84
85 if (!(Vector3f(points[1], &A) && Vector3f(points[2], &B) && Vector3f(points[3], &C))) {
86 return false;
87 }
88
89 *plane = Plane(A, B, C);
90
91 return true;
92 }
93 }
94
95
96 namespace vmf {
97
98 int current_line = 0;
99 int line_count = 0;
100 void progress_callback() {
101 current_line++;
102
103 if (current_line == line_count - 1)
104 std::cout << "Line " << current_line << "/" << line_count << "\n";
105 if(((current_line % 10000) == 0))
106 std::cout << "Line " << current_line << "/" << line_count << "\r";
107 }
108
109 enum team {
110 terrorist,
111 counter_terrorist
112 };
113
114 struct BoundingBox {
115 glm::vec3 NWU;
116 glm::vec3 SEL;
117 };
118
119 struct DispInfo {
120 int power;
121 glm::vec3 startposition;
122
123 std::vector<std::vector<glm::vec3>> normals;
124 std::vector<std::vector<float>> distances;
125
126 // OpenGL generated mesh
127 Mesh* glMesh;
128 };
129
130 struct Side {
131 int ID;
132 std::string texture;
133 Plane plane;
134
135 DispInfo* displacement = NULL;
136 };
137
138 struct Solid {
139 int fileorder_id;
140 int ID;
141 bool containsDisplacements = false;
142 std::vector<Side> faces;
143 glm::vec3 color;
144 glm::vec3 origin;
145 bool hidden = false;
146
147 std::vector<unsigned short> visgroupids;
148
149 BoundingBox bounds;
150
151 Mesh* mesh;
152 };
153
154 struct BuyZone {
155 int teamNum;
156 Mesh* mesh;
157 };
158
159 struct Entity {
160 int ID;
161 std::string classname;
162 glm::vec3 origin;
163
164 std::map<std::string, std::string> keyValues;
165 std::vector<Solid> internal_solids;
166
167 bool hidden = false;
168 };
169
170 class vmf {
171 public:
172 kv::FileData internal;
173 std::vector<Mesh> meshes;
174 std::vector<Solid> solids;
175 std::vector<Entity> entities;
176
177 std::map<unsigned short, std::string> visgroups;
178
179 vmf(std::string path)
180 {
181 std::ifstream ifs(path);
182 if (!ifs) {
183 std::cout << "Could not open file... " << path << std::endl;
184 throw std::exception("File read error");
185 }
186
187 std::cout << "Initializing VMF read\n";
188 std::ifstream _ifs(path);
189
190 // new lines will be skipped unless we stop it from happening:
191 _ifs.unsetf(std::ios_base::skipws);
192
193 // count the newlines with an algorithm specialized for counting:
194 line_count = std::count(
195 std::istream_iterator<char>(_ifs),
196 std::istream_iterator<char>(),
197 '\n');
198
199 _ifs.close();
200
201 std::cout << "Reading raw VMF\n";
202 std::string str((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
203
204 std::cout << "Processing VMF data\n";
205 kv::FileData data(str, &progress_callback);
206
207 this->internal = data;
208
209 #pragma region Solids
210 std::cout << "Processing solids\n";
211
212 //Process solids list
213 std::vector<kv::DataBlock> SolidList = data.headNode.GetFirstByName("world")->GetAllByName("solid");
214 int total = SolidList.size();
215
216 for (int i = 0; i < SolidList.size(); i++){
217 std::cout << "Solid " << i + 1 << "/" << total << "\r";
218
219 kv::DataBlock cBlock = SolidList[i];
220
221 Solid solid;
222 bool valid = true;
223
224 std::vector<kv::DataBlock> Sides = cBlock.GetAllByName("side");
225 for (int j = 0; j < Sides.size(); j++)
226 {
227 kv::DataBlock cSide = Sides[j];
228
229 Side side;
230 side.ID = ::atof(cSide.Values["id"].c_str());
231 side.texture = cSide.Values["material"];
232
233 Plane plane;
234 if (!vmf_parse::plane(cSide.Values["plane"], &plane))
235 {
236 valid = false; break;
237 }
238
239 side.plane = plane;
240
241 // Deal with displacement info. Oh no
242
243 #pragma region displacements
244
245 DispInfo* dispInfo = new DispInfo;
246
247 kv::DataBlock* dblockInfo = cSide.GetFirstByName("dispinfo");
248
249 if (dblockInfo != NULL){
250 solid.containsDisplacements = true; // Mark we have displacements here
251
252 kv::DataBlock* dblockNormals = dblockInfo->GetFirstByName("normals");
253 kv::DataBlock* dblockDistances = dblockInfo->GetFirstByName("distances");
254 dispInfo->power = std::stoi(dblockInfo->Values["power"]);
255 vmf_parse::Vector3fS(dblockInfo->Values["startposition"], &dispInfo->startposition);
256
257 int i_target = glm::pow(2, dispInfo->power) + 1;
258
259 for (int x = 0; x < i_target; x++) { //Row
260 dispInfo->normals.push_back(std::vector<glm::vec3>()); //Create row container
261 dispInfo->distances.push_back(std::vector<float>()); //Create distances container
262
263 //Parse in the normals
264 std::vector<std::string> values = split(dblockNormals->Values["row" + std::to_string(x)]);
265 std::vector<float> list;
266 for (auto && v : values) list.push_back(::atof(v.c_str()));
267
268 //Parse in the distances
269 std::vector<std::string> _values = split(dblockDistances->Values["row" + std::to_string(x)]);
270 for (auto && v : _values) dispInfo->distances[x].push_back(std::stof(v.c_str()));
271
272 for (int xx = 0; xx < i_target; xx++) { //Column
273 dispInfo->normals[x].push_back(
274 glm::vec3(list[xx * 3 + 0],
275 list[xx * 3 + 1],
276 list[xx * 3 + 2]));
277 }
278 }
279
280 side.displacement = dispInfo;
281 }
282 #pragma endregion
283
284 solid.faces.push_back(side);
285 }
286
287 kv::DataBlock* editorValues = cBlock.GetFirstByName("editor");
288
289 //Gather up the visgroups
290 int viscount = -1;
291 while (editorValues->Values.count("visgroupid" + (++viscount > 0 ? std::to_string(viscount) : "")))
292 solid.visgroupids.push_back(std::stoi(editorValues->Values["visgroupid" + (viscount > 0 ? std::to_string(viscount) : "")]));
293
294 glm::vec3 color;
295 if (vmf_parse::Vector3f(editorValues->Values["color"], &color))
296 solid.color = glm::vec3(color.x / 255.0f, color.y / 255.0f, color.z / 255.0f);
297 else
298 solid.color = glm::vec3(1, 0, 0);
299
300 this->solids.push_back(solid);
301 }
302
303 std::cout << "\n";
304
305 #pragma endregion Solids
306 #pragma region Entities
307 std::cout << "Processing entites\n";
308
309 //Process entities list
310 std::vector<kv::DataBlock> EntitiesList = data.headNode.GetAllByName("entity");
311 for (auto && block : EntitiesList) {
312
313 //if (block.Values["classname"] != "prop_static") continue; //Skip anything else than prop static for now
314
315 //Check wether origin can be resolved for entity
316 if ((block.GetFirstByName("solid") == NULL) && (block.Values.count("origin") == 0)) {
317 std::cout << "Origin could not be resolved for entity with ID " << block.Values["id"]; continue;
318 }
319
320 Entity ent;
321 ent.classname = block.Values["classname"];
322 ent.ID = (int)::atof(block.Values["id"].c_str());
323 ent.keyValues = block.Values;
324
325 glm::vec3 loc = glm::vec3();
326 if (block.Values.count("origin")) { //Start with hammer origin
327 vmf_parse::Vector3f(block.Values["origin"], &loc);
328 ent.origin = glm::vec3(loc.x, loc.y, loc.z);
329 }
330 else if (block.GetFirstByName("solid") != NULL) { //Try to process it from solid
331 //Get all solids
332 std::vector<kv::DataBlock> _solids = block.GetAllByName("solid");
333 //std::vector<Solid> _solids_ent;
334 for (int i = 0; i < _solids.size(); i++)
335 {
336 kv::DataBlock cBlock = _solids[i];
337
338 Solid solid;
339 bool valid = true;
340
341 std::vector<kv::DataBlock> Sides = cBlock.GetAllByName("side");
342 for (int j = 0; j < Sides.size(); j++)
343 {
344 kv::DataBlock cSide = Sides[j];
345
346 Side side;
347 side.ID = ::atof(cSide.Values["id"].c_str());
348 side.texture = cSide.Values["material"];
349
350 Plane plane;
351 if (!vmf_parse::plane(cSide.Values["plane"], &plane))
352 {
353 valid = false; break;
354 }
355
356 side.plane = plane;
357
358 solid.faces.push_back(side);
359 }
360
361 kv::DataBlock* editorValues = block.GetFirstByName("editor");
362
363 //Gather up the visgroups
364 int viscount = -1;
365 while (editorValues->Values.count("visgroupid" + (++viscount > 0 ? std::to_string(viscount) : "")))
366 solid.visgroupids.push_back(std::stoi(editorValues->Values["visgroupid" + (viscount > 0 ? std::to_string(viscount) : "")]));
367
368 glm::vec3 color;
369 if (vmf_parse::Vector3f(editorValues->Values["color"], &color))
370 solid.color = glm::vec3(color.x / 255.0f, color.y / 255.0f, color.z / 255.0f);
371 else
372 solid.color = glm::vec3(1, 0, 0);
373
374 ent.internal_solids.push_back(solid);
375 }
376
377 //Process convex polytopes & calculate origin
378
379 std::vector<Polytope> polytopes;
380
381 for (auto && iSolid : ent.internal_solids) {
382 std::vector<Plane> planes;
383 for (auto f : iSolid.faces) planes.push_back(f.plane);
384
385 polytopes.push_back(Polytope(planes, false));
386 }
387
388 glm::vec3 NWU = polytopes[0].NWU;
389 glm::vec3 SEL = polytopes[0].SEL;
390
391 for (auto && iPoly : polytopes) {
392 if (iPoly.NWU.z > NWU.z) NWU.z = iPoly.NWU.z;
393 if (iPoly.NWU.y > NWU.y) NWU.y = iPoly.NWU.y;
394 if (iPoly.NWU.x > NWU.x) NWU.x = iPoly.NWU.x;
395
396 if (iPoly.SEL.z < SEL.z) SEL.z = iPoly.SEL.z;
397 if (iPoly.SEL.y < SEL.y) SEL.y = iPoly.SEL.y;
398 if (iPoly.SEL.x < SEL.x) SEL.x = iPoly.SEL.x;
399 }
400
401 ent.origin = (NWU + SEL) * 0.5f;
402 }
403
404 this->entities.push_back(ent);
405 }
406 #pragma endregion
407
408 std::cout << "Processing visgroups\n";
409
410 //Process Visgroups
411 std::vector<kv::DataBlock> VisList = data.headNode.GetFirstByName("visgroups")->GetAllByName("visgroup");
412 for (auto v : VisList) {
413 this->visgroups.insert({ std::stoi(v.Values["visgroupid"]), v.Values["name"] });
414
415 std::cout << "Visgroup {" << std::stoi(v.Values["visgroupid"]) << "} = '" << v.Values["name"] << "'\n";
416 }
417 }
418
419 std::vector<Solid*> getSolidsInVisGroup(std::string visgroup) {
420 std::vector<Solid*> list;
421 for (auto && v : this->solids) {
422 for (auto && vid : v.visgroupids) {
423 if (this->visgroups[vid] == visgroup) {
424 list.push_back(&v);
425 }
426 }
427 }
428
429 return list;
430 }
431
432 std::vector<Solid*> getAllBrushesInVisGroup(std::string visgroup) {
433 std::vector<Solid*> list;
434
435 // All solids
436 for (auto && v : this->solids) {
437 for (auto && vid : v.visgroupids) {
438 if (this->visgroups[vid] == visgroup) {
439 list.push_back(&v);
440 }
441 }
442 }
443
444 // All entity brush solids
445 for (auto && e : this->entities) {
446 for (auto && es : e.internal_solids) {
447 for (auto && esvid : es.visgroupids) {
448 if (this->visgroups[esvid] == visgroup) {
449 list.push_back(&es);
450 }
451 }
452 }
453 }
454
455 return list;
456 }
457
458 std::vector<Solid*> getAllRenderBrushes() {
459 std::vector<Solid*> list;
460 for (auto && s : this->solids)
461 list.push_back(&s);
462
463 for (auto && ent : this->entities) {
464 if (ent.classname == "func_detail" || ent.classname == "func_brush") {
465 for (auto && s : ent.internal_solids) {
466 list.push_back(&s);
467 }
468 }
469 }
470
471 return list;
472 }
473
474 std::vector<Solid*> getAllBrushesByClassNameAppend(std::string classname) {
475
476 }
477
478 std::vector<Solid*> getAllBrushesByClassName(std::string classname) {
479 std::vector<Solid*> list;
480 for (auto && ent : this->entities) {
481 if (ent.classname == classname) {
482 for (auto && s : ent.internal_solids) {
483 list.push_back(&s);
484 }
485 }
486 }
487 return list;
488 }
489
490 /* Gets a list of entities with matching classname */
491 std::vector<Entity*> findEntitiesByClassName(std::string classname) {
492 std::vector<Entity*> list;
493 for (auto && ent : this->entities) {
494 if (ent.classname == classname) {
495 list.push_back(&ent);
496 }
497 }
498 return list;
499 }
500
501 glm::vec3* calculateSpawnLocation(team _team) {
502
503 std::vector<Entity*> spawns = this->findEntitiesByClassName(_team == team::terrorist ? "info_player_terrorist" : "info_player_counterterrorist");
504
505 if (spawns.size() <= 0) return NULL;
506
507 //Find lowest priority (highest)
508 int lowest = kv::tryGetValue<int>(spawns[0]->keyValues, "priority", 0);
509 for (auto && s : spawns) {
510 int l = kv::tryGetValue<int>(s->keyValues, "priority", 0);
511 lowest = l < lowest ? l : lowest;
512 }
513
514 //Collect all spawns with that priority
515 glm::vec3* location = new glm::vec3();
516 int c = 0;
517 for (auto && s : spawns) {
518 if (kv::tryGetValue<int>(s->keyValues, "priority", 0) == lowest) {
519 *location += s->origin; c++;
520 }
521 }
522
523 //avg
524 *location = *location / (float)c;
525 return location;
526 }
527
528 void ComputeGLMeshes() {
529 auto start = std::chrono::high_resolution_clock::now();
530
531 std::cout << "Processing solid meshes... ";
532 for (int i = 0; i < this->solids.size(); i++) {
533 std::vector<Plane> sidePlanes;
534 for (int j = 0; j < this->solids[i].faces.size(); j++)
535 sidePlanes.push_back(this->solids[i].faces[j].plane);
536
537 Polytope p = Polytope(sidePlanes);
538 this->solids[i].mesh = p.GeneratedMesh;
539 this->solids[i].origin = (p.NWU + p.SEL) * 0.5f;
540 this->solids[i].bounds.NWU = p.NWU;
541 this->solids[i].bounds.SEL = p.SEL;
542 }
543 std::cout << "done\n";
544
545 std::cout << "Processing entity solid meshes... ";
546 for (auto && ent : this->entities) {
547 for (auto && _solid : ent.internal_solids) {
548 std::vector<Plane> sidePlanes;
549 for (auto f : _solid.faces)
550 sidePlanes.push_back(f.plane);
551
552 Polytope p = Polytope(sidePlanes);
553 _solid.mesh = p.GeneratedMesh;
554 _solid.origin = (p.NWU + p.SEL) * 0.5f;
555 _solid.bounds.NWU = p.NWU;
556 _solid.bounds.SEL = p.SEL;
557 }
558 }
559 std::cout << "done\n";
560
561 auto elapsed = std::chrono::high_resolution_clock::now() - start;
562 long long milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count();
563
564 std::cout << "GL mesh computation: " << milliseconds << "ms" << std::endl;
565 }
566
567 void ComputeDisplacements() {
568 auto start = std::chrono::high_resolution_clock::now();
569
570 std::cout << "Computing displacements...\n";
571
572 for (auto && v :this->solids) {
573 if (v.containsDisplacements) {
574
575 std::vector<Plane> planes;
576 for (auto && face : v.faces) planes.push_back(face.plane);
577
578 Polytope polyTope = Polytope(planes, true, false); // Generate polytope so we can look at the individual ngon points
579
580 for (auto && side :v.faces) {
581 if (side.displacement != NULL) {
582 DispInfo* info = side.displacement;
583
584 BrushPolygon* bpoly = NULL;
585
586 std::map<float, BrushPolygon*> normalCorrelations;
587
588 //Sort planes by their similarity to the face's normal direction
589 for (auto && fuck : polyTope.ngons)
590 normalCorrelations.insert({ glm::distance(fuck.plane.normal, side.plane.normal), &fuck });
591
592 bpoly = normalCorrelations.begin()->second;
593
594 if (bpoly->vertices.size() != 4) {
595 std::cout << "Displacement info matched to face with {" << bpoly->vertices.size() << "} vertices!!!\n"; continue;
596 }
597
598 // Match the 'starting point' of dispinfo
599 std::map<float, glm::vec3*> distancesToStart;
600 for (auto && point : bpoly->vertices)
601 distancesToStart.insert({ glm::distance(info->startposition, point), &point });
602
603 // The corners of the displacement
604 glm::vec3* SW = distancesToStart.begin()->second;
605
606 // Find what point in the vector it was
607 int pos = 0;
608 for (auto && point : bpoly->vertices)
609 if (&point == SW) break; else pos++;
610
611 // Get the rest of the points, in clockwise order (they should already be sorted by polytope generation)
612 glm::vec3* NW = &bpoly->vertices[(pos + 1) % 4];
613 glm::vec3* NE = &bpoly->vertices[(pos + 2) % 4];
614 glm::vec3* SE = &bpoly->vertices[(pos + 3) % 4];
615
616 int points = glm::pow(2, info->power) + 1; // calculate the point count (5, 9, 17)
617
618 // Initialize list for floats
619 std::vector<float> meshPoints;
620
621 std::vector<glm::vec3> finalPoints;
622
623 glm::vec3* NWU = &v.bounds.NWU;
624 glm::vec3* SEL = &v.bounds.SEL;
625
626 for (int row = 0; row < points; row++) {
627 for (int col = 0; col < points; col++) {
628 //Generate original base points
629
630 float dx = (float)col / (float)(points-1); //Time values for linear interpolation
631 float dy = (float)row / (float)(points-1);
632
633 glm::vec3 LWR = lerp(*SW, *SE, dx);
634 glm::vec3 UPR = lerp(*NW, *NE, dx);
635 glm::vec3 P = lerp(LWR, UPR, dy); // Original point location
636
637 glm::vec3 offset = info->normals[col][row] * info->distances[col][row]; // Calculate offset
638 P = P + offset; //Add offset to P
639
640 finalPoints.push_back(P);
641
642 //Recompute bounds while we are at it
643 NWU->x = glm::max(-P.x, NWU->x);
644 NWU->y = glm::max(P.z, NWU->y);
645 NWU->z = glm::max(P.y, NWU->z);
646
647 SEL->x = glm::min(-P.x, SEL->x);
648 SEL->y = glm::min(P.z, SEL->y);
649 SEL->z = glm::min(P.y, SEL->z);
650
651 continue;
652
653 /* TESTING TRIANGLES */
654 meshPoints.push_back(-P.x);
655 meshPoints.push_back(P.z);
656 meshPoints.push_back(P.y);
657 meshPoints.push_back(0);
658 meshPoints.push_back(0);
659 meshPoints.push_back(1);
660
661 meshPoints.push_back(-P.x);
662 meshPoints.push_back(P.z);
663 meshPoints.push_back(P.y + 8.0f);
664 meshPoints.push_back(0);
665 meshPoints.push_back(0);
666 meshPoints.push_back(1);
667
668
669 meshPoints.push_back(-P.x + 8.0f);
670 meshPoints.push_back(P.z);
671 meshPoints.push_back(P.y + 8.0f);
672 meshPoints.push_back(0);
673 meshPoints.push_back(0);
674 meshPoints.push_back(1);
675 }
676 }
677
678 int i_condition = 0;
679 for (int row = 0; row < points - 1; row++) {
680 for (int col = 0; col < points - 1; col++) {
681
682 // Gather point pointers
683 // hehe :(
684 glm::vec3* SW = &finalPoints[((row + 0) * points) + (col + 0)];
685 glm::vec3* SE = &finalPoints[((row + 0) * points) + (col + 1)];
686
687 glm::vec3* NW = &finalPoints[((row + 1) * points) + (col + 0)];
688 glm::vec3* NE = &finalPoints[((row + 1) * points) + (col + 1)];
689
690 if (i_condition++ % 2 == 0) {//Condition 0
691 meshPoints.push_back(-SW->x);
692 meshPoints.push_back(SW->z);
693 meshPoints.push_back(SW->y);
694 meshPoints.push_back(0);
695 meshPoints.push_back(0);
696 meshPoints.push_back(1);
697 meshPoints.push_back(-NW->x);
698 meshPoints.push_back(NW->z);
699 meshPoints.push_back(NW->y);
700 meshPoints.push_back(0);
701 meshPoints.push_back(0);
702 meshPoints.push_back(1);
703 meshPoints.push_back(-NE->x);
704 meshPoints.push_back(NE->z);
705 meshPoints.push_back(NE->y);
706 meshPoints.push_back(0);
707 meshPoints.push_back(0);
708 meshPoints.push_back(1);
709
710 meshPoints.push_back(-SW->x);
711 meshPoints.push_back(SW->z);
712 meshPoints.push_back(SW->y);
713 meshPoints.push_back(0);
714 meshPoints.push_back(0);
715 meshPoints.push_back(1);
716 meshPoints.push_back(-NE->x);
717 meshPoints.push_back(NE->z);
718 meshPoints.push_back(NE->y);
719 meshPoints.push_back(0);
720 meshPoints.push_back(0);
721 meshPoints.push_back(1);
722 meshPoints.push_back(-SE->x);
723 meshPoints.push_back(SE->z);
724 meshPoints.push_back(SE->y);
725 meshPoints.push_back(0);
726 meshPoints.push_back(0);
727 meshPoints.push_back(1);
728 }
729 else { //Condition 1
730 meshPoints.push_back(-SW->x);
731 meshPoints.push_back(SW->z);
732 meshPoints.push_back(SW->y);
733 meshPoints.push_back(0);
734 meshPoints.push_back(0);
735 meshPoints.push_back(1);
736 meshPoints.push_back(-NW->x);
737 meshPoints.push_back(NW->z);
738 meshPoints.push_back(NW->y);
739 meshPoints.push_back(0);
740 meshPoints.push_back(0);
741 meshPoints.push_back(1);
742 meshPoints.push_back(-SE->x);
743 meshPoints.push_back(SE->z);
744 meshPoints.push_back(SE->y);
745 meshPoints.push_back(0);
746 meshPoints.push_back(0);
747 meshPoints.push_back(1);
748
749 meshPoints.push_back(-NW->x);
750 meshPoints.push_back(NW->z);
751 meshPoints.push_back(NW->y);
752 meshPoints.push_back(0);
753 meshPoints.push_back(0);
754 meshPoints.push_back(1);
755 meshPoints.push_back(-NE->x);
756 meshPoints.push_back(NE->z);
757 meshPoints.push_back(NE->y);
758 meshPoints.push_back(0);
759 meshPoints.push_back(0);
760 meshPoints.push_back(1);
761 meshPoints.push_back(-SE->x);
762 meshPoints.push_back(SE->z);
763 meshPoints.push_back(SE->y);
764 meshPoints.push_back(0);
765 meshPoints.push_back(0);
766 meshPoints.push_back(1);
767 }
768 }
769 i_condition++;
770 }
771
772 Mesh* _glMesh = new Mesh(meshPoints);
773 info->glMesh = _glMesh;
774 }
775 }
776 }
777 }
778
779 auto elapsed = std::chrono::high_resolution_clock::now() - start;
780 long long milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count();
781
782 std::cout << "Displacement computation: " << milliseconds << "ms" << std::endl;
783 }
784
785 void clean() {
786 for (int i = 0; i < this->solids.size(); i++) {
787 delete this->solids[i].mesh;
788 this->solids[i].mesh = NULL;
789 }
790
791 for (auto i : this->entities) {
792 for (auto m : i.internal_solids) {
793 delete m.mesh;
794 m.mesh = NULL;
795 }
796 }
797 }
798
799 ~vmf() {
800
801 }
802 };
803
804 BoundingBox getSolidListBounds(std::vector<Solid*> list) {
805 if (list.size() <= 0) return BoundingBox();
806
807 BoundingBox bounds;
808 bounds.NWU = list[0]->bounds.NWU;
809 bounds.SEL = list[0]->bounds.SEL;
810
811 for (auto && iSolid : list) {
812 if (iSolid->bounds.NWU.z > bounds.NWU.z) bounds.NWU.z = iSolid->bounds.NWU.z;
813 if (iSolid->bounds.NWU.y > bounds.NWU.y) bounds.NWU.y = iSolid->bounds.NWU.y;
814 if (iSolid->bounds.NWU.x > bounds.NWU.x) bounds.NWU.x = iSolid->bounds.NWU.x;
815
816 if (iSolid->bounds.SEL.z < bounds.SEL.z) bounds.SEL.z = iSolid->bounds.SEL.z;
817 if (iSolid->bounds.SEL.y < bounds.SEL.y) bounds.SEL.y = iSolid->bounds.SEL.y;
818 if (iSolid->bounds.SEL.x < bounds.SEL.x) bounds.SEL.x = iSolid->bounds.SEL.x;
819 }
820
821 return bounds;
822 }
823 }