MezzanineEngine 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
meshmanager.cpp
1 // © Copyright 2010 - 2014 BlackTopp Studios Inc.
2 /* This file is part of The Mezzanine Engine.
3 
4  The Mezzanine Engine is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  The Mezzanine Engine is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with The Mezzanine Engine. If not, see <http://www.gnu.org/licenses/>.
16 */
17 /* The original authors have included a copy of the license specified above in the
18  'Docs' folder. See 'gpl.txt'
19 */
20 /* We welcome the use of the Mezzanine engine to anyone, including companies who wish to
21  Build professional software and charge for their product.
22 
23  However there are some practical restrictions, so if your project involves
24  any of the following you should contact us and we will try to work something
25  out:
26  - DRM or Copy Protection of any kind(except Copyrights)
27  - Software Patents You Do Not Wish to Freely License
28  - Any Kind of Linking to Non-GPL licensed Works
29  - Are Currently In Violation of Another Copyright Holder's GPL License
30  - If You want to change our code and not add a few hundred MB of stuff to
31  your distribution
32 
33  These and other limitations could cause serious legal problems if you ignore
34  them, so it is best to simply contact us or the Free Software Foundation, if
35  you have any questions.
36 
37  Joseph Toppi - toppij@gmail.com
38  John Blackwood - makoenergy02@gmail.com
39 */
40 #ifndef _graphicsmeshmanager_cpp
41 #define _graphicsmeshmanager_cpp
42 
43 #include "vector2.h"
44 #include "Graphics/meshmanager.h"
45 #include "Graphics/mesh.h"
46 
47 #include <Ogre.h>
48 
49 namespace Mezzanine
50 {
51  template<> Graphics::MeshManager* Singleton<Graphics::MeshManager>::SingletonPtr = NULL;
52 
53  namespace Graphics
54  {
56  {
57  }
58 
60  {
61  /// @todo This class currently doesn't initialize anything from XML, if that changes this constructor needs to be expanded.
62  }
63 
65  {
66  this->Deinitialize();
68  }
69 
70  ///////////////////////////////////////////////////////////////////////////////
71  // Generic Mesh Utility
72 
73  Mesh* MeshManager::GetMesh(const String& MeshName)
74  {
75  MeshIterator lit = this->LoadedMeshes.find(MeshName);
76  if(lit != this->LoadedMeshes.end())
77  return (*lit).second;
78  MeshIterator git = this->GeneratedMeshes.find(MeshName);
79  if(git != this->GeneratedMeshes.end())
80  return (*git).second;
81  return NULL;
82  }
83 
85  {
87  this->UnloadAllLoadedMeshes();
88  }
89 
90  ///////////////////////////////////////////////////////////////////////////////
91  // Non-Generated Mesh Management
92 
93  Mesh* MeshManager::LoadMesh(const String& MeshName, const String& Group)
94  {
95  MeshIterator it = this->LoadedMeshes.find(MeshName);
96  if( it != this->LoadedMeshes.end() )
97  return (*it).second;
98  Mesh* Loaded = new Mesh(Ogre::MeshManager::getSingleton().load(MeshName,Group));
99  this->LoadedMeshes[MeshName] = Loaded;
100  return Loaded;
101  }
102 
103  void MeshManager::UnloadMesh(const String& MeshName)
104  {
105  MeshIterator it = this->LoadedMeshes.find(MeshName);
106  if( it == this->LoadedMeshes.end() )
107  return;
108  Ogre::MeshManager::getSingleton().unload(MeshName);
109  delete (*it).second;
110  this->LoadedMeshes.erase(it);
111  }
112 
114  {
115  return this->LoadedMeshes.size();
116  }
117 
119  {
120  for( MeshIterator it = this->LoadedMeshes.begin() ; it != this->LoadedMeshes.end() ; it++ )
121  {
122  delete (*it).second;
123  }
124  this->LoadedMeshes.clear();
125  Ogre::MeshManager::getSingleton().unloadAll();
126  }
127 
128  ///////////////////////////////////////////////////////////////////////////////
129  // Generated Mesh Management
130 
132  {
133  return this->GeneratedMeshes.size();
134  }
135 
137  {
138  MeshIterator it = this->GeneratedMeshes.find(MeshName);
139  if(it == this->GeneratedMeshes.end())
140  return;
141  Ogre::MeshManager::getSingletonPtr()->remove((*it).second->GetName());
142  delete (*it).second;
143  this->GeneratedMeshes.erase(it);
144  return;
145  }
146 
148  {
149  for( MeshIterator it = this->GeneratedMeshes.begin() ; it != this->GeneratedMeshes.end() ; it++ )
150  {
151  Ogre::MeshManager::getSingletonPtr()->remove((*it).second->GetName());
152  delete (*it).second;
153  }
154  this->GeneratedMeshes.clear();
155  }
156 
157  ///////////////////////////////////////////////////////////////////////////////
158  // Mesh Generation
159 
160  Mesh* MeshManager::CreateBoxMesh(const String& MeshName, const String& MaterialName, const Vector3& HalfExtents)
161  {
162  Vector3 Half = HalfExtents;
163  Ogre::MaterialPtr TheMaterial = Ogre::MaterialManager::getSingleton().getByName(MaterialName);
164  String GroupName = TheMaterial->getGroup();
165 
166  Ogre::ManualObject* box = new Ogre::ManualObject("TempMan");
167  box->begin(MaterialName);
168  //Front
169  box->position(-Half.X,-Half.Y,Half.Z); box->normal(0,0,1); box->textureCoord(0,1);
170  box->position(Half.X,-Half.Y,Half.Z); box->normal(0,0,1); box->textureCoord(1,1);
171  box->position(Half.X,Half.Y,Half.Z); box->normal(0,0,1); box->textureCoord(1,0);
172  box->position(-Half.X,Half.Y,Half.Z); box->normal(0,0,1); box->textureCoord(0,0);
173  //Back
174  box->position(Half.X,-Half.Y,-Half.Z); box->normal(0,0,-1); box->textureCoord(0,1);
175  box->position(-Half.X,-Half.Y,-Half.Z); box->normal(0,0,-1); box->textureCoord(1,1);
176  box->position(-Half.X,Half.Y,-Half.Z); box->normal(0,0,-1); box->textureCoord(1,0);
177  box->position(Half.X,Half.Y,-Half.Z); box->normal(0,0,-1); box->textureCoord(0,0);
178  //Left
179  box->position(-Half.X,-Half.Y,-Half.Z); box->normal(-1,0,0); box->textureCoord(0,1);
180  box->position(-Half.X,-Half.Y,Half.Z); box->normal(-1,0,0); box->textureCoord(1,1);
181  box->position(-Half.X,Half.Y,Half.Z); box->normal(-1,0,0); box->textureCoord(1,0);
182  box->position(-Half.X,Half.Y,-Half.Z); box->normal(-1,0,0); box->textureCoord(0,0);
183  //Right
184  box->position(Half.X,-Half.Y,Half.Z); box->normal(1,0,0); box->textureCoord(0,1);
185  box->position(Half.X,-Half.Y,-Half.Z); box->normal(1,0,0); box->textureCoord(1,1);
186  box->position(Half.X,Half.Y,-Half.Z); box->normal(1,0,0); box->textureCoord(1,0);
187  box->position(Half.X,Half.Y,Half.Z); box->normal(1,0,0); box->textureCoord(0,0);
188  //Top
189  box->position(-Half.X,Half.Y,Half.Z); box->normal(0,1,0); box->textureCoord(0,1);
190  box->position(Half.X,Half.Y,Half.Z); box->normal(0,1,0); box->textureCoord(1,1);
191  box->position(Half.X,Half.Y,-Half.Z); box->normal(0,1,0); box->textureCoord(1,0);
192  box->position(-Half.X,Half.Y,-Half.Z); box->normal(0,1,0); box->textureCoord(0,0);
193  //Bottom
194  box->position(-Half.X,-Half.Y,-Half.Z); box->normal(0,-1,0); box->textureCoord(0,1);
195  box->position(Half.X,-Half.Y,-Half.Z); box->normal(0,-1,0); box->textureCoord(1,1);
196  box->position(Half.X,-Half.Y,Half.Z); box->normal(0,-1,0); box->textureCoord(1,0);
197  box->position(-Half.X,-Half.Y,Half.Z); box->normal(0,-1,0); box->textureCoord(0,0);
198 
199  box->triangle(0,1,2); box->triangle(0,2,3); //Front
200  box->triangle(4,5,6); box->triangle(4,6,7); //Back
201  box->triangle(8,9,10); box->triangle(8,10,11); //Left
202  box->triangle(12,13,14); box->triangle(12,14,15); //Right
203  box->triangle(16,17,18); box->triangle(16,18,19); //Top
204  box->triangle(20,21,22); box->triangle(20,22,23); //Bottom
205 
206  box->end();
207  Ogre::MeshPtr boxmesh = box->convertToMesh(MeshName, GroupName);
208  boxmesh->_setBounds(Ogre::AxisAlignedBox(-Half.X,-Half.Y,-Half.Z,Half.X,Half.Y,Half.Z));
209  Real FirstCheck = Half.X > Half.Y ? Half.X : Half.Y;
210  Real Largest = FirstCheck > Half.Z ? FirstCheck : Half.Z;
211  boxmesh->_setBoundingSphereRadius(1.4 * Largest);
212  Mesh* NewMesh = new Mesh(boxmesh);
213  this->GeneratedMeshes[MeshName] = NewMesh;
214  delete box;
215  return NewMesh;
216  }
217 
218  Mesh* MeshManager::CreateBoxMesh(const String& MeshName, const ColourValue& Colour, const Vector3& HalfExtents)
219  {
220  String MatName(MeshName+"Mat");
221  this->CreateColouredMaterial(MatName,Colour);
222  return this->CreateBoxMesh(MeshName,MatName,HalfExtents);
223  }
224 
225  Mesh* MeshManager::CreateCylinderMesh(const String& MeshName, const String& MaterialName, const Vector3& HalfExtents, const Vector3& AxisOrientation, const Whole& CircleRes, const Whole& Segments)
226  {
227  /// Start of MIT(Ogre Proceadural) License ///
228  Ogre::Quaternion RotationModifier;
229  if(AxisOrientation == Vector3::Unit_X())
230  RotationModifier = Ogre::Quaternion(Ogre::Radian(0.5),Ogre::Vector3::UNIT_Z);
231  else if( AxisOrientation == Vector3::Unit_Y() )
232  RotationModifier = Ogre::Quaternion(1,0,0,0);
233  else if( AxisOrientation == Vector3::Unit_Z() )
234  RotationModifier = Ogre::Quaternion(Ogre::Radian(0.5),Ogre::Vector3::UNIT_X);
235 
236  Vector3 Half = HalfExtents;
237  Ogre::MaterialPtr TheMaterial = Ogre::MaterialManager::getSingleton().getByName(MaterialName);
238  String GroupName = TheMaterial->getGroup();
239 
240  Real deltaAngle = (Ogre::Math::TWO_PI / CircleRes);
241  Real deltaHeight = (Half.Y * 2)/(Real)Segments;
242  Real radius = Half.X;
243  Whole offset = 0;
244 
245  Ogre::ManualObject* cylinder = new Ogre::ManualObject("TempMan");
246  cylinder->begin(MaterialName);
247 
248  for( Whole i = 0 ; i <= Segments ; i++ )
249  {
250  for( Whole j = 0 ; j < CircleRes ; j++ )
251  {
252  Real x0 = radius * cosf(j*deltaAngle);
253  Real z0 = radius * sinf(j*deltaAngle);
254  cylinder->position( RotationModifier * Ogre::Vector3(x0, (i*deltaHeight) - Half.Y, z0) );
255  cylinder->normal( RotationModifier * Ogre::Vector3(x0,0,z0).normalisedCopy() );
256  cylinder->textureCoord(j/(Real)CircleRes, i/(Real)Segments);
257 
258  if(i != Segments)
259  {
260  /// @todo These if/elses aren't really a long term solution
261  /// as they won't work for any more then 1 segment. This needs to be addressed.
262  if(offset + CircleRes == CircleRes * 2)
263  cylinder->index(CircleRes);
264  else
265  cylinder->index(offset + CircleRes + 1);
266 
267  cylinder->index(offset);
268  cylinder->index(offset + CircleRes);
269 
270  if(offset + CircleRes == CircleRes * 2)
271  cylinder->index(0);
272  else
273  cylinder->index(offset + CircleRes + 1);
274 
275  cylinder->index(offset + 1);
276  cylinder->index(offset);
277  }
278  offset++;
279  }
280  }
281 
282  //low cap
283  Whole centerIndex = offset;
284  cylinder->position( RotationModifier * Ogre::Vector3(0,-Half.Y,0) );
285  cylinder->normal( RotationModifier * Ogre::Vector3::NEGATIVE_UNIT_Y );
286  cylinder->textureCoord(0,1);
287  offset++;
288  for( Whole j = 0 ; j <= CircleRes ; j++ )
289  {
290  Real x0 = radius * cosf(j*deltaAngle);
291  Real z0 = radius * sinf(j*deltaAngle);
292 
293  cylinder->position( RotationModifier * Ogre::Vector3(x0,-Half.Y, z0) );
294  cylinder->normal( RotationModifier * Ogre::Vector3::NEGATIVE_UNIT_Y );
295  cylinder->textureCoord(j/(Real)CircleRes,0.0);
296  if( j != CircleRes )
297  {
298  cylinder->index(centerIndex);
299  cylinder->index(offset);
300  cylinder->index(offset+1);
301  }
302  offset++;
303  }
304 
305  // high cap
306  centerIndex = offset;
307  cylinder->position( RotationModifier * Ogre::Vector3(0,Half.Y,0) );
308  cylinder->normal( RotationModifier * Ogre::Vector3::UNIT_Y );
309  cylinder->textureCoord(0,0);
310  offset++;
311  for(Whole j = 0 ; j <= CircleRes ; j++ )
312  {
313  Real x0 = radius * cosf(j*deltaAngle);
314  Real z0 = radius * sinf(j*deltaAngle);
315 
316  cylinder->position( RotationModifier * Ogre::Vector3(x0, Half.Y, z0) );
317  cylinder->normal( RotationModifier * Ogre::Vector3::UNIT_Y );
318  cylinder->textureCoord(j/(Real)CircleRes,1);
319  if( j != CircleRes )
320  {
321  cylinder->index(centerIndex);
322  cylinder->index(offset+1);
323  cylinder->index(offset);
324  }
325  offset++;
326  }
327 
328  cylinder->end();
329  Ogre::MeshPtr cylindermesh = cylinder->convertToMesh(MeshName, GroupName);
330  cylindermesh->_setBounds(Ogre::AxisAlignedBox(-Half.X,-Half.Y,-Half.Z,Half.X,Half.Y,Half.Z));
331  Real FirstCheck = Half.X > Half.Y ? Half.X : Half.Y;
332  Real Largest = FirstCheck > Half.Z ? FirstCheck : Half.Z;
333  cylindermesh->_setBoundingSphereRadius(1.4 * Largest);
334  Mesh* NewMesh = new Mesh(cylindermesh);
335  this->GeneratedMeshes[MeshName] = NewMesh;
336  delete cylinder;
337  return NewMesh;
338  /// End of MIT(Ogre Proceadural) License ///
339  }
340 
341  Mesh* MeshManager::CreateCylinderMesh(const String& MeshName, const ColourValue& Colour, const Vector3& HalfExtents, const Vector3& AxisOrientation, const Whole& CircleRes, const Whole& Segments)
342  {
343  String MatName(MeshName+"Mat");
344  this->CreateColouredMaterial(MatName,Colour);
345  return this->CreateCylinderMesh(MeshName,MatName,HalfExtents,AxisOrientation,CircleRes,Segments);
346  }
347 
348  Mesh* MeshManager::CreateSphereMesh(const String& MeshName, const String& MaterialName, const Real& Radius, const Real& Rings, const Real& Segments)
349  {
350  Ogre::MaterialPtr TheMaterial = Ogre::MaterialManager::getSingleton().getByName(MaterialName);
351  String GroupName = TheMaterial->getGroup();
352 
353  Real RingAngle = (Ogre::Math::PI / Rings);
354  Real SegAngle = (2 * Ogre::Math::PI / Segments);
355  Whole VertIndex = 0;
356 
357  Ogre::ManualObject* sphere = new Ogre::ManualObject("TempMan");
358  sphere->begin(MaterialName);
359 
360  for( Whole ring = 0 ; ring <= Rings ; ring++ ) {
361  Real r0 = Radius * sinf (ring * RingAngle);
362  Real y0 = Radius * cosf (ring * RingAngle);
363 
364  // Generate the group of segments for the current ring
365  for( Whole seg = 0 ; seg <= Segments ; seg++ ) {
366  Real x0 = r0 * sinf(seg * SegAngle);
367  Real z0 = r0 * cosf(seg * SegAngle);
368 
369  // Add one vertex to the strip which makes up the sphere
370  sphere->position( x0, y0, z0);
371  sphere->normal(Ogre::Vector3(x0, y0, z0).normalisedCopy());
372  sphere->textureCoord((Real) seg / (Real) Segments, (Real) ring / (Real) Rings);
373 
374  if (ring != Rings) {
375  // each vertex (except the last) has six indicies pointing to it
376  sphere->index(VertIndex + Segments + 1);
377  sphere->index(VertIndex);
378  sphere->index(VertIndex + Segments);
379  sphere->index(VertIndex + Segments + 1);
380  sphere->index(VertIndex + 1);
381  sphere->index(VertIndex);
382  VertIndex++;
383  }
384  }
385  }
386 
387  sphere->end();
388  Ogre::MeshPtr spheremesh = sphere->convertToMesh(MeshName, GroupName);
389  spheremesh->_setBounds(Ogre::AxisAlignedBox(-Radius,-Radius,-Radius,Radius,Radius,Radius));
390  spheremesh->_setBoundingSphereRadius(Radius);
391  Mesh* NewMesh = new Mesh(spheremesh);
392  this->GeneratedMeshes[MeshName] = NewMesh;
393  delete sphere;
394  return NewMesh;
395  }
396 
397  Mesh* MeshManager::CreateSphereMesh(const String& MeshName, const ColourValue& Colour, const Real& Radius, const Real& Rings, const Real& Segments)
398  {
399  String MatName(MeshName+"Mat");
400  this->CreateColouredMaterial(MatName,Colour);
401  return this->CreateSphereMesh(MeshName,MatName,Radius,Rings,Segments);
402  }
403 
404  namespace{
405  /// @internal
406  /// @brief used to created simple manual shapes in a quick and dirty way
407  struct IdealPoint
408  {
409  Vector3 Vertex;
410  Vector3 Normal;
411  Vector2 TextureCoord;
412 
413  IdealPoint(Vector3 Vertex_, Vector3 Normal_, Vector2 TextureCoord_)
414  {
415  Vertex=Vertex_;
416  Normal=Normal_;
417  TextureCoord=TextureCoord_;
418  }
419  };
420  }
421 
422  Mesh* MeshManager::CreateBoxCornerMesh(const String& MeshName, const String& MaterialName, const Vector3& HalfExtents, const Real& BoxThickness)
423  {
424  Vector3 Half = HalfExtents;
425  Vector3 Full = HalfExtents * 2;
426 
427  Real Length = 0.0;
428  Real FirstSizeCheck = HalfExtents.X < HalfExtents.Y ? HalfExtents.X : HalfExtents.Y;
429  Real Smallest = FirstSizeCheck < HalfExtents.Z ? FirstSizeCheck : HalfExtents.Z;
430  if(Smallest * 2 <= FirstSizeCheck) Length = Smallest * 0.5;
431  else Length = Smallest * 0.25;
432  Ogre::MaterialPtr TheMaterial = Ogre::MaterialManager::getSingleton().getByName(MaterialName);
433  String GroupName = TheMaterial->getGroup();
434 
435  Ogre::ManualObject* boxcorner = new Ogre::ManualObject("TempMan");
436  boxcorner->begin(MaterialName);
437 
438  // ©reate a list of data we can play around with
439  std::vector<IdealPoint> IdealShape; //Vertex //Normal //textureCoord
440  // Forward Face // 0 /
441  IdealShape.push_back( IdealPoint( Vector3(-Half.X,Half.Y,Half.Z), Vector3(0,0,1), Vector2(0,0) ));
442  IdealShape.push_back( IdealPoint( Vector3(-Half.X,Half.Y - Length,Half.Z), Vector3(0,0,1), Vector2(0,0.5) ));
443  IdealShape.push_back( IdealPoint( Vector3(-Half.X + BoxThickness,Half.Y - Length,Half.Z), Vector3(0,0,1), Vector2(BoxThickness / Full.X,0.5) ));
444  IdealShape.push_back( IdealPoint( Vector3(-Half.X + BoxThickness,Half.Y - BoxThickness,Half.Z), Vector3(0,0,1), Vector2(BoxThickness / Full.X,BoxThickness / Full.Y) ));
445  IdealShape.push_back( IdealPoint( Vector3(-Half.X + Length,Half.Y - BoxThickness,Half.Z), Vector3(0,0,1), Vector2(0.5,BoxThickness / Full.Y) ));
446  IdealShape.push_back( IdealPoint( Vector3(-Half.X + Length,Half.Y,Half.Z), Vector3(0,0,1), Vector2(0.5,0) ));
447  // Upward Face // 6 */
448  IdealShape.push_back( IdealPoint( Vector3(-Half.X,Half.Y,Half.Z), Vector3(0,1,0), Vector2(0,1) ));
449  IdealShape.push_back( IdealPoint( Vector3(-Half.X + Length,Half.Y,Half.Z), Vector3(0,1,0), Vector2(0.5,1) ));
450  IdealShape.push_back( IdealPoint( Vector3(-Half.X + Length,Half.Y,Half.Z - BoxThickness), Vector3(0,1,0), Vector2(0.5,1 - (BoxThickness / Full.Y)) ));
451  IdealShape.push_back( IdealPoint( Vector3(-Half.X + BoxThickness,Half.Y,Half.Z - BoxThickness), Vector3(0,1,0), Vector2(BoxThickness / Full.X,1 - (BoxThickness / Full.Y)) ));
452  IdealShape.push_back( IdealPoint( Vector3(-Half.X + BoxThickness,Half.Y,Half.Z - Length), Vector3(0,1,0), Vector2(BoxThickness / Full.X,0.5) ));
453  IdealShape.push_back( IdealPoint( Vector3(-Half.X,Half.Y,Half.Z - Length), Vector3(0,1,0), Vector2(0,0.5) ));
454  // Left Face // 12 */
455  IdealShape.push_back( IdealPoint( Vector3(-Half.X,Half.Y,Half.Z), Vector3(-1,0,0), Vector2(1,0) ));
456  IdealShape.push_back( IdealPoint( Vector3(-Half.X,Half.Y,Half.Z - Length), Vector3(-1,0,0), Vector2(0.5,0) ));
457  IdealShape.push_back( IdealPoint( Vector3(-Half.X,Half.Y - BoxThickness,Half.Z - Length), Vector3(-1,0,0), Vector2(0.5,BoxThickness / Full.Y) ));
458  IdealShape.push_back( IdealPoint( Vector3(-Half.X,Half.Y - BoxThickness,Half.Z - BoxThickness), Vector3(-1,0,0), Vector2(1 - (BoxThickness / Full.X),BoxThickness / Full.Y) ));
459  IdealShape.push_back( IdealPoint( Vector3(-Half.X,Half.Y - Length,Half.Z - BoxThickness), Vector3(-1,0,0), Vector2(1 - (BoxThickness / Full.X),0.5) ));
460  IdealShape.push_back( IdealPoint( Vector3(-Half.X,Half.Y - Length,Half.Z), Vector3(-1,0,0), Vector2(1,0.5) ));
461  // Backward Faces // 18 */
462  IdealShape.push_back( IdealPoint( Vector3(-Half.X + Length,Half.Y,Half.Z - BoxThickness), Vector3(0,0,-1), Vector2(0.5,0) ));
463  IdealShape.push_back( IdealPoint( Vector3(-Half.X + Length,Half.Y - BoxThickness,Half.Z - BoxThickness), Vector3(0,0,-1), Vector2(0.5,BoxThickness / Full.Y) ));
464  IdealShape.push_back( IdealPoint( Vector3(-Half.X + BoxThickness,Half.Y - BoxThickness,Half.Z - BoxThickness), Vector3(0,0,-1), Vector2(1 - (BoxThickness / Full.X),BoxThickness / Full.Y) ));
465  IdealShape.push_back( IdealPoint( Vector3(-Half.X + BoxThickness,Half.Y,Half.Z - BoxThickness), Vector3(0,0,-1), Vector2(1 - (BoxThickness / Full.X),0) ));
466  IdealShape.push_back( IdealPoint( Vector3(-Half.X + BoxThickness,Half.Y,Half.Z - Length), Vector3(0,0,-1), Vector2(1 - (BoxThickness / Full.X),0) ));
467  IdealShape.push_back( IdealPoint( Vector3(-Half.X + BoxThickness,Half.Y - BoxThickness,Half.Z - Length), Vector3(0,0,-1), Vector2(1 - (BoxThickness / Full.X),BoxThickness / Full.Y) ));
468  IdealShape.push_back( IdealPoint( Vector3(-Half.X,Half.Y - BoxThickness,Half.Z - Length), Vector3(0,0,-1), Vector2(1,BoxThickness / Full.Y) ));
469  IdealShape.push_back( IdealPoint( Vector3(-Half.X,Half.Y,Half.Z - Length), Vector3(0,0,-1), Vector2(1,0) ));
470  IdealShape.push_back( IdealPoint( Vector3(-Half.X + BoxThickness,Half.Y - BoxThickness,Half.Z - BoxThickness), Vector3(0,0,-1), Vector2(1 - (BoxThickness / Full.X),BoxThickness / Full.Y) ));
471  IdealShape.push_back( IdealPoint( Vector3(-Half.X + BoxThickness,Half.Y - Length,Half.Z - BoxThickness), Vector3(0,0,-1), Vector2(1 - (BoxThickness / Full.X),0.5) ));
472  IdealShape.push_back( IdealPoint( Vector3(-Half.X,Half.Y - Length,Half.Z - BoxThickness), Vector3(0,0,-1), Vector2(1,0.5) ));
473  IdealShape.push_back( IdealPoint( Vector3(-Half.X,Half.Y - BoxThickness,Half.Z - BoxThickness), Vector3(0,0,-1), Vector2(1,BoxThickness / Full.Y) ));
474  // Downward Faces // 30 */
475  IdealShape.push_back( IdealPoint( Vector3(-Half.X + BoxThickness,Half.Y - BoxThickness,Half.Z), Vector3(0,-1,0), Vector2(BoxThickness / Full.X,0) ));
476  IdealShape.push_back( IdealPoint( Vector3(-Half.X + BoxThickness,Half.Y - BoxThickness,Half.Z - BoxThickness), Vector3(0,-1,0), Vector2(BoxThickness / Full.X,BoxThickness / Full.Y) ));
477  IdealShape.push_back( IdealPoint( Vector3(-Half.X + Length,Half.Y - BoxThickness,Half.Z - BoxThickness), Vector3(0,-1,0), Vector2(0.5,BoxThickness / Full.Y) ));
478  IdealShape.push_back( IdealPoint( Vector3(-Half.X + Length,Half.Y - BoxThickness,Half.Z), Vector3(0,-1,0), Vector2(0.5,0) ));
479  IdealShape.push_back( IdealPoint( Vector3(-Half.X,Half.Y - Length,Half.Z), Vector3(0,-1,0), Vector2(0,0) ));
480  IdealShape.push_back( IdealPoint( Vector3(-Half.X,Half.Y - Length,Half.Z - BoxThickness), Vector3(0,-1,0), Vector2(0,BoxThickness / Full.Y) ));
481  IdealShape.push_back( IdealPoint( Vector3(-Half.X + BoxThickness,Half.Y - Length,Half.Z - BoxThickness), Vector3(0,-1,0), Vector2(BoxThickness / Full.X,BoxThickness / Full.Y) ));
482  IdealShape.push_back( IdealPoint( Vector3(-Half.X + BoxThickness,Half.Y - Length,Half.Z), Vector3(0,-1,0), Vector2(BoxThickness / Full.X,0) ));
483  IdealShape.push_back( IdealPoint( Vector3(-Half.X,Half.Y - BoxThickness,Half.Z - BoxThickness), Vector3(0,-1,0), Vector2(0,BoxThickness / Full.Y) ));
484  IdealShape.push_back( IdealPoint( Vector3(-Half.X,Half.Y - BoxThickness,Half.Z - Length), Vector3(0,-1,0), Vector2(0,0.5) ));
485  IdealShape.push_back( IdealPoint( Vector3(-Half.X + BoxThickness,Half.Y - BoxThickness,Half.Z - Length), Vector3(0,-1,0), Vector2(BoxThickness / Full.X,0.5) ));
486  IdealShape.push_back( IdealPoint( Vector3(-Half.X + BoxThickness,Half.Y - BoxThickness,Half.Z - BoxThickness), Vector3(0,-1,0), Vector2(BoxThickness / Full.X,BoxThickness / Full.Y) ));
487  // Right Faces // 42 */
488  IdealShape.push_back( IdealPoint( Vector3(-Half.X + BoxThickness,Half.Y,Half.Z - BoxThickness), Vector3(1,0,0), Vector2(BoxThickness / Full.X,0) ));
489  IdealShape.push_back( IdealPoint( Vector3(-Half.X + BoxThickness,Half.Y - BoxThickness,Half.Z - BoxThickness), Vector3(1,0,0), Vector2(BoxThickness / Full.X,BoxThickness / Full.Y) ));
490  IdealShape.push_back( IdealPoint( Vector3(-Half.X + BoxThickness,Half.Y - BoxThickness,Half.Z - Length), Vector3(1,0,0), Vector2(0.5,BoxThickness / Full.Y) ));
491  IdealShape.push_back( IdealPoint( Vector3(-Half.X + BoxThickness,Half.Y,Half.Z - Length), Vector3(1,0,0), Vector2(0.5,0) ));
492  IdealShape.push_back( IdealPoint( Vector3(-Half.X + Length,Half.Y,Half.Z), Vector3(1,0,0), Vector2(0,0) ));
493  IdealShape.push_back( IdealPoint( Vector3(-Half.X + Length,Half.Y - BoxThickness,Half.Z), Vector3(1,0,0), Vector2(0,BoxThickness / Full.Y) ));
494  IdealShape.push_back( IdealPoint( Vector3(-Half.X + Length,Half.Y - BoxThickness,Half.Z - BoxThickness), Vector3(1,0,0), Vector2(BoxThickness / Full.X,BoxThickness / Full.Y) ));
495  IdealShape.push_back( IdealPoint( Vector3(-Half.X + Length,Half.Y,Half.Z - BoxThickness), Vector3(1,0,0), Vector2(BoxThickness / Full.X,0) ));
496  IdealShape.push_back( IdealPoint( Vector3(-Half.X + BoxThickness,Half.Y - BoxThickness,Half.Z), Vector3(1,0,0), Vector2(0,BoxThickness / Full.Y) ));
497  IdealShape.push_back( IdealPoint( Vector3(-Half.X + BoxThickness,Half.Y - Length,Half.Z), Vector3(1,0,0), Vector2(0,0.5) ));
498  IdealShape.push_back( IdealPoint( Vector3(-Half.X + BoxThickness,Half.Y - Length,Half.Z - BoxThickness), Vector3(1,0,0), Vector2(BoxThickness / Full.X,0.5) ));
499  IdealShape.push_back( IdealPoint( Vector3(-Half.X + BoxThickness,Half.Y - BoxThickness,Half.Z - BoxThickness), Vector3(1,0,0), Vector2(BoxThickness / Full.X,BoxThickness / Full.Y) ));
500 
501  // Each of the flips we need to make
502  std::vector<Vector3> Flips;
503  Flips.push_back(Vector3(1,1,1));
504  Flips.push_back(Vector3(1,1,-1));
505  Flips.push_back(Vector3(1,-1,1));
506  Flips.push_back(Vector3(-1,1,1));
507  Flips.push_back(Vector3(1,-1,-1));
508  Flips.push_back(Vector3(-1,1,-1));
509  Flips.push_back(Vector3(-1,-1,1));
510  Flips.push_back(Vector3(-1,-1,-1));
511 
512  // flip this set of points against the list of flips
513  for( std::vector<Vector3>::iterator CurrentFlip=Flips.begin() ; CurrentFlip!=Flips.end() ; ++CurrentFlip )
514  {
515  for(std::vector<IdealPoint>::iterator CurrentVertex=IdealShape.begin(); CurrentVertex!=IdealShape.end(); ++CurrentVertex)
516  {
517  boxcorner->position( (CurrentVertex->Vertex * *CurrentFlip).GetOgreVector3() );
518  boxcorner->normal( (CurrentVertex->Normal * *CurrentFlip).GetOgreVector3() );
519  boxcorner->textureCoord( CurrentVertex->TextureCoord.GetOgreVector2() );
520  }
521  }
522 
523  // Create Index's
524  for( Whole FlipCount = 0 ; FlipCount<Flips.size() ; ++FlipCount )
525  {
526  Whole ShapeIndex = FlipCount*IdealShape.size();
527 
528  // Top-Left-Front Forward Face
529  if(1==Flips.at(FlipCount).Z) // draw them in backward order if this shape is flipped on the Z axis
530  {
531  //Forward Face Unflipped
532  boxcorner->triangle(0+ShapeIndex,1+ShapeIndex,2+ShapeIndex); // These things could be replaced by a series of loops, but this was simpler
533  boxcorner->triangle(0+ShapeIndex,2+ShapeIndex,3+ShapeIndex);
534  boxcorner->triangle(0+ShapeIndex,3+ShapeIndex,4+ShapeIndex);
535  boxcorner->triangle(0+ShapeIndex,4+ShapeIndex,5+ShapeIndex);
536  //Backward Faces Unflipped
537  boxcorner->triangle(18+ShapeIndex,19+ShapeIndex,20+ShapeIndex);
538  boxcorner->triangle(18+ShapeIndex,20+ShapeIndex,21+ShapeIndex);
539  boxcorner->triangle(22+ShapeIndex,23+ShapeIndex,24+ShapeIndex);
540  boxcorner->triangle(22+ShapeIndex,24+ShapeIndex,25+ShapeIndex);
541  boxcorner->triangle(26+ShapeIndex,27+ShapeIndex,28+ShapeIndex);
542  boxcorner->triangle(26+ShapeIndex,28+ShapeIndex,29+ShapeIndex);
543  }else{
544  //Forward Face Flipped
545  boxcorner->triangle(0+ShapeIndex,1+ShapeIndex,2+ShapeIndex);
546  boxcorner->triangle(0+ShapeIndex,3+ShapeIndex,4+ShapeIndex);
547  boxcorner->triangle(0+ShapeIndex,2+ShapeIndex,3+ShapeIndex);
548  boxcorner->triangle(0+ShapeIndex,4+ShapeIndex,5+ShapeIndex);
549  //Backward Faces Flipped
550  boxcorner->triangle(26+ShapeIndex,28+ShapeIndex,29+ShapeIndex);
551  boxcorner->triangle(26+ShapeIndex,27+ShapeIndex,28+ShapeIndex);
552  boxcorner->triangle(22+ShapeIndex,24+ShapeIndex,25+ShapeIndex);
553  boxcorner->triangle(22+ShapeIndex,23+ShapeIndex,24+ShapeIndex);
554  boxcorner->triangle(18+ShapeIndex,20+ShapeIndex,21+ShapeIndex);
555  boxcorner->triangle(18+ShapeIndex,19+ShapeIndex,20+ShapeIndex);
556  }
557 
558  if(1==Flips.at(FlipCount).Y) // draw them in backward order if this shape is flipped on the Y axis
559  {
560  // Upward Face Unflipped
561  boxcorner->triangle(6+ShapeIndex,7+ShapeIndex,8+ShapeIndex);
562  boxcorner->triangle(6+ShapeIndex,8+ShapeIndex,9+ShapeIndex);
563  boxcorner->triangle(6+ShapeIndex,9+ShapeIndex,10+ShapeIndex);
564  boxcorner->triangle(6+ShapeIndex,10+ShapeIndex,11+ShapeIndex);
565  // Downward Faces Unflipped
566  boxcorner->triangle(30+ShapeIndex,31+ShapeIndex,32+ShapeIndex);
567  boxcorner->triangle(30+ShapeIndex,32+ShapeIndex,33+ShapeIndex);
568  boxcorner->triangle(34+ShapeIndex,35+ShapeIndex,36+ShapeIndex);
569  boxcorner->triangle(34+ShapeIndex,36+ShapeIndex,37+ShapeIndex);
570  boxcorner->triangle(38+ShapeIndex,39+ShapeIndex,40+ShapeIndex);
571  boxcorner->triangle(38+ShapeIndex,40+ShapeIndex,41+ShapeIndex);
572  }else{
573  // Upward Face Flipped
574  boxcorner->triangle(6+ShapeIndex,10+ShapeIndex,11+ShapeIndex);
575  boxcorner->triangle(6+ShapeIndex,9+ShapeIndex,10+ShapeIndex);
576  boxcorner->triangle(6+ShapeIndex,8+ShapeIndex,9+ShapeIndex);
577  boxcorner->triangle(6+ShapeIndex,7+ShapeIndex,8+ShapeIndex);
578  // Downward Faces Flipped
579  boxcorner->triangle(38+ShapeIndex,40+ShapeIndex,41+ShapeIndex);
580  boxcorner->triangle(38+ShapeIndex,39+ShapeIndex,40+ShapeIndex);
581  boxcorner->triangle(34+ShapeIndex,36+ShapeIndex,37+ShapeIndex);
582  boxcorner->triangle(34+ShapeIndex,35+ShapeIndex,36+ShapeIndex);
583  boxcorner->triangle(30+ShapeIndex,32+ShapeIndex,33+ShapeIndex);
584  boxcorner->triangle(30+ShapeIndex,31+ShapeIndex,32+ShapeIndex);
585  }
586 
587  if(1==Flips.at(FlipCount).X) // draw them in backward order if this shape is flipped on the X axis
588  {
589  // Left Face Unflipped
590  boxcorner->triangle(12+ShapeIndex,13+ShapeIndex,14+ShapeIndex);
591  boxcorner->triangle(12+ShapeIndex,14+ShapeIndex,15+ShapeIndex);
592  boxcorner->triangle(12+ShapeIndex,15+ShapeIndex,16+ShapeIndex);
593  boxcorner->triangle(12+ShapeIndex,16+ShapeIndex,17+ShapeIndex);
594  // Right Faces Unflipped
595  boxcorner->triangle(42+ShapeIndex,43+ShapeIndex,44+ShapeIndex);
596  boxcorner->triangle(42+ShapeIndex,44+ShapeIndex,45+ShapeIndex);
597  boxcorner->triangle(46+ShapeIndex,47+ShapeIndex,48+ShapeIndex);
598  boxcorner->triangle(46+ShapeIndex,48+ShapeIndex,49+ShapeIndex);
599  boxcorner->triangle(50+ShapeIndex,51+ShapeIndex,52+ShapeIndex);
600  boxcorner->triangle(50+ShapeIndex,52+ShapeIndex,53+ShapeIndex);
601  }else{
602  // Left Face Unflipped
603  boxcorner->triangle(12+ShapeIndex,16+ShapeIndex,17+ShapeIndex);
604  boxcorner->triangle(12+ShapeIndex,15+ShapeIndex,16+ShapeIndex);
605  boxcorner->triangle(12+ShapeIndex,14+ShapeIndex,15+ShapeIndex);
606  boxcorner->triangle(12+ShapeIndex,13+ShapeIndex,14+ShapeIndex);
607  // Right Faces Unflipped
608  boxcorner->triangle(50+ShapeIndex,52+ShapeIndex,53+ShapeIndex);
609  boxcorner->triangle(50+ShapeIndex,51+ShapeIndex,52+ShapeIndex);
610  boxcorner->triangle(46+ShapeIndex,48+ShapeIndex,49+ShapeIndex);
611  boxcorner->triangle(46+ShapeIndex,47+ShapeIndex,48+ShapeIndex);
612  boxcorner->triangle(42+ShapeIndex,44+ShapeIndex,45+ShapeIndex);
613  boxcorner->triangle(42+ShapeIndex,43+ShapeIndex,44+ShapeIndex);
614  }
615  }
616 
617  boxcorner->end();
618  Ogre::MeshPtr boxcornermesh = boxcorner->convertToMesh(MeshName, GroupName);
619  boxcornermesh->_setBounds(Ogre::AxisAlignedBox(-Half.X,-Half.Y,-Half.Z,Half.X,Half.Y,Half.Z));
620  Real FirstCheck = Half.X > Half.Y ? Half.X : Half.Y;
621  Real Largest = FirstCheck > Half.Z ? FirstCheck : Half.Z;
622  boxcornermesh->_setBoundingSphereRadius(1.4 * Largest);
623  Mesh* NewMesh = new Mesh(boxcornermesh);
624  this->GeneratedMeshes[MeshName] = NewMesh;
625  delete boxcorner;
626  return NewMesh;
627  }
628 
629  Mesh* MeshManager::CreateBoxCornerMesh(const String& MeshName, const ColourValue& Colour, const Vector3& HalfExtents, const Real& BoxThickness)
630  {
631  String MatName(MeshName+"Mat");
632  this->CreateColouredMaterial(MatName,Colour);
633  return this->CreateBoxCornerMesh(MeshName,MatName,HalfExtents,BoxThickness);
634  }
635 
636  Mesh* MeshManager::CreateMeshFromShape(const String& MeshName, const String& MaterialName, Physics::CollisionShape* Shape)
637  {
638  return NULL;
639  }
640 
641  ///////////////////////////////////////////////////////////////////////////////
642  // Material Utilities - Until we can get a Material Manager
643 
644  const String& MeshManager::CreateColouredMaterial(const String& MatName, const ColourValue& Colour, const String& Group)
645  {
646  Ogre::ResourceManager::ResourceCreateOrRetrieveResult Result = Ogre::MaterialManager::getSingletonPtr()->createOrRetrieve(MatName, Group.empty() ? Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME : Group);
647  Ogre::MaterialPtr NewMaterial = static_cast<Ogre::MaterialPtr>(Result.first);
648  NewMaterial->setReceiveShadows(false);
649  Ogre::Pass* pass = NewMaterial->getTechnique(0)->getPass(0);
650  pass->setCullingMode(Ogre::CULL_NONE);
651  pass->setDepthCheckEnabled(true);
652  pass->setDepthWriteEnabled(false);
653  pass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
654  pass->setAmbient(Colour.GetOgreColourValue());
655  pass->setDiffuse(Colour.GetOgreColourValue());
656  NewMaterial->prepare();
657  NewMaterial->load();
658  return MatName;
659  }
660 
661  ///////////////////////////////////////////////////////////////////////////////
662  // Utility
663 
665  { this->Initialized = true; }
666 
668  { this->Initialized = false; }
669 
670  ///////////////////////////////////////////////////////////////////////////////
671  // Type Identifier Methods
672 
674  { return ManagerBase::MT_MeshManager; }
675 
677  { return "DefaultMeshManager"; }
678 
679  ///////////////////////////////////////////////////////////////////////////////
680  // DefaultMeshManagerFactory Methods
681 
683  {
684  }
685 
687  {
688  }
689 
691  {
692  return "DefaultMeshManager";
693  }
694 
696  {
698  {
699  /// @todo Add something to log a warning that the manager exists and was requested to be constructed when we have a logging manager set up.
701  }else return new MeshManager();
702  }
703 
705  {
707  {
708  /// @todo Add something to log a warning that the manager exists and was requested to be constructed when we have a logging manager set up.
710  }else return new MeshManager(XMLNode);
711  }
712 
714  {
715  delete ToBeDestroyed;
716  }
717  }//Graphics
718 }//Mezzanine
719 
720 #endif