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, name);
213 Walls.emplace_back(wall);
214 return wall;
215}
216
218{
219 //find a wall object by name
220
221 SetCase(name, false);
222
223 for (size_t i = 0; i < Walls.size(); i++)
224 {
225 if (!Walls[i])
226 continue;
227
228 if (name == SetCaseCopy(Walls[i]->GetName(), false) == true)
229 return Walls[i];
230 }
231 return 0;
232}
233
235{
236 return enabled;
237}
238
239void MeshObject::Prepare(bool force)
240{
241 //prepare mesh object
242
243 SBS_PROFILE("MeshObject::Prepare");
244
245 if (prepared == true && force == false)
246 return;
247
248 //set up bounding box
249 if (model_loaded == false)
250 {
251 Bounds->setNull();
252 for (size_t i = 0; i < Walls.size(); i++)
253 {
254 if (!Walls[i])
255 continue;
256
257 for (size_t j = 0; j < Walls[i]->polygons.size(); j++)
258 {
259 Polygon *poly = Walls[i]->polygons[j];
260
261 if (!poly)
262 continue;
263 for (size_t k = 0; k < poly->geometry.size(); k++)
264 {
265 for (size_t l = 0; l < poly->geometry[k].size(); l++)
266 Bounds->merge(poly->geometry[k][l].vertex);
267 }
268 }
269 }
270 }
271
272 //update dynamic mesh
274
275 prepared = true;
276}
277
279{
280 //enable or disable debug view of mesh
281 MeshWrapper->EnableDebugView(value, this);
282}
283
284void MeshObject::CreateColliderFromModel(int &vertex_count, Vector3* &vertices, int &index_count, unsigned long* &indices)
285{
286 //set up triangle collider based on loaded model geometry
287
288 if (create_collider == false)
289 return;
290
291 //exit of collider already exists
292 if (mBody)
293 return;
294
295 if (!GetSceneNode())
296 return;
297
298 try
299 {
300 //initialize collider shape
301 OgreBulletCollisions::TriangleMeshCollisionShape* shape = new OgreBulletCollisions::TriangleMeshCollisionShape(vertex_count, index_count);
302
303 //add vertices to shape
304 for (int i = 0; i < index_count; i += 3)
305 {
306 shape->AddTriangle(vertices[indices[i]], vertices[indices[i + 1]], vertices[indices[i + 2]]);
307 }
308
309 //finalize shape
310 shape->Finish();
311
312 //create a collider scene node
313 if (!collider_node)
314 collider_node = GetSceneNode()->CreateChild(GetName() + " collider");
315
316 //physics is not supported on triangle meshes; use CreateBoxCollider instead
317 mBody = new OgreBulletDynamics::RigidBody(name, sbs->mWorld);
318 mBody->setStaticShape(collider_node->GetRawSceneNode(), shape, 0.1f, 0.5f, false);
319 mShape = shape;
320 }
321 catch (Ogre::Exception &e)
322 {
323 ReportError("Error creating model collider for '" + name + "'\n" + e.getDescription());
324 }
325}
326
328{
329 //set up a box collider for full extents of a mesh
330
331 if (create_collider == false)
332 return;
333
334 //exit of collider already exists
335 if (mBody)
336 return;
337
338 if (!GetSceneNode())
339 return;
340
341 try
342 {
343 //initialize collider shape
344 Real scale = GetSceneNode()->GetScale();
345
346 if (Bounds->isNull() == true)
347 return;
348
349 Vector3 bounds = Bounds->getHalfSize() * scale;
350 OgreBulletCollisions::BoxCollisionShape* shape = new OgreBulletCollisions::BoxCollisionShape(bounds);
351
352 //create a new scene node for this collider, and center the collider accordingly
353 Vector3 collider_center = sbs->ToLocal(Bounds->getCenter());
354 if (!collider_node)
355 collider_node = GetSceneNode()->CreateChild(GetName() + " collider", collider_center);
356
357 mBody = new OgreBulletDynamics::RigidBody(name, sbs->mWorld);
358 if (IsPhysical() == false)
359 mBody->setStaticShape(collider_node->GetRawSceneNode(), shape, 0.1f, 0.5f, false);
360 else
362 mShape = shape;
363 }
364 catch (Ogre::Exception &e)
365 {
366 ReportError("Error creating box collider for '" + name + "'\n" + e.getDescription());
367 }
368}
369
371{
372 //delete all wall objects
373
374 for (size_t i = 0; i < Walls.size(); i++)
375 {
376 Wall *wall = Walls[i];
377 if (wall)
378 {
379 wall->parent_deleting = true;
380 if (sbs->FastDelete == false)
381 wall->DeletePolygons();
382 delete wall;
383 Walls[i] = 0;
384 }
385 }
386 Walls.clear();
387}
388
390{
391 //delete walls of specified parent object
392
393 for (size_t i = 0; i < Walls.size(); i++)
394 {
395 Wall *wall = Walls[i];
396 if (wall)
397 {
398 if (wall->GetParent() == parent)
399 {
400 wall->parent_deleting = true;
401 wall->DeletePolygons();
402 delete wall;
403 Walls.erase(Walls.begin() + i);
404 i--;
405 }
406 }
407 }
408}
409
410Vector3 MeshObject::GetPoint(const std::string &wallname, const Vector3 &start, const Vector3 &end)
411{
412 //do a line intersection with a specified wall associated with this mesh object,
413 //and return the intersection point
414
415 Wall *wall = GetWallByName(wallname);
416
417 if (wall)
418 return wall->GetPoint(start, end);
419
420 return Vector3(0, 0, 0);
421}
422
423Vector3 MeshObject::GetWallExtents(const std::string &name, Real altitude, bool get_max)
424{
425 //return the X and Z extents of a standard wall (by name) at a specific altitude, by doing a double plane cut
426
427 Wall *wall = GetWallByName(name);
428
429 if (wall)
430 return wall->GetWallExtents(altitude, get_max);
431
432 return Vector3(0, 0, 0);
433}
434
435void MeshObject::OnMove(bool parent)
436{
437 if (collider_node)
439
440 if (mBody)
441 mBody->updateTransform(true, false, false);
442
443 if (UsingDynamicBuffers() == true)
445}
446
447void MeshObject::OnRotate(bool parent)
448{
449 if (collider_node)
451
452 if (mBody)
453 {
454 if (parent == true)
455 OnMove(parent); //update position if parent object has been rotated
456
457 mBody->updateTransform(false, true, false);
458 }
459
460 if (UsingDynamicBuffers() == true)
462}
463
464bool MeshObject::IsVisible(Ogre::Camera *camera)
465{
466 //returns if this mesh object is visible in the provided camera's view frustum or not
467
468 if (IsEnabled() == false || !camera)
469 return false;
470
471 //if beyond the max render distance
472 if (MeshWrapper->IsVisible(this) == false)
473 return false;
474
475 //if (polymesh->GetSubmeshCount() == 0)
476 //return false;
477
478 if (Bounds->isNull() == true)
479 return false;
480
481 Vector3 min = Bounds->getMinimum();
482 Vector3 max = Bounds->getMaximum();
484 Ogre::AxisAlignedBox global_box (pos + min, pos + max);
485
486 return camera->isVisible(global_box);
487}
488
490{
491 return is_physical;
492}
493
495{
496 //for models, return bounding box offset value, used to center the mesh
497
498 Bounds->scale(GetSceneNode()->GetRawSceneNode()->getScale());
499
500 if (Bounds->isNull() == true)
501 return Vector3::ZERO;
502
503 Vector3 vec = Bounds->getCenter();
504 Vector3 min = Bounds->getMinimum();
505 Vector3 offset (vec.x, -Bounds->getMinimum().y, -vec.z);
506 return sbs->ToLocal(offset);
507}
508
509void MeshObject::Cut(Vector3 start, Vector3 end, bool cutwalls, bool cutfloors, int checkwallnumber, bool reset_check)
510{
511 //cut all walls in this mesh object
512
513 for (size_t i = 0; i < Walls.size(); i++)
514 {
515 if (!Walls[i])
516 continue;
517
518 sbs->GetUtility()->Cut(Walls[i], start, end, cutwalls, cutfloors, checkwallnumber, reset_check);
519 }
520}
521
522void MeshObject::CutOutsideBounds(Vector3 start, Vector3 end, bool cutwalls, bool cutfloors)
523{
524 Real limit = 1000000;
525
526 Vector3 left_min (-limit, -limit, -limit);
527 Vector3 left_max (start.x, limit, limit);
528 Vector3 right_min (end.x, -limit, -limit);
529 Vector3 right_max (limit, limit, limit);
530 Vector3 front_min (-limit, -limit, -limit);
531 Vector3 front_max (limit, limit, start.z);
532 Vector3 back_min (-limit, -limit, end.z);
533 Vector3 back_max (limit, limit, limit);
534
535 Cut(left_min, left_max, cutwalls, cutfloors);
536 Cut(right_min, right_max, cutwalls, cutfloors);
537 Cut(front_min, front_max, cutwalls, cutfloors);
538 Cut(back_min, back_max, cutwalls, cutfloors);
539}
540
541bool MeshObject::LoadFromFile(const std::string &filename)
542{
543 //load mesh object from a file
544
545 std::string filename1 = "data/";
546 filename1.append(filename);
547 std::string filename2 = sbs->VerifyFile(filename1);
548 std::string path = sbs->GetMountPath(filename2, filename2);
549 std::string matname;
550
551 //load material file
552 try
553 {
554 matname = filename2.substr(0, filename2.length() - 5) + ".material";
555 std::string matname2 = sbs->VerifyFile(matname);
556 Ogre::DataStreamPtr stream = Ogre::ResourceGroupManager::getSingleton().openResource(matname2, path);
557 Report("Loading material script " + matname2);
558 Ogre::MaterialManager::getSingleton().parseScript(stream, path);
559
560 if(stream)
561 {
562 stream->seek(0);
563 while(!stream->eof())
564 {
565 std::string line = stream->getLine();
566 TrimString(line);
567 if (StartsWith(line, "material", true) == true)
568 {
569 std::vector<std::string> vec = Ogre::StringUtil::split(line," \t:");
570 for (std::vector<std::string>::iterator it = vec.begin(); it < vec.end(); ++it)
571 {
572 std::string match = (*it);
573 TrimString(match);
574 if (!match.empty())
575 {
576 Ogre::MaterialPtr materialPtr = Ogre::MaterialManager::getSingleton().getByName(match, path);
577 if (materialPtr)
578 {
579 Report("Loading material " + match);
580 //materialPtr->compile();
581 materialPtr->load();
582
583 //set lighting
584 materialPtr->setLightingEnabled(false);
585 if (sbs->GetConfigBool("Skyscraper.SBS.Lighting", false) == true)
586 {
587 materialPtr->setLightingEnabled(true);
588 materialPtr->setAmbient(sbs->AmbientR, sbs->AmbientG, sbs->AmbientB);
589 }
590 }
591 }
592 }
593 }
594 }
595 stream->close();
596 }
597 }
598 catch (Ogre::Exception &e)
599 {
600 ReportError("Error loading material file " + matname + "\n" + e.getDescription());
601 }
602
603 //load model
604 bool status = MeshWrapper->LoadFromFile(filename2, path);
605 if (status == false)
606 return false;
607
608 model_loaded = true;
609 return true;
610}
611
612bool MeshObject::LoadColliderModel(Ogre::MeshPtr &collidermesh)
613{
614 if (Filename == "")
615 return false;
616
617 std::string filename1 = "data/";
618 filename1.append(Filename);
619 std::string filename2 = sbs->VerifyFile(filename1);
620 std::string path = sbs->GetMountPath(filename2, filename2);
621
622 //load collider model if physics is disabled
623 if (is_physical == false)
624 {
625 std::string colname2;
626
627 try
628 {
629 std::string colname = filename2.substr(0, filename2.length() - 5) + ".collider.mesh";
630 colname2 = sbs->VerifyFile(colname);
631 collidermesh = Ogre::MeshManager::getSingleton().load(colname2, path);
632 }
633 catch (Ogre::Exception &e)
634 {
635 return ReportError("No collider model for " + colname2 + "\n" + e.getDescription());
636 }
637 }
638 return true;
639}
640
641bool MeshObject::LoadFromMesh(const std::string &meshname)
642{
643 //load mesh
644 return MeshWrapper->LoadFromMesh(meshname);
645}
646
651
653{
654 //change height of all walls associated with this mesh object
655
656 SBS_PROFILE("MeshObject::ChangeHeight");
657
658 for (size_t i = 0; i < Walls.size(); i++)
659 {
660 if (!Walls[i])
661 continue;
662
663 Walls[i]->ChangeHeight(newheight);
664 }
665}
666
668{
669 //enable shadows
670
672}
673
678
680{
681 return prepared;
682}
683
685{
686 prepared = false;
687}
688
689bool MeshObject::ReplaceTexture(const std::string &oldtexture, const std::string &newtexture)
690{
691 //replace polygon materials named oldtexture with newtexture
692
693 //update associated polygons
694 bool found = false;
695 for (size_t i = 0; i < Walls.size(); i++)
696 {
697 if (!Walls[i])
698 continue;
699
700 bool result = Walls[i]->ReplaceTexture(oldtexture, newtexture);
701 if (result == true)
702 found = true;
703 }
704 return found;
705}
706
707bool MeshObject::ChangeTexture(const std::string &texture, bool matcheck)
708{
709 //changes a texture
710 //if matcheck is true, exit if old and new textures are the same
711
712 //update associated polygons
713 bool found = false;
714 for (size_t i = 0; i < Walls.size(); i++)
715 {
716 if (!Walls[i])
717 continue;
718
719 bool result = Walls[i]->ChangeTexture(texture, matcheck);
720 if (result == true)
721 found = true;
722 }
723 return found;
724}
725
727{
728 //returns the height of the mesh
729
730 Real y = 0.0;
731 for (size_t i = 0; i < Walls.size(); i++)
732 {
733 if (!Walls[i])
734 continue;
735
736 for (size_t j = 0; j < Walls[i]->GetPolygonCount(); j++)
737 {
738 Polygon *poly = Walls[i]->GetPolygon(j);
739
740 if (!poly)
741 continue;
742
743 for (size_t k = 0; k < poly->geometry.size(); k++)
744 {
745 for (size_t l = 0; l < poly->geometry[k].size(); l++)
746 {
747 Real new_y = poly->geometry[k][l].vertex.y;
748 if (new_y > y)
749 y = new_y;
750 }
751 }
752 }
753 }
754
755 return sbs->ToLocal(y);
756}
757
758Real MeshObject::HitBeam(const Vector3 &origin, const Vector3 &direction, Real max_distance)
759{
760 //cast a ray and return the collision distance to the mesh
761 //return -1 if no hit
762
763 //cast a ray from the camera position downwards
764 SBS_PROFILE("MeshObject::HitBeam");
765
766 Vector3 position = sbs->ToRemote(origin - GetPosition());
767 Ray ray (position, sbs->ToRemote(direction, false));
768
769 for (size_t i = 0; i < Walls.size(); i++)
770 {
771 if (!Walls[i])
772 continue;
773
774 for (size_t j = 0; j < Walls[i]->GetPolygonCount(); j++)
775 {
776 Polygon *poly = Walls[i]->GetPolygon(j);
777
778 if (!poly)
779 continue;
780
781 for (size_t k = 0; k < poly->triangles.size(); k++)
782 {
783 const Triangle &tri = poly->triangles[k];
784 Vector3 tri_a = poly->GetVertex(tri.a);
785 Vector3 tri_b = poly->GetVertex(tri.b);
786 Vector3 tri_c = poly->GetVertex(tri.c);
787
788 std::pair<bool, Real> result = Ogre::Math::intersects(ray, tri_a, tri_b, tri_c);
789 if (result.first == true)
790 {
791 if (result.second <= sbs->ToRemote(max_distance))
792 return sbs->ToLocal(result.second);
793 }
794 }
795 }
796 }
797 return -1;
798}
799
801{
802 //set up triangle collider based on raw SBS mesh geometry
803
804 SBS_PROFILE("MeshObject::CreateCollider");
805
806 if (create_collider == false)
807 return;
808
809 //exit if collider already exists
810 if (mBody)
811 return;
812
813 if (!GetSceneNode())
814 return;
815
816 //exit if mesh is empty
817 if (Walls.size() == 0)
818 return;
819
820 unsigned int tricount = GetTriangleCount("", true);
821 unsigned int vcount = GetVertexCount();
822
823 try
824 {
825 //initialize collider shape
826 OgreBulletCollisions::TriangleMeshCollisionShape* shape = new OgreBulletCollisions::TriangleMeshCollisionShape(vcount, tricount * 3);
827
828 Real scale = GetSceneNode()->GetScale();
829
830 //add vertices to shape
831
832 int additions = 0;
833 for (size_t i = 0; i < Walls.size(); i++)
834 {
835 if (!Walls[i])
836 continue;
837
838 for (size_t j = 0; j < Walls[i]->GetPolygonCount(); j++)
839 {
840 Polygon *poly = Walls[i]->GetPolygon(j);
841
842 if (!poly)
843 continue;
844
845 PolyArray polyarray;
846
847 for (size_t k = 0; k < poly->geometry.size(); k++)
848 {
849 for (size_t l = 0; l < poly->geometry[k].size(); l++)
850 polyarray.emplace_back(poly->geometry[k][l].vertex);
851 }
852
853 for (size_t k = 0; k < poly->triangles.size(); k++)
854 {
855 const Triangle &tri = poly->triangles[k];
856
857 Vector3 a = polyarray[tri.a];
858 Vector3 b = polyarray[tri.b];
859 Vector3 c = polyarray[tri.c];
860
861 if (scale != 1.0)
862 {
863 a *= scale;
864 b *= scale;
865 c *= scale;
866 }
867
868 shape->AddTriangle(a, b, c);
869 additions++;
870 }
871 }
872 }
873
874 //exit if no geometry
875 if (additions == 0)
876 return;
877
878 //finalize shape
879 shape->Finish();
880
881 //create a collider scene node
882 if (!collider_node)
883 collider_node = GetSceneNode()->CreateChild(GetName() + " collider");
884
885 //physics is not supported on triangle meshes; use CreateBoxCollider instead
886 mBody = new OgreBulletDynamics::RigidBody(name, sbs->mWorld);
887 mBody->setStaticShape(collider_node->GetRawSceneNode(), shape, 0.1f, 0.5f, false);
888 mShape = shape;
889
890 if (sbs->DeleteColliders == true)
891 {
892 bool revert = false;
893 if (remove_on_disable == false)
894 {
895 remove_on_disable = true;
896 revert = true;
897 }
898
899 Enabled(false);
900 Enabled(true);
901
902 if (revert == true)
903 remove_on_disable = false;
904 }
905 }
906 catch (Ogre::Exception &e)
907 {
908 ReportError("Error creating collider for '" + name + "'\n" + e.getDescription());
909 }
910}
911
913{
914 //delete mesh collider
915
916 SBS_PROFILE("MeshObject::DeleteCollider");
917
918 //exit if collider doesn't exist
919 if (!mBody)
920 return;
921
922 //remove collider from world
923 mBody->removeFromWorld();
924
925 //delete collider object
926 delete mBody;
927 mBody = 0;
928 mShape = 0;
929}
930
931Vector2 MeshObject::GetExtents(int coord, bool flip_z)
932{
933 //returns the smallest and largest values from a specified coordinate type
934 //(x, y, or z) from the polygons of this mesh object.
935 //first parameter must be either 1 (for x), 2 (for y) or 3 (for z)
936
937 Real esmall = 0;
938 Real ebig = 0;
939 Real tempnum = 0;
940
941 //return 0,0 if coord value is out of range
942 if (coord < 1 || coord > 3)
943 return Vector2(0, 0);
944
945 for (size_t i = 0; i < Walls.size(); i++)
946 {
947 if (!Walls[i])
948 continue;
949
950 for (size_t j = 0; j < Walls[i]->GetPolygonCount(); j++)
951 {
952 Polygon *poly = Walls[i]->GetPolygon(j);
953
954 if (!poly)
955 continue;
956
957 for (size_t k = 0; k < poly->geometry.size(); k++)
958 {
959 for (size_t l = 0; l < poly->geometry[k].size(); l++)
960 {
961 Ogre::Vector3 vertex = poly->geometry[k][l].vertex;
962
963 if (coord == 1)
964 tempnum = poly->geometry[k][l].vertex.x;
965 if (coord == 2)
966 tempnum = poly->geometry[k][l].vertex.y;
967 if (coord == 3)
968 {
969 if (flip_z == false)
970 tempnum = poly->geometry[k][l].vertex.z;
971 else
972 tempnum = -poly->geometry[k][l].vertex.z;
973 }
974
975 if (j == 0)
976 {
977 esmall = tempnum;
978 ebig = tempnum;
979 }
980 else
981 {
982 if (tempnum < esmall)
983 esmall = tempnum;
984 if (tempnum > ebig)
985 ebig = tempnum;
986 }
987 }
988 }
989 }
990 }
991
992 return Vector2(esmall, ebig);
993}
994
995Wall* MeshObject::FindPolygon(const std::string &name, int &index)
996{
997 //finds a polygon by name in all associated wall objects
998 //returns associated wall object and polygon index
999
1000 for (size_t i = 0; i < Walls.size(); i++)
1001 {
1002 if (!Walls[i])
1003 continue;
1004
1005 int polygon = Walls[i]->FindPolygon(name);
1006 if (polygon > -1)
1007 {
1008 index = polygon;
1009 return Walls[i];
1010 }
1011 }
1012 index = -1;
1013 return 0;
1014}
1015
1016bool MeshObject::InBoundingBox(const Vector3 &pos, bool check_y)
1017{
1018 //determine if position 'pos' is inside the mesh's bounding box
1019
1020 Vector3 position = sbs->ToRemote(pos - GetPosition());
1021
1022 if (Bounds->isNull() == true)
1023 return false;
1024
1025 Vector3 min = Bounds->getMinimum();
1026 Vector3 max = Bounds->getMaximum();
1027
1028 if (position.x >= min.x && position.x <= max.x && position.z >= min.z && position.z <= max.z)
1029 {
1030 if (check_y == false)
1031 return true;
1032 else
1033 {
1034 if (position.y >= min.y && position.y <= max.y)
1035 return true;
1036 }
1037 }
1038 return false;
1039}
1040
1045
1046void MeshObject::GetMeshInformation(const Ogre::Mesh* const mesh, int &vertex_count, Vector3* &vertices, int &index_count, unsigned long* &indices, Ogre::AxisAlignedBox &extents)
1047{
1048 //read hardware buffers from a loaded model mesh, and return geometry arrays
1049
1050 bool added_shared = false;
1051 size_t current_offset = 0;
1052 size_t shared_offset = 0;
1053 size_t next_offset = 0;
1054 size_t index_offset = 0;
1055
1056 vertex_count = index_count = 0;
1057
1058 // Calculate how many vertices and indices we're going to need
1059 for (unsigned short i = 0; i < mesh->getNumSubMeshes(); i++)
1060 {
1061 Ogre::SubMesh* submesh = mesh->getSubMesh(i);
1062
1063 // We only need to add the shared vertices once
1064 if (submesh->useSharedVertices)
1065 {
1066 if (!added_shared)
1067 {
1068 vertex_count += (int)mesh->sharedVertexData->vertexCount;
1069 added_shared = true;
1070 }
1071 }
1072 else
1073 {
1074 vertex_count += (int)submesh->vertexData->vertexCount;
1075 }
1076
1077 // Add the indices
1078 index_count += (int)submesh->indexData->indexCount;
1079 }
1080
1081 //ensure minimum index count
1082 if (index_count < 3)
1083 return;
1084
1085 // Allocate space for the vertices and indices
1086 vertices = new Vector3[vertex_count];
1087 indices = new unsigned long[index_count];
1088
1089 added_shared = false;
1090
1091 // Run through the submeshes again, adding the data into the arrays
1092 for (unsigned short i = 0; i < mesh->getNumSubMeshes(); i++)
1093 {
1094 Ogre::SubMesh* submesh = mesh->getSubMesh(i);
1095 Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData;
1096
1097 if ((!submesh->useSharedVertices) || (submesh->useSharedVertices && !added_shared))
1098 {
1099 if(submesh->useSharedVertices)
1100 {
1101 added_shared = true;
1102 shared_offset = current_offset;
1103 }
1104
1105 const Ogre::VertexElement* posElem =
1106 vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
1107
1108 Ogre::HardwareVertexBufferSharedPtr vbuf =
1109 vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());
1110
1111 unsigned char* vertex =
1112 static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
1113
1114 float* pReal;
1115
1116 for (size_t j = 0; j < vertex_data->vertexCount; j++, vertex += vbuf->getVertexSize())
1117 {
1118 posElem->baseVertexPointerToElement(vertex, &pReal);
1119 Vector3 pt(pReal[0], pReal[1], pReal[2]);
1120 //vertices[current_offset + j] = (orient * (pt * scale)) + position;
1121 vertices[current_offset + j] = pt * sbs->ToRemote(GetSceneNode()->GetScale());
1122 extents.merge(vertices[current_offset + j]);
1123 }
1124
1125 vbuf->unlock();
1126 next_offset += vertex_data->vertexCount;
1127 }
1128
1129 Ogre::IndexData* index_data = submesh->indexData;
1130 size_t numTris = index_data->indexCount / 3;
1131 Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
1132
1133 bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
1134
1135 unsigned long* pLong = static_cast<unsigned long*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
1136 unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong);
1137
1138 size_t offset = (submesh->useSharedVertices)? shared_offset : current_offset;
1139
1140 if (use32bitindexes)
1141 {
1142 for (size_t k = 0; k < numTris * 3; k++)
1143 {
1144 indices[index_offset++] = pLong[k] + static_cast<unsigned long>(offset);
1145 }
1146 }
1147 else
1148 {
1149 for (size_t k = 0; k < numTris * 3; k++)
1150 {
1151 indices[index_offset++] = static_cast<unsigned long>(pShort[k]) + static_cast<unsigned long>(offset);
1152 }
1153 }
1154
1155 ibuf->unlock();
1156 current_offset = next_offset;
1157 }
1158}
1159
1161{
1162 unsigned int total = 0;
1163
1164 for (size_t i = 0; i < Walls.size(); i++)
1165 {
1166 if (Walls[i])
1167 total += Walls[i]->GetVertexCount();
1168 }
1169
1170 return total;
1171}
1172
1173unsigned int MeshObject::GetTriangleCount(const std::string &material, bool total)
1174{
1175 unsigned int tris = 0;
1176
1177 for (size_t i = 0; i < Walls.size(); i++)
1178 {
1179 if (Walls[i])
1180 {
1181 for (int j = 0; j < Walls[i]->GetPolygonCount(); j++)
1182 {
1183 Polygon *poly = Walls[i]->GetPolygon(j);
1184
1185 if (poly)
1186 {
1187 if (poly->material == material || (material == "" && total == true))
1188 tris += poly->triangles.size();
1189 }
1190 }
1191 }
1192 }
1193
1194 return tris;
1195}
1196
1197void MeshObject::SetMaterial(const std::string& material)
1198{
1199 //set material of this mesh object
1200
1201 MeshWrapper->SetMaterial(material);
1202}
1203
1204void MeshObject::EnablePhysics(bool value, Real restitution, Real friction, Real mass)
1205{
1206 //Enables or disables physics on the mesh, the physics properties
1207 //and collider will be set up on the object later during the SBS::Prepare() stage
1208
1209 is_physical = value;
1210 this->restitution = restitution;
1211 this->friction = friction;
1212 this->mass = mass;
1213
1214 //use box collider if physics should be enabled
1215 if (is_physical == true)
1216 tricollider = false;
1217
1219
1220 //set up collider for model (if mesh loaded from a filename)
1221 if ((Filename != "" || Meshname != "") && create_collider == true)
1222 {
1223 if (collidermesh.get() && Filename != "")
1224 {
1225 //create collider based on provided mesh collider
1226 int vertex_count, index_count;
1227 Vector3* vertices;
1228 long unsigned int* indices;
1229 Ogre::AxisAlignedBox box;
1230 GetMeshInformation(collidermesh.get(), vertex_count, vertices, index_count, indices, box);
1231 CreateColliderFromModel(vertex_count, vertices, index_count, indices);
1232 delete[] vertices;
1233 delete[] indices;
1234 Ogre::MeshManager::getSingleton().remove(collidermesh->getHandle());
1235 }
1236 else
1237 {
1238 //create generic box collider if separate mesh collider isn't available
1239 GetBounds();
1241 }
1242 }
1243}
1244
1246{
1247 //return size in bytes of this mesh object
1248
1249 if (size > 0)
1250 return size;
1251
1252 for (size_t i = 0; i < Walls.size(); i++)
1253 {
1254 if (!Walls[i])
1255 continue;
1256
1257 for (size_t j = 0; j < Walls[i]->GetPolygonCount(); j++)
1258 {
1259 Polygon *poly = Walls[i]->GetPolygon(j);
1260
1261 if (!poly)
1262 continue;
1263
1264 size += poly->size;
1265 }
1266 }
1267
1268 return size;
1269}
1270
1271}
bool IsActive()
Definition camera.h:171
void ResetCollisions()
Definition camera.cpp:1159
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:674
std::string Filename
Definition mesh.h:107
void EnableShadows(bool value)
Definition mesh.cpp:667
size_t size
Definition mesh.h:123
void CreateCollider()
Definition mesh.cpp:800
Real friction
Definition mesh.h:114
bool IsPhysical()
Definition mesh.cpp:489
bool model_loaded
Definition mesh.h:109
bool LoadFromMesh(const std::string &meshname)
Definition mesh.cpp:641
Vector3 GetWallExtents(const std::string &name, Real altitude, bool get_max)
Definition mesh.cpp:423
std::vector< Wall * > Walls
Definition mesh.h:99
Wall * GetWallByName(std::string name)
Definition mesh.cpp:217
bool wrapper_selfcreate
Definition mesh.h:116
PolyMesh * polymesh
Definition mesh.h:121
void EnableDebugView(bool value)
Definition mesh.cpp:278
void CreateBoxCollider()
Definition mesh.cpp:327
bool InBoundingBox(const Vector3 &pos, bool check_y)
Definition mesh.cpp:1016
void OnRotate(bool parent)
Definition mesh.cpp:447
bool IsPrepared()
Definition mesh.cpp:679
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:509
bool LoadColliderModel(Ogre::MeshPtr &collidermesh)
Definition mesh.cpp:612
Vector2 GetExtents(int coord, bool flip_z=false)
Definition mesh.cpp:931
Real HitBeam(const Vector3 &origin, const Vector3 &direction, Real max_distance)
Definition mesh.cpp:758
bool remove_on_disable
Definition mesh.h:49
void ResetPrepare()
Definition mesh.cpp:684
unsigned int GetVertexCount()
Definition mesh.cpp:1160
void GetMeshInformation(const Ogre::Mesh *const mesh, int &vertex_count, Vector3 *&vertices, int &index_count, unsigned long *&indices, Ogre::AxisAlignedBox &extents)
Definition mesh.cpp:1046
Real GetHeight()
Definition mesh.cpp:726
void OnMove(bool parent)
Definition mesh.cpp:435
bool ChangeTexture(const std::string &texture, bool matcheck=true)
Definition mesh.cpp:707
void SetMaterial(const std::string &material)
Definition mesh.cpp:1197
void Prepare(bool force=false)
Definition mesh.cpp:239
Ogre::MeshPtr collidermesh
Definition mesh.h:122
Vector3 GetOffset()
Definition mesh.cpp:494
void EnableCollider(bool value)
Definition mesh.cpp:179
void ChangeHeight(Real newheight)
Definition mesh.cpp:652
void DeleteWalls()
Definition mesh.cpp:370
Wall * FindPolygon(const std::string &name, int &index)
Definition mesh.cpp:995
unsigned int GetTriangleCount(const std::string &material, bool total)
Definition mesh.cpp:1173
Vector3 GetPoint(const std::string &wallname, const Vector3 &start, const Vector3 &end)
Definition mesh.cpp:410
bool is_physical
Definition mesh.h:113
void CutOutsideBounds(Vector3 start, Vector3 end, bool cutwalls, bool cutfloors)
Definition mesh.cpp:522
void GetBounds()
Definition mesh.cpp:149
void DeleteCollider()
Definition mesh.cpp:912
virtual ~MeshObject()
Definition mesh.cpp:117
bool tricollider
Definition mesh.h:48
bool LoadFromFile(const std::string &filename)
Definition mesh.cpp:541
bool ReplaceTexture(const std::string &oldtexture, const std::string &newtexture)
Definition mesh.cpp:689
size_t GetSize()
Definition mesh.cpp:1245
bool enabled
Definition mesh.h:112
bool UsingDynamicBuffers()
Definition mesh.cpp:647
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:284
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:234
void EnablePhysics(bool value, Real restitution=0, Real friction=0, Real mass=0)
Definition mesh.cpp:1204
DynamicMesh * GetDynamicMesh()
Definition mesh.cpp:1041
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:464
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:307
SceneNode * GetSceneNode()
Definition object.cpp:246
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:3162
void AddMeshHandle(MeshObject *handle)
Definition sbs.cpp:3157
Real AmbientG
Definition sbs.h:428
Real AmbientR
Definition sbs.h:428
std::string GetMountPath(std::string filename, std::string &newfilename)
Definition sbs.cpp:3365
Utility * GetUtility()
Definition sbs.cpp:4641
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:2397
bool GetConfigBool(const std::string &key, bool default_value)
Definition sbs.cpp:3273
Real ToRemote(Real local_value)
Definition sbs.cpp:2437
bool DeleteColliders
Definition sbs.h:184
Real AmbientB
Definition sbs.h:428
std::string VerifyFile(const std::string &filename)
Definition sbs.cpp:2946
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:206
Vector3 GetWallExtents(Real altitude, bool get_max)
Definition wall.cpp:310
void DeletePolygons(bool recreate_collider=true)
Definition wall.cpp:144
Vector3 GetPoint(const Vector3 &start, const Vector3 &end)
Definition wall.cpp:294
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