19267ea6b6cf67314fe65cdeffae0b1a4c994f15
[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
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 = cBlock.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
407 std::cout << "Processing visgroups\n";
408
409 //Process Visgroups
410 std::vector<kv::DataBlock> VisList = data.headNode.GetFirstByName("visgroups")->GetAllByName("visgroup");
411 for (auto v : VisList) {
412 this->visgroups.insert({ std::stoi(v.Values["visgroupid"]), v.Values["name"] });
413
414 std::cout << "Visgroup {" << std::stoi(v.Values["visgroupid"]) << "} = '" << v.Values["name"] << "'\n";
415 }
416 }
417
418 std::vector<Solid*> getSolidsInVisGroup(std::string visgroup) {
419 std::vector<Solid*> list;
420 for (auto && v : this->solids) {
421 for (auto && vid : v.visgroupids) {
422 if (this->visgroups[vid] == visgroup) {
423 list.push_back(&v);
424 }
425 }
426 }
427
428 return list;
429 }
430
431 std::vector<Solid*> getAllBrushesInVisGroup(std::string visgroup) {
432 std::vector<Solid*> list;
433
434 // All solids
435 for (auto && v : this->solids) {
436 for (auto && vid : v.visgroupids) {
437 if (this->visgroups[vid] == visgroup) {
438 list.push_back(&v);
439 }
440 }
441 }
442
443 // All entity brush solids
444 for (auto && e : this->entities) {
445 for (auto && es : e.internal_solids) {
446 for (auto && esvid : es.visgroupids) {
447 if (this->visgroups[esvid] == visgroup) {
448 list.push_back(&es);
449 }
450 }
451 }
452 }
453
454 return list;
455 }
456
457 std::vector<Solid*> getAllBrushesByClassName(std::string classname) {
458 std::vector<Solid*> list;
459 for (auto && ent : this->entities) {
460 if (ent.classname == classname) {
461 for (auto && s : ent.internal_solids) {
462 list.push_back(&s);
463 }
464 }
465 }
466 return list;
467 }
468
469 /* Gets a list of entities with matching classname */
470 std::vector<Entity*> findEntitiesByClassName(std::string classname) {
471 std::vector<Entity*> list;
472 for (auto && ent : this->entities) {
473 if (ent.classname == classname) {
474 list.push_back(&ent);
475 }
476 }
477 return list;
478 }
479
480 glm::vec3* calculateSpawnLocation(team _team) {
481
482 std::vector<Entity*> spawns = this->findEntitiesByClassName(_team == team::terrorist ? "info_player_terrorist" : "info_player_counterterrorist");
483
484 if (spawns.size() <= 0) return NULL;
485
486 //Find lowest priority (highest)
487 int lowest = kv::tryGetValue<int>(spawns[0]->keyValues, "priority", 0);
488 for (auto && s : spawns) {
489 int l = kv::tryGetValue<int>(s->keyValues, "priority", 0);
490 lowest = l < lowest ? l : lowest;
491 }
492
493 //Collect all spawns with that priority
494 glm::vec3* location = new glm::vec3();
495 int c = 0;
496 for (auto && s : spawns) {
497 if (kv::tryGetValue<int>(s->keyValues, "priority", 0) == lowest) {
498 *location += s->origin; c++;
499 }
500 }
501
502 //avg
503 *location = *location / (float)c;
504 return location;
505 }
506
507 void ComputeGLMeshes() {
508 auto start = std::chrono::high_resolution_clock::now();
509
510 std::cout << "Processing solid meshes... ";
511 for (int i = 0; i < this->solids.size(); i++) {
512 std::vector<Plane> sidePlanes;
513 for (int j = 0; j < this->solids[i].faces.size(); j++)
514 sidePlanes.push_back(this->solids[i].faces[j].plane);
515
516 Polytope p = Polytope(sidePlanes);
517 this->solids[i].mesh = p.GeneratedMesh;
518 this->solids[i].origin = (p.NWU + p.SEL) * 0.5f;
519 this->solids[i].bounds.NWU = p.NWU;
520 this->solids[i].bounds.SEL = p.SEL;
521 }
522 std::cout << "done\n";
523
524 std::cout << "Processing entity solid meshes... ";
525 for (auto && ent : this->entities) {
526 for (auto && _solid : ent.internal_solids) {
527 std::vector<Plane> sidePlanes;
528 for (auto f : _solid.faces)
529 sidePlanes.push_back(f.plane);
530
531 Polytope p = Polytope(sidePlanes);
532 _solid.mesh = p.GeneratedMesh;
533 _solid.origin = (p.NWU + p.SEL) * 0.5f;
534 _solid.bounds.NWU = p.NWU;
535 _solid.bounds.SEL = p.SEL;
536 }
537 }
538 std::cout << "done\n";
539
540 auto elapsed = std::chrono::high_resolution_clock::now() - start;
541 long long milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count();
542
543 std::cout << "GL mesh computation: " << milliseconds << "ms" << std::endl;
544 }
545
546 void ComputeDisplacements() {
547 auto start = std::chrono::high_resolution_clock::now();
548
549 std::cout << "Computing displacements...\n";
550
551 for (auto && v :this->solids) {
552 if (v.containsDisplacements) {
553
554 std::vector<Plane> planes;
555 for (auto && face : v.faces) planes.push_back(face.plane);
556
557 Polytope polyTope = Polytope(planes, true, false); // Generate polytope so we can look at the individual ngon points
558
559 for (auto && side :v.faces) {
560 if (side.displacement != NULL) {
561 DispInfo* info = side.displacement;
562
563 BrushPolygon* bpoly = NULL;
564
565 std::map<float, BrushPolygon*> normalCorrelations;
566
567 //Sort planes by their similarity to the face's normal direction
568 for (auto && fuck : polyTope.ngons)
569 normalCorrelations.insert({ glm::distance(fuck.plane.normal, side.plane.normal), &fuck });
570
571 bpoly = normalCorrelations.begin()->second;
572
573 if (bpoly->vertices.size() != 4) {
574 std::cout << "Displacement info matched to face with {" << bpoly->vertices.size() << "} vertices!!!\n"; continue;
575 }
576
577 // Match the 'starting point' of dispinfo
578 std::map<float, glm::vec3*> distancesToStart;
579 for (auto && point : bpoly->vertices)
580 distancesToStart.insert({ glm::distance(info->startposition, point), &point });
581
582 // The corners of the displacement
583 glm::vec3* SW = distancesToStart.begin()->second;
584
585 // Find what point in the vector it was
586 int pos = 0;
587 for (auto && point : bpoly->vertices)
588 if (&point == SW) break; else pos++;
589
590 // Get the rest of the points, in clockwise order (they should already be sorted by polytope generation)
591 glm::vec3* NW = &bpoly->vertices[(pos + 1) % 4];
592 glm::vec3* NE = &bpoly->vertices[(pos + 2) % 4];
593 glm::vec3* SE = &bpoly->vertices[(pos + 3) % 4];
594
595 int points = glm::pow(2, info->power) + 1; // calculate the point count (5, 9, 17)
596
597 // Initialize list for floats
598 std::vector<float> meshPoints;
599
600 std::vector<glm::vec3> finalPoints;
601
602 glm::vec3* NWU = &v.bounds.NWU;
603 glm::vec3* SEL = &v.bounds.SEL;
604
605 for (int row = 0; row < points; row++) {
606 for (int col = 0; col < points; col++) {
607 //Generate original base points
608
609 float dx = (float)col / (float)(points-1); //Time values for linear interpolation
610 float dy = (float)row / (float)(points-1);
611
612 glm::vec3 LWR = lerp(*SW, *SE, dx);
613 glm::vec3 UPR = lerp(*NW, *NE, dx);
614 glm::vec3 P = lerp(LWR, UPR, dy); // Original point location
615
616 glm::vec3 offset = info->normals[col][row] * info->distances[col][row]; // Calculate offset
617 P = P + offset; //Add offset to P
618
619 finalPoints.push_back(P);
620
621 //Recompute bounds while we are at it
622 NWU->x = glm::max(-P.x, NWU->x);
623 NWU->y = glm::max(P.z, NWU->y);
624 NWU->z = glm::max(P.y, NWU->z);
625
626 SEL->x = glm::min(-P.x, SEL->x);
627 SEL->y = glm::min(P.z, SEL->y);
628 SEL->z = glm::min(P.y, SEL->z);
629
630 continue;
631
632 /* TESTING TRIANGLES */
633 meshPoints.push_back(-P.x);
634 meshPoints.push_back(P.z);
635 meshPoints.push_back(P.y);
636 meshPoints.push_back(0);
637 meshPoints.push_back(0);
638 meshPoints.push_back(1);
639
640 meshPoints.push_back(-P.x);
641 meshPoints.push_back(P.z);
642 meshPoints.push_back(P.y + 8.0f);
643 meshPoints.push_back(0);
644 meshPoints.push_back(0);
645 meshPoints.push_back(1);
646
647
648 meshPoints.push_back(-P.x + 8.0f);
649 meshPoints.push_back(P.z);
650 meshPoints.push_back(P.y + 8.0f);
651 meshPoints.push_back(0);
652 meshPoints.push_back(0);
653 meshPoints.push_back(1);
654 }
655 }
656
657 int i_condition = 0;
658 for (int row = 0; row < points - 1; row++) {
659 for (int col = 0; col < points - 1; col++) {
660
661 // Gather point pointers
662 // hehe :(
663 glm::vec3* SW = &finalPoints[((row + 0) * points) + (col + 0)];
664 glm::vec3* SE = &finalPoints[((row + 0) * points) + (col + 1)];
665
666 glm::vec3* NW = &finalPoints[((row + 1) * points) + (col + 0)];
667 glm::vec3* NE = &finalPoints[((row + 1) * points) + (col + 1)];
668
669 if (i_condition++ % 2 == 0) {//Condition 0
670 meshPoints.push_back(-SW->x);
671 meshPoints.push_back(SW->z);
672 meshPoints.push_back(SW->y);
673 meshPoints.push_back(0);
674 meshPoints.push_back(0);
675 meshPoints.push_back(1);
676 meshPoints.push_back(-NW->x);
677 meshPoints.push_back(NW->z);
678 meshPoints.push_back(NW->y);
679 meshPoints.push_back(0);
680 meshPoints.push_back(0);
681 meshPoints.push_back(1);
682 meshPoints.push_back(-NE->x);
683 meshPoints.push_back(NE->z);
684 meshPoints.push_back(NE->y);
685 meshPoints.push_back(0);
686 meshPoints.push_back(0);
687 meshPoints.push_back(1);
688
689 meshPoints.push_back(-SW->x);
690 meshPoints.push_back(SW->z);
691 meshPoints.push_back(SW->y);
692 meshPoints.push_back(0);
693 meshPoints.push_back(0);
694 meshPoints.push_back(1);
695 meshPoints.push_back(-NE->x);
696 meshPoints.push_back(NE->z);
697 meshPoints.push_back(NE->y);
698 meshPoints.push_back(0);
699 meshPoints.push_back(0);
700 meshPoints.push_back(1);
701 meshPoints.push_back(-SE->x);
702 meshPoints.push_back(SE->z);
703 meshPoints.push_back(SE->y);
704 meshPoints.push_back(0);
705 meshPoints.push_back(0);
706 meshPoints.push_back(1);
707 }
708 else { //Condition 1
709 meshPoints.push_back(-SW->x);
710 meshPoints.push_back(SW->z);
711 meshPoints.push_back(SW->y);
712 meshPoints.push_back(0);
713 meshPoints.push_back(0);
714 meshPoints.push_back(1);
715 meshPoints.push_back(-NW->x);
716 meshPoints.push_back(NW->z);
717 meshPoints.push_back(NW->y);
718 meshPoints.push_back(0);
719 meshPoints.push_back(0);
720 meshPoints.push_back(1);
721 meshPoints.push_back(-SE->x);
722 meshPoints.push_back(SE->z);
723 meshPoints.push_back(SE->y);
724 meshPoints.push_back(0);
725 meshPoints.push_back(0);
726 meshPoints.push_back(1);
727
728 meshPoints.push_back(-NW->x);
729 meshPoints.push_back(NW->z);
730 meshPoints.push_back(NW->y);
731 meshPoints.push_back(0);
732 meshPoints.push_back(0);
733 meshPoints.push_back(1);
734 meshPoints.push_back(-NE->x);
735 meshPoints.push_back(NE->z);
736 meshPoints.push_back(NE->y);
737 meshPoints.push_back(0);
738 meshPoints.push_back(0);
739 meshPoints.push_back(1);
740 meshPoints.push_back(-SE->x);
741 meshPoints.push_back(SE->z);
742 meshPoints.push_back(SE->y);
743 meshPoints.push_back(0);
744 meshPoints.push_back(0);
745 meshPoints.push_back(1);
746 }
747 }
748 i_condition++;
749 }
750
751 Mesh* _glMesh = new Mesh(meshPoints);
752 info->glMesh = _glMesh;
753 }
754 }
755 }
756 }
757
758 auto elapsed = std::chrono::high_resolution_clock::now() - start;
759 long long milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count();
760
761 std::cout << "Displacement computation: " << milliseconds << "ms" << std::endl;
762 }
763
764 void clean() {
765 for (int i = 0; i < this->solids.size(); i++) {
766 delete this->solids[i].mesh;
767 this->solids[i].mesh = NULL;
768 }
769
770 for (auto i : this->entities) {
771 for (auto m : i.internal_solids) {
772 delete m.mesh;
773 m.mesh = NULL;
774 }
775 }
776 }
777
778 ~vmf() {
779
780 }
781 };
782
783 BoundingBox getSolidListBounds(std::vector<Solid*> list) {
784 if (list.size() <= 0) return BoundingBox();
785
786 BoundingBox bounds;
787 bounds.NWU = list[0]->bounds.NWU;
788 bounds.SEL = list[0]->bounds.SEL;
789
790 for (auto && iSolid : list) {
791 if (iSolid->bounds.NWU.z > bounds.NWU.z) bounds.NWU.z = iSolid->bounds.NWU.z;
792 if (iSolid->bounds.NWU.y > bounds.NWU.y) bounds.NWU.y = iSolid->bounds.NWU.y;
793 if (iSolid->bounds.NWU.x > bounds.NWU.x) bounds.NWU.x = iSolid->bounds.NWU.x;
794
795 if (iSolid->bounds.SEL.z < bounds.SEL.z) bounds.SEL.z = iSolid->bounds.SEL.z;
796 if (iSolid->bounds.SEL.y < bounds.SEL.y) bounds.SEL.y = iSolid->bounds.SEL.y;
797 if (iSolid->bounds.SEL.x < bounds.SEL.x) bounds.SEL.x = iSolid->bounds.SEL.x;
798 }
799
800 return bounds;
801 }
802 }