Skyscraper 2.0
mesh.cpp
Go to the documentation of this file.
1/*
2 Scalable Building Simulator - Mesh Object
3 The Skyscraper Project - Version 2.0
4 Copyright (C)2004-2024 Ryan Thoryk
5 https://www.skyscrapersim.net
6 https://sourceforge.net/projects/skyscraper/
7 Contact - ryan@skyscrapersim.net
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22*/
23
24#include <OgreMesh.h>
25#include <OgreResourceGroupManager.h>
26#include <OgreMaterialManager.h>
27#include <OgreBulletDynamicsRigidBody.h>
28#include <OgreMath.h>
29#include <OgreAxisAlignedBox.h>
30#include <Shapes/OgreBulletCollisionsTrimeshShape.h>
31#include <Shapes/OgreBulletCollisionsBoxShape.h>
32#include "globals.h"
33#include "sbs.h"
34#include "camera.h"
35#include "wall.h"
36#include "texture.h"
37#include "profiler.h"
38#include "scenenode.h"
39#include "dynamicmesh.h"
40#include "polymesh.h"
41#include "polygon.h"
42#include "utility.h"
43#include "mesh.h"
44
45namespace SBS {
46
47MeshObject::MeshObject(Object* parent, const std::string &name, DynamicMesh* wrapper, const std::string &filename, const std::string &meshname, Real max_render_distance, Real scale_multiplier, bool create_collider, bool dynamic_buffers) : Object(parent)
48{
49 //set up SBS object
50 SetValues("Mesh", name, true);
51
52 //create an instance of the geometry processor
53 polymesh = new PolyMesh(this);
54
55 //initialize mesh object
56 enabled = true;
57 mBody = 0;
58 mShape = 0;
59 prepared = false;
60 is_physical = false;
61 restitution = 0;
62 friction = 0;
63 mass = 0;
64 this->create_collider = create_collider;
65 collider_node = 0;
66 Filename = filename;
67 Meshname = meshname;
68 remove_on_disable = true;
69 wrapper_selfcreate = false;
70 model_loaded = false;
71 Bounds = new Ogre::AxisAlignedBox();
72 collidermesh = 0;
73 size = 0;
74 tricollider = true;
75
76 std::string Name = GetSceneNode()->GetFullName();
77 this->name = Name;
78
79 if (wrapper == 0)
80 {
81 wrapper_selfcreate = true;
82 MeshWrapper = new DynamicMesh(this, GetSceneNode(), name, max_render_distance, dynamic_buffers);
83 }
84 else
85 MeshWrapper = wrapper;
86
87 //add this mesh object as a client to the dynamic mesh wrapper
89
90 if (filename != "")
91 {
92 //load mesh from a file if specified
93 bool result = LoadFromFile(filename);
94
95 if (result == false)
96 return;
97 }
98 else if (meshname != "")
99 {
100 //load mesh from a preexisting name if specified
101 bool result = LoadFromMesh(meshname);
102
103 if (result == false)
104 return;
105 }
106
107 //rescale mesh
108 //file-loaded meshes need to be converted to a remote scale, since they're not pre-scaled
109 if (filename == "")
110 GetSceneNode()->SetScale(scale_multiplier);
111 else
112 GetSceneNode()->SetScale(sbs->ToRemote(scale_multiplier));
113
114 sbs->AddMeshHandle(this);
115}
116
118{
119 //delete physics/collider components
121
122 //delete wall objects
123 DeleteWalls();
124
125 if (collider_node)
126 delete collider_node;
127 collider_node = 0;
128
130
131 if (sbs->FastDelete == false)
132 {
134 sbs->DeleteMeshHandle(this);
135 }
136
137 //delete dynamic mesh wrapper if needed
138 if (wrapper_selfcreate == true)
139 delete MeshWrapper;
140 MeshWrapper = 0;
141
142 if (Bounds)
143 delete Bounds;
144 Bounds = 0;
145
146 delete polymesh;
147}
148
150{
151 *Bounds = MeshWrapper->GetBounds(this);
152}
153
154void MeshObject::Enabled(bool value)
155{
156 //enables or disables the mesh
157
158 if (value == enabled)
159 {
160 if (remove_on_disable == false && sbs->camera->IsActive() == false && value == false)
161 {
162 //if camera is detached from this engine, and mesh is disabled, detach a persistent collider
163 remove_on_disable = true;
164 EnableCollider(false);
165 remove_on_disable = false;
166 }
167 return;
168 }
169
170 SBS_PROFILE("MeshObject::Enable");
171
172 MeshWrapper->Enabled(value, this);
173
174 EnableCollider(value);
175
176 enabled = value;
177}
178
180{
181 //enable or disable collision detection
182
183 if (!mBody)
184 return;
185
186 SBS_PROFILE("MeshObject::EnableCollider");
187
188 if (remove_on_disable == false && sbs->camera->IsActive() == true)
189 {
190 //if removed from world and 'remove_on_disable' is false, add to world
191 if (mBody->isInWorld() == false)
192 mBody->addToWorld();
193
194 //disable collisions on object only (don't remove)
195 mBody->enableCollisions(value);
196 }
197 else
198 {
199 //completely remove object from dynamics world if disabled; re-add to enable
200 if (value == false)
201 mBody->removeFromWorld();
202 else
203 mBody->addToWorld();
204 }
206}
207
208Wall* MeshObject::CreateWallObject(const std::string &name)
209{
210 //create a new wall object in the given array
211
212 Wall *wall = new Wall(this);
213 wall->SetParentArray(Walls);
214 wall->SetValues("Wall", name, false, true);
215 Walls.emplace_back(wall);
216 return wall;
217}
218
220{
221 //find a wall object by name
222
223 SetCase(name, false);
224
225 for (size_t i = 0; i < Walls.size(); i++)
226 {
227 if (!Walls[i])
228 continue;
229
230 if (name == SetCaseCopy(Walls[i]->GetName(), false) == true)
231 return Walls[i];
232 }
233 return 0;
234}
235
237{
238 return enabled;
239}
240
241void MeshObject::Prepare(bool force)
242{
243 //prepare mesh object
244
245 SBS_PROFILE("MeshObject::Prepare");
246
247 if (prepared == true && force == false)
248 return;
249
250 //set up bounding box
251 if (model_loaded == false)
252 {
253 Bounds->setNull();
254 for (size_t i = 0; i < Walls.size(); i++)
255 {
256 if (!Walls[i])
257 continue;
258
259 for (size_t j = 0; j < Walls[i]->polygons.size(); j++)
260 {
261 Polygon *poly = Walls[i]->polygons[j];
262
263 if (!poly)
264 continue;
265 for (size_t k = 0; k < poly->geometry.size(); k++)
266 {
267 for (size_t l = 0; l < poly->geometry[k].size(); l++)
268 Bounds->merge(poly->geometry[k][l].vertex);
269 }
270 }
271 }
272 }
273
274 //update dynamic mesh
276
277 prepared = true;
278}
279
281{
282 //enable or disable debug view of mesh
283 MeshWrapper->EnableDebugView(value, this);
284}
285
286void MeshObject::CreateColliderFromModel(int &vertex_count, Vector3* &vertices, int &index_count, unsigned long* &indices)
287{
288 //set up triangle collider based on loaded model geometry
289
290 if (create_collider == false)
291 return;
292
293 //exit of collider already exists
294 if (mBody)
295 return;
296
297 if (!GetSceneNode())
298 return;
299
300 try
301 {
302 //initialize collider shape
303 OgreBulletCollisions::TriangleMeshCollisionShape* shape = new OgreBulletCollisions::TriangleMeshCollisionShape(vertex_count, index_count);
304
305 //add vertices to shape
306 for (int i = 0; i < index_count; i += 3)
307 {
308 shape->AddTriangle(vertices[indices[i]], vertices[indices[i + 1]], vertices[indices[i + 2]]);
309 }
310
311 //finalize shape
312 shape->Finish();
313
314 //create a collider scene node
315 if (!collider_node)
316 collider_node = GetSceneNode()->CreateChild(GetName() + " collider");
317
318 //physics is not supported on triangle meshes; use CreateBoxCollider instead
319 mBody = new OgreBulletDynamics::RigidBody(name, sbs->mWorld);
320 mBody->setStaticShape(collider_node->GetRawSceneNode(), shape, 0.1f, 0.5f, false);
321 mShape = shape;
322 }
323 catch (Ogre::Exception &e)
324 {
325 ReportError("Error creating model collider for '" + name + "'\n" + e.getDescription());
326 }
327}
328
330{
331 //set up a box collider for full extents of a mesh
332
333 if (create_collider == false)
334 return;
335
336 //exit of collider already exists
337 if (mBody)
338 return;
339
340 if (!GetSceneNode())
341 return;
342
343 try
344 {
345 //initialize collider shape
346 Real scale = GetSceneNode()->GetScale();
347
348 if (Bounds->isNull() == true)
349 return;
350
351 Vector3 bounds = Bounds->getHalfSize() * scale;
352 OgreBulletCollisions::BoxCollisionShape* shape = new OgreBulletCollisions::BoxCollisionShape(bounds);
353
354 //create a new scene node for this collider, and center the collider accordingly
355 Vector3 collider_center = sbs->ToLocal(Bounds->getCenter());
356 if (!collider_node)
357 collider_node = GetSceneNode()->CreateChild(GetName() + " collider", collider_center);
358
359 mBody = new OgreBulletDynamics::RigidBody(name, sbs->mWorld);
360 if (IsPhysical() == false)
361 mBody->setStaticShape(collider_node->GetRawSceneNode(), shape, 0.1f, 0.5f, false);
362 else
364 mShape = shape;
365 }
366 catch (Ogre::Exception &e)
367 {
368 ReportError("Error creating box collider for '" + name + "'\n" + e.getDescription());
369 }
370}
371
373{
374 //delete all wall objects
375
376 for (size_t i = 0; i < Walls.size(); i++)
377 {
378 Wall *wall = Walls[i];
379 if (wall)
380 {
381 wall->parent_deleting = true;
382 if (sbs->FastDelete == false)
383 wall->DeletePolygons();
384 delete wall;
385 Walls[i] = 0;
386 }
387 }
388 Walls.clear();
389}
390
392{
393 //delete walls of specified parent object
394
395 for (size_t i = 0; i < Walls.size(); i++)
396 {
397 Wall *wall = Walls[i];
398 if (wall)
399 {
400 if (wall->GetParent() == parent)
401 {
402 wall->parent_deleting = true;
403 wall->DeletePolygons();
404 delete wall;
405 Walls.erase(Walls.begin() + i);
406 i--;
407 }
408 }
409 }
410}
411
412Vector3 MeshObject::GetPoint(const std::string &wallname, const Vector3 &start, const Vector3 &end)
413{
414 //do a line intersection with a specified wall associated with this mesh object,
415 //and return the intersection point
416
417 Wall *wall = GetWallByName(wallname);
418
419 if (wall)
420 return wall->GetPoint(start, end);
421
422 return Vector3(0, 0, 0);
423}
424
425Vector3 MeshObject::GetWallExtents(const std::string &name, Real altitude, bool get_max)
426{
427 //return the X and Z extents of a standard wall (by name) at a specific altitude, by doing a double plane cut
428
429 Wall *wall = GetWallByName(name);
430
431 if (wall)
432 return wall->GetWallExtents(altitude, get_max);
433
434 return Vector3(0, 0, 0);
435}
436
437void MeshObject::OnMove(bool parent)
438{
439 if (collider_node)
441
442 if (mBody)
443 mBody->updateTransform(true, false, false);
444
445 if (UsingDynamicBuffers() == true)
447}
448
449void MeshObject::OnRotate(bool parent)
450{
451 if (collider_node)
453
454 if (mBody)
455 {
456 if (parent == true)
457 OnMove(parent); //update position if parent object has been rotated
458
459 mBody->updateTransform(false, true, false);
460 }
461
462 if (UsingDynamicBuffers() == true)
464}
465
466bool MeshObject::IsVisible(Ogre::Camera *camera)
467{
468 //returns if this mesh object is visible in the provided camera's view frustum or not
469
470 if (IsEnabled() == false || !camera)
471 return false;
472
473 //if beyond the max render distance
474 if (MeshWrapper->IsVisible(this) == false)
475 return false;
476
477 //if (polymesh->GetSubmeshCount() == 0)
478 //return false;
479
480 if (Bounds->isNull() == true)
481 return false;
482
483 Vector3 min = Bounds->getMinimum();
484 Vector3 max = Bounds->getMaximum();
486 Ogre::AxisAlignedBox global_box (pos + min, pos + max);
487
488 return camera->isVisible(global_box);
489}
490
492{
493 return is_physical;
494}
495
497{
498 //for models, return bounding box offset value, used to center the mesh
499
500 Bounds->scale(GetSceneNode()->GetRawSceneNode()->getScale());
501
502 if (Bounds->isNull() == true)
503 return Vector3::ZERO;
504
505 Vector3 vec = Bounds->getCenter();
506 Vector3 min = Bounds->getMinimum();
507 Vector3 offset (vec.x, -Bounds->getMinimum().y, -vec.z);
508 return sbs->ToLocal(offset);
509}
510
511void MeshObject::Cut(Vector3 start, Vector3 end, bool cutwalls, bool cutfloors, int checkwallnumber, bool reset_check)
512{
513 //cut all walls in this mesh object
514
515 for (size_t i = 0; i < Walls.size(); i++)
516 {
517 if (!Walls[i])
518 continue;
519
520 sbs->GetUtility()->Cut(Walls[i], start, end, cutwalls, cutfloors, checkwallnumber, reset_check);
521 }
522}
523
524void MeshObject::CutOutsideBounds(Vector3 start, Vector3 end, bool cutwalls, bool cutfloors)
525{
526 Real limit = 1000000;
527
528 Vector3 left_min (-limit, -limit, -limit);
529 Vector3 left_max (start.x, limit, limit);
530 Vector3 right_min (end.x, -limit, -limit);
531 Vector3 right_max (limit, limit, limit);
532 Vector3 front_min (-limit, -limit, -limit);
533 Vector3 front_max (limit, limit, start.z);
534 Vector3 back_min (-limit, -limit, end.z);
535 Vector3 back_max (limit, limit, limit);
536
537 Cut(left_min, left_max, cutwalls, cutfloors);
538 Cut(right_min, right_max, cutwalls, cutfloors);
539 Cut(front_min, front_max, cutwalls, cutfloors);
540 Cut(back_min, back_max, cutwalls, cutfloors);
541}
542
543bool MeshObject::LoadFromFile(const std::string &filename)
544{
545 //load mesh object from a file
546
547 std::string filename1 = "data/";
548 filename1.append(filename);
549 std::string filename2 = sbs->VerifyFile(filename1);
550 std::string path = sbs->GetMountPath(filename2, filename2);
551 std::string matname;
552
553 //load material file
554 try
555 {
556 matname = filename2.substr(0, filename2.length() - 5) + ".material";
557 std::string matname2 = sbs->VerifyFile(matname);
558 Ogre::DataStreamPtr stream = Ogre::ResourceGroupManager::getSingleton().openResource(matname2, path);
559 Report("Loading material script " + matname2);
560 Ogre::MaterialManager::getSingleton().parseScript(stream, path);
561
562 if(stream)
563 {
564 stream->seek(0);
565 while(!stream->eof())
566 {
567 std::string line = stream->getLine();
568 TrimString(line);
569 if (StartsWith(line, "material", true) == true)
570 {
571 std::vector<std::string> vec = Ogre::StringUtil::split(line," \t:");
572 for (std::vector<std::string>::iterator it = vec.begin(); it < vec.end(); ++it)
573 {
574 std::string match = (*it);
575 TrimString(match);
576 if (!match.empty())
577 {
578 Ogre::MaterialPtr materialPtr = Ogre::MaterialManager::getSingleton().getByName(match, path);
579 if (materialPtr)
580 {
581 Report("Loading material " + match);
582 //materialPtr->compile();
583 materialPtr->load();
584
585 //set lighting
586 materialPtr->setLightingEnabled(false);
587 if (sbs->GetConfigBool("Skyscraper.SBS.Lighting", false) == true)
588 {
589 materialPtr->setLightingEnabled(true);
590 materialPtr->setAmbient(sbs->AmbientR, sbs->AmbientG, sbs->AmbientB);
591 }
592 }
593 }
594 }
595 }
596 }
597 stream->close();
598 }
599 }
600 catch (Ogre::Exception &e)
601 {
602 ReportError("Error loading material file " + matname + "\n" + e.getDescription());
603 }
604
605 //load model
606 bool status = MeshWrapper->LoadFromFile(filename2, path);
607 if (status == false)
608 return false;
609
610 model_loaded = true;
611 return true;
612}
613
614bool MeshObject::LoadColliderModel(Ogre::MeshPtr &collidermesh)
615{
616 if (Filename == "")
617 return false;
618
619 std::string filename1 = "data/";
620 filename1.append(Filename);
621 std::string filename2 = sbs->VerifyFile(filename1);
622 std::string path = sbs->GetMountPath(filename2, filename2);
623
624 //load collider model if physics is disabled
625 if (is_physical == false)
626 {
627 std::string colname2;
628
629 try
630 {
631 std::string colname = filename2.substr(0, filename2.length() - 5) + ".collider.mesh";
632 colname2 = sbs->VerifyFile(colname);
633 collidermesh = Ogre::MeshManager::getSingleton().load(colname2, path);
634 }
635 catch (Ogre::Exception &e)
636 {
637 return ReportError("No collider model for " + colname2 + "\n" + e.getDescription());
638 }
639 }
640 return true;
641}
642
643bool MeshObject::LoadFromMesh(const std::string &meshname)
644{
645 //load mesh
646 return MeshWrapper->LoadFromMesh(meshname);
647}
648
653
655{
656 //change height of all walls associated with this mesh object
657
658 SBS_PROFILE("MeshObject::ChangeHeight");
659
660 for (size_t i = 0; i < Walls.size(); i++)
661 {
662 if (!Walls[i])
663 continue;
664
665 Walls[i]->ChangeHeight(newheight);
666 }
667}
668
670{
671 //enable shadows
672
674}
675
680
682{
683 return prepared;
684}
685
687{
688 prepared = false;
689}
690
691bool MeshObject::ReplaceTexture(const std::string &oldtexture, const std::string &newtexture)
692{
693 //replace polygon materials named oldtexture with newtexture
694
695 //update associated polygons
696 bool found = false;
697 for (size_t i = 0; i < Walls.size(); i++)
698 {
699 if (!Walls[i])
700 continue;
701
702 bool result = Walls[i]->ReplaceTexture(oldtexture, newtexture);
703 if (result == true)
704 found = true;
705 }
706 return found;
707}
708
709bool MeshObject::ChangeTexture(const std::string &texture, bool matcheck)
710{
711 //changes a texture
712 //if matcheck is true, exit if old and new textures are the same
713
714 //update associated polygons
715 bool found = false;
716 for (size_t i = 0; i < Walls.size(); i++)
717 {
718 if (!Walls[i])
719 continue;
720
721 bool result = Walls[i]->ChangeTexture(texture, matcheck);
722 if (result == true)
723 found = true;
724 }
725 return found;
726}
727
729{
730 //returns the height of the mesh
731
732 Real y = 0.0;
733 for (size_t i = 0; i < Walls.size(); i++)
734 {
735 if (!Walls[i])
736 continue;
737
738 for (size_t j = 0; j < Walls[i]->GetPolygonCount(); j++)
739 {
740 Polygon *poly = Walls[i]->GetPolygon(j);
741
742 if (!poly)
743 continue;
744
745 for (size_t k = 0; k < poly->geometry.size(); k++)
746 {
747 for (size_t l = 0; l < poly->geometry[k].size(); l++)
748 {
749 Real new_y = poly->geometry[k][l].vertex.y;
750 if (new_y > y)
751 y = new_y;
752 }
753 }
754 }
755 }
756
757 return sbs->ToLocal(y);
758}
759
760Real MeshObject::HitBeam(const Vector3 &origin, const Vector3 &direction, Real max_distance)
761{
762 //cast a ray and return the collision distance to the mesh
763 //return -1 if no hit
764
765 //cast a ray from the camera position downwards
766 SBS_PROFILE("MeshObject::HitBeam");
767
768 Vector3 position = sbs->ToRemote(origin - GetPosition());
769 Ray ray (position, sbs->ToRemote(direction, false));
770
771 for (size_t i = 0; i < Walls.size(); i++)
772 {
773 if (!Walls[i])
774 continue;
775
776 for (size_t j = 0; j < Walls[i]->GetPolygonCount(); j++)
777 {
778 Polygon *poly = Walls[i]->GetPolygon(j);
779
780 if (!poly)
781 continue;
782
783 for (size_t k = 0; k < poly->triangles.size(); k++)
784 {
785 const Triangle &tri = poly->triangles[k];
786 Vector3 tri_a = poly->GetVertex(tri.a);
787 Vector3 tri_b = poly->GetVertex(tri.b);
788 Vector3 tri_c = poly->GetVertex(tri.c);
789
790 std::pair<bool, Real> result = Ogre::Math::intersects(ray, tri_a, tri_b, tri_c);
791 if (result.first == true)
792 {
793 if (result.second <= sbs->ToRemote(max_distance))
794 return sbs->ToLocal(result.second);
795 }
796 }
797 }
798 }
799 return -1;
800}
801
803{
804 //set up triangle collider based on raw SBS mesh geometry
805
806 SBS_PROFILE("MeshObject::CreateCollider");
807
808 if (create_collider == false)
809 return;
810
811 //exit if collider already exists
812 if (mBody)
813 return;
814
815 if (!GetSceneNode())
816 return;
817
818 //exit if mesh is empty
819 if (Walls.size() == 0)
820 return;
821
822 unsigned int tricount = GetTriangleCount("", true);
823 unsigned int vcount = GetVertexCount();
824
825 try
826 {
827 //initialize collider shape
828 OgreBulletCollisions::TriangleMeshCollisionShape* shape = new OgreBulletCollisions::TriangleMeshCollisionShape(vcount, tricount * 3);
829
830 Real scale = GetSceneNode()->GetScale();
831
832 //add vertices to shape
833
834 int additions = 0;
835 for (size_t i = 0; i < Walls.size(); i++)
836 {
837 if (!Walls[i])
838 continue;
839
840 for (size_t j = 0; j < Walls[i]->GetPolygonCount(); j++)
841 {
842 Polygon *poly = Walls[i]->GetPolygon(j);
843
844 if (!poly)
845 continue;
846
847 PolyArray polyarray;
848
849 for (size_t k = 0; k < poly->geometry.size(); k++)
850 {
851 for (size_t l = 0; l < poly->geometry[k].size(); l++)
852 polyarray.emplace_back(poly->geometry[k][l].vertex);
853 }
854
855 for (size_t k = 0; k < poly->triangles.size(); k++)
856 {
857 const Triangle &tri = poly->triangles[k];
858
859 Vector3 a = polyarray[tri.a];
860 Vector3 b = polyarray[tri.b];
861 Vector3 c = polyarray[tri.c];
862
863 if (scale != 1.0)
864 {
865 a *= scale;
866 b *= scale;
867 c *= scale;
868 }
869
870 shape->AddTriangle(a, b, c);
871 additions++;
872 }
873 }
874 }
875
876 //exit if no geometry
877 if (additions == 0)
878 return;
879
880 //finalize shape
881 shape->Finish();
882
883 //create a collider scene node
884 if (!collider_node)
885 collider_node = GetSceneNode()->CreateChild(GetName() + " collider");
886
887 //physics is not supported on triangle meshes; use CreateBoxCollider instead
888 mBody = new OgreBulletDynamics::RigidBody(name, sbs->mWorld);
889 mBody->setStaticShape(collider_node->GetRawSceneNode(), shape, 0.1f, 0.5f, false);
890 mShape = shape;
891
892 if (sbs->DeleteColliders == true)
893 {
894 bool revert = false;
895 if (remove_on_disable == false)
896 {
897 remove_on_disable = true;
898 revert = true;
899 }
900
901 Enabled(false);
902 Enabled(true);
903
904 if (revert == true)
905 remove_on_disable = false;
906 }
907 }
908 catch (Ogre::Exception &e)
909 {
910 ReportError("Error creating collider for '" + name + "'\n" + e.getDescription());
911 }
912}
913
915{
916 //delete mesh collider
917
918 SBS_PROFILE("MeshObject::DeleteCollider");
919
920 //exit if collider doesn't exist
921 if (!mBody)
922 return;
923
924 //remove collider from world
925 mBody->removeFromWorld();
926
927 //delete collider object
928 delete mBody;
929 mBody = 0;
930 mShape = 0;
931}
932
933Vector2 MeshObject::GetExtents(int coord, bool flip_z)
934{
935 //returns the smallest and largest values from a specified coordinate type
936 //(x, y, or z) from the polygons of this mesh object.
937 //first parameter must be either 1 (for x), 2 (for y) or 3 (for z)
938
939 Real esmall = 0;
940 Real ebig = 0;
941 Real tempnum = 0;
942
943 //return 0,0 if coord value is out of range
944 if (coord < 1 || coord > 3)
945 return Vector2(0, 0);
946
947 for (size_t i = 0; i < Walls.size(); i++)
948 {
949 if (!Walls[i])
950 continue;
951
952 for (size_t j = 0; j < Walls[i]->GetPolygonCount(); j++)
953 {
954 Polygon *poly = Walls[i]->GetPolygon(j);
955
956 if (!poly)
957 continue;
958
959 for (size_t k = 0; k < poly->geometry.size(); k++)
960 {
961 for (size_t l = 0; l < poly->geometry[k].size(); l++)
962 {
963 Ogre::Vector3 vertex = poly->geometry[k][l].vertex;
964
965 if (coord == 1)
966 tempnum = poly->geometry[k][l].vertex.x;
967 if (coord == 2)
968 tempnum = poly->geometry[k][l].vertex.y;
969 if (coord == 3)
970 {
971 if (flip_z == false)
972 tempnum = poly->geometry[k][l].vertex.z;
973 else
974 tempnum = -poly->geometry[k][l].vertex.z;
975 }
976
977 if (j == 0)
978 {
979 esmall = tempnum;
980 ebig = tempnum;
981 }
982 else
983 {
984 if (tempnum < esmall)
985 esmall = tempnum;
986 if (tempnum > ebig)
987 ebig = tempnum;
988 }
989 }
990 }
991 }
992 }
993
994 return Vector2(esmall, ebig);
995}
996
997Wall* MeshObject::FindPolygon(const std::string &name, int &index)
998{
999 //finds a polygon by name in all associated wall objects
1000 //returns associated wall object and polygon index
1001
1002 for (size_t i = 0; i < Walls.size(); i++)
1003 {
1004 if (!Walls[i])
1005 continue;
1006
1007 int polygon = Walls[i]->FindPolygon(name);
1008 if (polygon > -1)
1009 {
1010 index = polygon;
1011 return Walls[i];
1012 }
1013 }
1014 index = -1;
1015 return 0;
1016}
1017
1018bool MeshObject::InBoundingBox(const Vector3 &pos, bool check_y)
1019{
1020 //determine if position 'pos' is inside the mesh's bounding box
1021
1022 Vector3 position = sbs->ToRemote(pos - GetPosition());
1023
1024 if (Bounds->isNull() == true)
1025 return false;
1026
1027 Vector3 min = Bounds->getMinimum();
1028 Vector3 max = Bounds->getMaximum();
1029
1030 if (position.x >= min.x && position.x <= max.x && position.z >= min.z && position.z <= max.z)
1031 {
1032 if (check_y == false)
1033 return true;
1034 else
1035 {
1036 if (position.y >= min.y && position.y <= max.y)
1037 return true;
1038 }
1039 }
1040 return false;
1041}
1042
1047
1048void MeshObject::GetMeshInformation(const Ogre::Mesh* const mesh, int &vertex_count, Vector3* &vertices, int &index_count, unsigned long* &indices, Ogre::AxisAlignedBox &extents)
1049{
1050 //read hardware buffers from a loaded model mesh, and return geometry arrays
1051
1052 bool added_shared = false;
1053 size_t current_offset = 0;
1054 size_t shared_offset = 0;
1055 size_t next_offset = 0;
1056 size_t index_offset = 0;
1057
1058 vertex_count = index_count = 0;
1059
1060 // Calculate how many vertices and indices we're going to need
1061 for (unsigned short i = 0; i < mesh->getNumSubMeshes(); i++)
1062 {
1063 Ogre::SubMesh* submesh = mesh->getSubMesh(i);
1064
1065 // We only need to add the shared vertices once
1066 if (submesh->useSharedVertices)
1067 {
1068 if (!added_shared)
1069 {
1070 vertex_count += (int)mesh->sharedVertexData->vertexCount;
1071 added_shared = true;
1072 }
1073 }
1074 else
1075 {
1076 vertex_count += (int)submesh->vertexData->vertexCount;
1077 }
1078
1079 // Add the indices
1080 index_count += (int)submesh->indexData->indexCount;
1081 }
1082
1083 //ensure minimum index count
1084 if (index_count < 3)
1085 return;
1086
1087 // Allocate space for the vertices and indices
1088 vertices = new Vector3[vertex_count];
1089 indices = new unsigned long[index_count];
1090
1091 added_shared = false;
1092
1093 // Run through the submeshes again, adding the data into the arrays
1094 for (unsigned short i = 0; i < mesh->getNumSubMeshes(); i++)
1095 {
1096 Ogre::SubMesh* submesh = mesh->getSubMesh(i);
1097 Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData;
1098
1099 if ((!submesh->useSharedVertices) || (submesh->useSharedVertices && !added_shared))
1100 {
1101 if(submesh->useSharedVertices)
1102 {
1103 added_shared = true;
1104 shared_offset = current_offset;
1105 }
1106
1107 const Ogre::VertexElement* posElem =
1108 vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
1109
1110 Ogre::HardwareVertexBufferSharedPtr vbuf =
1111 vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());
1112
1113 unsigned char* vertex =
1114 static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
1115
1116 float* pReal;
1117
1118 for (size_t j = 0; j < vertex_data->vertexCount; j++, vertex += vbuf->getVertexSize())
1119 {
1120 posElem->baseVertexPointerToElement(vertex, &pReal);
1121 Vector3 pt(pReal[0], pReal[1], pReal[2]);
1122 //vertices[current_offset + j] = (orient * (pt * scale)) + position;
1123 vertices[current_offset + j] = pt * sbs->ToRemote(GetSceneNode()->GetScale());
1124 extents.merge(vertices[current_offset + j]);
1125 }
1126
1127 vbuf->unlock();
1128 next_offset += vertex_data->vertexCount;
1129 }
1130
1131 Ogre::IndexData* index_data = submesh->indexData;
1132 size_t numTris = index_data->indexCount / 3;
1133 Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
1134
1135 bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
1136
1137 unsigned long* pLong = static_cast<unsigned long*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
1138 unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong);
1139
1140 size_t offset = (submesh->useSharedVertices)? shared_offset : current_offset;
1141
1142 if (use32bitindexes)
1143 {
1144 for (size_t k = 0; k < numTris * 3; k++)
1145 {
1146 indices[index_offset++] = pLong[k] + static_cast<unsigned long>(offset);
1147 }
1148 }
1149 else
1150 {
1151 for (size_t k = 0; k < numTris * 3; k++)
1152 {
1153 indices[index_offset++] = static_cast<unsigned long>(pShort[k]) + static_cast<unsigned long>(offset);
1154 }
1155 }
1156
1157 ibuf->unlock();
1158 current_offset = next_offset;
1159 }
1160}
1161
1163{
1164 unsigned int total = 0;
1165
1166 for (size_t i = 0; i < Walls.size(); i++)
1167 {
1168 if (Walls[i])
1169 total += Walls[i]->GetVertexCount();
1170 }
1171
1172 return total;
1173}
1174
1175unsigned int MeshObject::GetTriangleCount(const std::string &material, bool total)
1176{
1177 unsigned int tris = 0;
1178
1179 for (size_t i = 0; i < Walls.size(); i++)
1180 {
1181 if (Walls[i])
1182 {
1183 for (int j = 0; j < Walls[i]->GetPolygonCount(); j++)
1184 {
1185 Polygon *poly = Walls[i]->GetPolygon(j);
1186
1187 if (poly)
1188 {
1189 if (poly->material == material || (material == "" && total == true))
1190 tris += poly->triangles.size();
1191 }
1192 }
1193 }
1194 }
1195
1196 return tris;
1197}
1198
1199void MeshObject::SetMaterial(const std::string& material)
1200{
1201 //set material of this mesh object
1202
1203 MeshWrapper->SetMaterial(material);
1204}
1205
1206void MeshObject::EnablePhysics(bool value, Real restitution, Real friction, Real mass)
1207{
1208 //Enables or disables physics on the mesh, the physics properties
1209 //and collider will be set up on the object later during the SBS::Prepare() stage
1210
1211 is_physical = value;
1212 this->restitution = restitution;
1213 this->friction = friction;
1214 this->mass = mass;
1215
1216 //use box collider if physics should be enabled
1217 if (is_physical == true)
1218 tricollider = false;
1219
1221
1222 //set up collider for model (if mesh loaded from a filename)
1223 if ((Filename != "" || Meshname != "") && create_collider == true)
1224 {
1225 if (collidermesh.get() && Filename != "")
1226 {
1227 //create collider based on provided mesh collider
1228 int vertex_count, index_count;
1229 Vector3* vertices;
1230 long unsigned int* indices;
1231 Ogre::AxisAlignedBox box;
1232 GetMeshInformation(collidermesh.get(), vertex_count, vertices, index_count, indices, box);
1233 CreateColliderFromModel(vertex_count, vertices, index_count, indices);
1234 delete[] vertices;
1235 delete[] indices;
1236 Ogre::MeshManager::getSingleton().remove(collidermesh->getHandle());
1237 }
1238 else
1239 {
1240 //create generic box collider if separate mesh collider isn't available
1241 GetBounds();
1243 }
1244 }
1245}
1246
1248{
1249 //return size in bytes of this mesh object
1250
1251 if (size > 0)
1252 return size;
1253
1254 for (size_t i = 0; i < Walls.size(); i++)
1255 {
1256 if (!Walls[i])
1257 continue;
1258
1259 for (size_t j = 0; j < Walls[i]->GetPolygonCount(); j++)
1260 {
1261 Polygon *poly = Walls[i]->GetPolygon(j);
1262
1263 if (!poly)
1264 continue;
1265
1266 size += poly->size;
1267 }
1268 }
1269
1270 return size;
1271}
1272
1273}
bool IsActive()
Definition camera.h:171
void ResetCollisions()
Definition camera.cpp:1160
void UpdateVertices(MeshObject *client, const std::string &material="", Polygon *polygon=0, bool single=false)
void NeedsUpdate(MeshObject *client=0)
void EnableDebugView(bool value, MeshObject *client=0)
void SetMaterial(const std::string &material)
void RemoveClient(MeshObject *mesh)
void AddClient(MeshObject *mesh)
void DetachClient(MeshObject *client)
bool LoadFromMesh(const std::string &meshname)
void EnableShadows(bool value)
Ogre::AxisAlignedBox GetBounds(MeshObject *client=0)
bool IsVisible(MeshObject *client=0)
void Enabled(bool value, MeshObject *client=0)
bool UseDynamicBuffers()
Definition dynamicmesh.h:57
bool LoadFromFile(const std::string &filename, const std::string &path)
OgreBulletCollisions::CollisionShape * mShape
Definition mesh.h:105
PolyMesh * GetPolyMesh()
Definition mesh.cpp:676
std::string Filename
Definition mesh.h:107
void EnableShadows(bool value)
Definition mesh.cpp:669
size_t size
Definition mesh.h:122
void CreateCollider()
Definition mesh.cpp:802
Real friction
Definition mesh.h:114
bool IsPhysical()
Definition mesh.cpp:491
bool model_loaded
Definition mesh.h:109
bool LoadFromMesh(const std::string &meshname)
Definition mesh.cpp:643
Vector3 GetWallExtents(const std::string &name, Real altitude, bool get_max)
Definition mesh.cpp:425
std::vector< Wall * > Walls
Definition mesh.h:99
Wall * GetWallByName(std::string name)
Definition mesh.cpp:219
bool wrapper_selfcreate
Definition mesh.h:116
PolyMesh * polymesh
Definition mesh.h:120
void EnableDebugView(bool value)
Definition mesh.cpp:280
void CreateBoxCollider()
Definition mesh.cpp:329
bool InBoundingBox(const Vector3 &pos, bool check_y)
Definition mesh.cpp:1018
void OnRotate(bool parent)
Definition mesh.cpp:449
bool IsPrepared()
Definition mesh.cpp:681
void Enabled(bool value)
Definition mesh.cpp:154
void Cut(Vector3 start, Vector3 end, bool cutwalls, bool cutfloors, int checkwallnumber=0, bool reset_check=true)
Definition mesh.cpp:511
bool LoadColliderModel(Ogre::MeshPtr &collidermesh)
Definition mesh.cpp:614
Vector2 GetExtents(int coord, bool flip_z=false)
Definition mesh.cpp:933
Real HitBeam(const Vector3 &origin, const Vector3 &direction, Real max_distance)
Definition mesh.cpp:760
bool remove_on_disable
Definition mesh.h:49
void ResetPrepare()
Definition mesh.cpp:686
unsigned int GetVertexCount()
Definition mesh.cpp:1162
void GetMeshInformation(const Ogre::Mesh *const mesh, int &vertex_count, Vector3 *&vertices, int &index_count, unsigned long *&indices, Ogre::AxisAlignedBox &extents)
Definition mesh.cpp:1048
Real GetHeight()
Definition mesh.cpp:728
void OnMove(bool parent)
Definition mesh.cpp:437
bool ChangeTexture(const std::string &texture, bool matcheck=true)
Definition mesh.cpp:709
void SetMaterial(const std::string &material)
Definition mesh.cpp:1199
void Prepare(bool force=false)
Definition mesh.cpp:241
Ogre::MeshPtr collidermesh
Definition mesh.h:121
Vector3 GetOffset()
Definition mesh.cpp:496
void EnableCollider(bool value)
Definition mesh.cpp:179
void ChangeHeight(Real newheight)
Definition mesh.cpp:654
void DeleteWalls()
Definition mesh.cpp:372
Wall * FindPolygon(const std::string &name, int &index)
Definition mesh.cpp:997
unsigned int GetTriangleCount(const std::string &material, bool total)
Definition mesh.cpp:1175
Vector3 GetPoint(const std::string &wallname, const Vector3 &start, const Vector3 &end)
Definition mesh.cpp:412
bool is_physical
Definition mesh.h:113
void CutOutsideBounds(Vector3 start, Vector3 end, bool cutwalls, bool cutfloors)
Definition mesh.cpp:524
void GetBounds()
Definition mesh.cpp:149
void DeleteCollider()
Definition mesh.cpp:914
virtual ~MeshObject()
Definition mesh.cpp:117
bool tricollider
Definition mesh.h:48
bool LoadFromFile(const std::string &filename)
Definition mesh.cpp:543
bool ReplaceTexture(const std::string &oldtexture, const std::string &newtexture)
Definition mesh.cpp:691
size_t GetSize()
Definition mesh.cpp:1247
bool enabled
Definition mesh.h:112
bool UsingDynamicBuffers()
Definition mesh.cpp:649
OgreBulletDynamics::RigidBody * mBody
Definition mesh.h:104
Ogre::AxisAlignedBox * Bounds
Definition mesh.h:102
void CreateColliderFromModel(int &vertex_count, Vector3 *&vertices, int &index_count, unsigned long *&indices)
Definition mesh.cpp:286
DynamicMesh * MeshWrapper
Definition mesh.h:98
Wall * CreateWallObject(const std::string &name)
Definition mesh.cpp:208
bool prepared
Definition mesh.h:115
bool create_collider
Definition mesh.h:47
SceneNode * collider_node
Definition mesh.h:101
std::string name
Definition mesh.h:46
std::string Meshname
Definition mesh.h:108
bool IsEnabled()
Definition mesh.cpp:236
void EnablePhysics(bool value, Real restitution=0, Real friction=0, Real mass=0)
Definition mesh.cpp:1206
DynamicMesh * GetDynamicMesh()
Definition mesh.cpp:1043
Real restitution
Definition mesh.h:114
MeshObject(Object *parent, const std::string &name, DynamicMesh *wrapper=0, const std::string &filename="", const std::string &meshname="", Real max_render_distance=0, Real scale_multiplier=1, bool create_collider=true, bool dynamic_buffers=false)
Definition mesh.cpp:47
bool IsVisible(Ogre::Camera *camera)
Definition mesh.cpp:466
std::string Name
Definition object.h:52
const std::string & GetName()
Definition object.cpp:53
virtual bool ReportError(const std::string &message)
Definition object.cpp:84
Object * GetParent()
Definition object.cpp:42
virtual void Report(const std::string &message)
Definition object.cpp:78
bool parent_deleting
Definition object.h:64
virtual Vector3 GetPosition(bool relative=false)
Definition object.cpp:321
SceneNode * GetSceneNode()
Definition object.cpp:240
void SetValues(const std::string &type, const std::string &name, bool is_permanent, bool is_movable=true)
Definition object.cpp:144
std::vector< Triangle > triangles
Definition polygon.h:49
size_t size
Definition polygon.h:58
std::string material
Definition polygon.h:56
Vector3 GetVertex(int index)
Definition polygon.cpp:205
GeometrySet geometry
Definition polygon.h:47
void DeleteMeshHandle(MeshObject *handle)
Definition sbs.cpp:3132
void AddMeshHandle(MeshObject *handle)
Definition sbs.cpp:3127
Real AmbientG
Definition sbs.h:426
Real AmbientR
Definition sbs.h:426
std::string GetMountPath(std::string filename, std::string &newfilename)
Definition sbs.cpp:3335
Utility * GetUtility()
Definition sbs.cpp:4611
bool FastDelete
Definition sbs.h:188
Camera * camera
Definition sbs.h:160
OgreBulletDynamics::DynamicsWorld * mWorld
Definition sbs.h:153
Real ToLocal(Real remote_value)
Definition sbs.cpp:2367
bool GetConfigBool(const std::string &key, bool default_value)
Definition sbs.cpp:3243
Real ToRemote(Real local_value)
Definition sbs.cpp:2407
bool DeleteColliders
Definition sbs.h:184
Real AmbientB
Definition sbs.h:426
std::string VerifyFile(const std::string &filename)
Definition sbs.cpp:2916
Ogre::SceneNode * GetRawSceneNode()
Definition scenenode.h:35
SceneNode * CreateChild(std::string name, const Vector3 &offset=Vector3::ZERO)
void SetScale(Real scale)
std::string GetFullName()
void Cut(Wall *wall, Vector3 start, Vector3 end, bool cutwalls, bool cutfloors, int checkwallnumber=0, bool reset_check=true)
Definition utility.cpp:96
int FindPolygon(const std::string &name)
Definition wall.cpp:190
Vector3 GetWallExtents(Real altitude, bool get_max)
Definition wall.cpp:284
void DeletePolygons(bool recreate_collider=true)
Definition wall.cpp:137
void SetParentArray(std::vector< Wall * > &array)
Definition wall.cpp:263
Vector3 GetPoint(const Vector3 &start, const Vector3 &end)
Definition wall.cpp:268
Ogre::Ray Ray
Definition globals.h:63
Ogre::Vector3 Vector3
Definition globals.h:58
Ogre::Real Real
Definition globals.h:57
Ogre::Vector2 Vector2
Definition globals.h:59
std::vector< Vector3 > PolyArray
Definition sbs.h:118
void SetCase(std::string &string, bool uppercase)
Definition globals.cpp:172
std::string SetCaseCopy(std::string string, bool uppercase)
Definition globals.cpp:165
bool StartsWith(const std::string &string, const std::string &check_string, bool ignore_case)
Definition globals.cpp:216
void TrimString(std::string &string)
Definition globals.cpp:188
#define SBS_PROFILE(name)
Definition profiler.h:131
unsigned int c
Definition triangle.h:33
unsigned int a
Definition triangle.h:33
unsigned int b
Definition triangle.h:33