RigsofRods
Soft-body Physics Simulation
Mesh.cpp
Go to the documentation of this file.
1 /*
2 --------------------------------------------------------------------------------
3 This source file is part of Hydrax.
4 Visit ---
5 
6 Copyright (C) 2008 Xavier Vergu�n Gonz�lez <xavierverguin@hotmail.com>
7  <xavyiy@gmail.com>
8 
9 This program is free software; you can redistribute it and/or modify it under
10 the terms of the GNU Lesser General Public License as published by the Free Software
11 Foundation; either version 2 of the License, or (at your option) any later
12 version.
13 
14 This program is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
17 
18 You should have received a copy of the GNU Lesser General Public License along with
19 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
20 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
21 http://www.gnu.org/copyleft/lesser.txt.
22 --------------------------------------------------------------------------------
23 */
24 
25 #include "Mesh.h"
26 
27 #include "Hydrax.h"
28 #include <OgreMatrix4.h>
29 
30 namespace Hydrax
31 {
33  : mHydrax(h)
34  , mCreated(false)
35  , mMesh()
36  , mSubMesh(0)
37  , mEntity(0)
38  , mNumFaces(0)
39  , mNumVertices(0)
40  , mVertexBuffer()
41  , mIndexBuffer()
42  , mSceneNode(0)
43  , mMaterialName("_NULL_")
44  {
45  }
46 
48  {
49  remove();
50  }
51 
52  void Mesh::remove()
53  {
54  if (!mCreated)
55  {
56  return;
57  }
58 
59  mSceneNode->detachAllObjects();
60  mSceneNode->getParentSceneNode()->removeAndDestroyChild(mSceneNode);
61  mSceneNode = 0;
62 
63  Ogre::MeshManager::getSingleton().remove("HydraxMesh");
64  mHydrax->getSceneManager()->destroyEntity(mEntity);
65 
66  mMesh.setNull();
67  mSubMesh = 0;
68  mEntity = 0;
69  mNumFaces = 0;
70  mNumVertices = 0;
71  mVertexBuffer.setNull();
72  mIndexBuffer.setNull();
73  mMaterialName = "_NULL_";
74 
75  mCreated = false;
76  }
77 
79  {
80  if (mCreated)
81  {
82  Ogre::AxisAlignedBox meshBounds;
83 
84  if (Options.MeshSize.Width == 0 && Options.MeshSize.Height == 0)
85  {
86  meshBounds = Ogre::AxisAlignedBox(-1000000, -Options.MeshStrength/2,-1000000,
87  1000000, Options.MeshStrength/2, 1000000);
88  }
89  else
90  {
91  meshBounds = Ogre::AxisAlignedBox(0, -Options.MeshStrength/2, 0,
93  }
94 
95  mMesh->_setBounds(meshBounds);
96  mSceneNode->_updateBounds();
97 
99  {
101  }
102  }
103 
104  mOptions = Options;
105  }
106 
107  void Mesh::setMaterialName(const Ogre::String &MaterialName)
108  {
109  mMaterialName = MaterialName;
110 
111  if (mEntity)
112  {
113  mEntity->setMaterialName(mMaterialName);
114  }
115  }
116 
118  {
119  if (mCreated)
120  {
121  return;
122  }
123 
124  // Create mesh and submesh
125  mMesh = Ogre::MeshManager::getSingleton().createManual("HydraxMesh",
126  Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
127  mSubMesh = mMesh->createSubMesh();
128  mSubMesh->useSharedVertices = false;
129 
130  if (mHydrax->getModule())
131  {
132  if (!mHydrax->getModule()->_createGeometry(this))
133  {
134  _createGeometry();
135  }
136  }
137 
138  // End mesh creation
139  Ogre::AxisAlignedBox meshBounds;
140 
141  if (mOptions.MeshSize.Width == 0 && mOptions.MeshSize.Height == 0)
142  {
143  meshBounds = Ogre::AxisAlignedBox(-1000000, -mOptions.MeshStrength/2,-1000000,
144  1000000, mOptions.MeshStrength/2, 1000000);
145  }
146  else
147  {
148  meshBounds = Ogre::AxisAlignedBox(0, -mOptions.MeshStrength/2, 0,
150  }
151 
152  mMesh->_setBounds(meshBounds);
153  mMesh->load();
154  mMesh->touch();
155 
156  mEntity = mHydrax->getSceneManager()->createEntity("HydraxMeshEnt", "HydraxMesh");
157  mEntity->setMaterialName(mMaterialName);
158  mEntity->setCastShadows(false);
159  mEntity->setRenderQueueGroup(Ogre::RENDER_QUEUE_1);
160 
161  mSceneNode = mHydrax->getSceneManager()->getRootSceneNode()->createChildSceneNode();
162  mSceneNode->showBoundingBox(false);
163  mSceneNode->attachObject(mEntity);
165 
166  mCreated = true;
167  }
168 
170  {
171  int& Complexity = mOptions.MeshComplexity;
172 
173  int numVertices = Complexity*Complexity;
174  int numEle = 6 * (Complexity-1)*(Complexity-1);
175 
176  // Vertex buffers
177  mSubMesh->vertexData = new Ogre::VertexData();
178  mSubMesh->vertexData->vertexStart = 0;
179  mSubMesh->vertexData->vertexCount = numVertices;
180 
181  Ogre::VertexDeclaration* vdecl = mSubMesh->vertexData->vertexDeclaration;
182  Ogre::VertexBufferBinding* vbind = mSubMesh->vertexData->vertexBufferBinding;
183 
184  size_t offset = 0;
185 
186  switch (mOptions.MeshVertexType)
187  {
188  case VT_POS_NORM_UV:
189  {
190  vdecl->addElement(0, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
191  offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
192  vdecl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
193  offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
194  vdecl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES);
195 
196  mVertexBuffer = Ogre::HardwareBufferManager::getSingleton().
197  createVertexBuffer(sizeof(POS_NORM_UV_VERTEX),
198  numVertices,
199  Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY);
200  }
201  break;
202 
203  case VT_POS_NORM:
204  {
205  vdecl->addElement(0, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
206  offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
207  vdecl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
208 
209  mVertexBuffer = Ogre::HardwareBufferManager::getSingleton().
210  createVertexBuffer(sizeof(POS_NORM_VERTEX),
211  numVertices,
212  Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY);
213  }
214  break;
215 
216  case VT_POS_UV:
217  {
218  vdecl->addElement(0, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
219  offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
220  vdecl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES);
221 
222  mVertexBuffer = Ogre::HardwareBufferManager::getSingleton().
223  createVertexBuffer(sizeof(POS_UV_VERTEX),
224  numVertices,
225  Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY);
226  }
227  break;
228 
229  case VT_POS:
230  {
231  vdecl->addElement(0, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
232 
233  mVertexBuffer = Ogre::HardwareBufferManager::getSingleton().
234  createVertexBuffer(sizeof(POS_VERTEX),
235  numVertices,
236  Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY);
237  }
238  break;
239  }
240 
241  vbind->setBinding(0, mVertexBuffer);
242 
243  unsigned int *indexbuffer = new unsigned int[numEle];
244 
245  int i = 0;
246  for(int v=0; v<Complexity-1; v++){
247  for(int u=0; u<Complexity-1; u++){
248  // face 1 |/
249  indexbuffer[i++] = v*Complexity + u;
250  indexbuffer[i++] = v*Complexity + u + 1;
251  indexbuffer[i++] = (v+1)*Complexity + u;
252 
253  // face 2 /|
254  indexbuffer[i++] = (v+1)*Complexity + u;
255  indexbuffer[i++] = v*Complexity + u + 1;
256  indexbuffer[i++] = (v+1)*Complexity + u + 1;
257  }
258  }
259 
260  // Prepare buffer for indices
261  mIndexBuffer =
262  Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
263  Ogre::HardwareIndexBuffer::IT_32BIT,
264  numEle,
265  Ogre::HardwareBuffer::HBU_STATIC, true);
266 
267  mIndexBuffer->
268  writeData(0,
269  mIndexBuffer->getSizeInBytes(),
270  indexbuffer,
271  true);
272 
273  delete []indexbuffer;
274 
275  // Set index buffer for this submesh
276  mSubMesh->indexData->indexBuffer = mIndexBuffer;
277  mSubMesh->indexData->indexStart = 0;
278  mSubMesh->indexData->indexCount = numEle;
279  }
280 
281  bool Mesh::updateGeometry(const int &numVer, void* verArray)
282  {
283  if (numVer != mVertexBuffer->getNumVertices() || !mCreated)
284  {
285  return false;
286  }
287 
288  if (verArray)
289  {
290  mVertexBuffer->
291  writeData(0,
292  mVertexBuffer->getSizeInBytes(),
293  verArray,
294  true);
295  }
296 
297  return true;
298  }
299 
300  bool Mesh::isPointInGrid(const Ogre::Vector2 &Position)
301  {
302  Ogre::AxisAlignedBox WordMeshBox = mEntity->getWorldBoundingBox();
303 
304  // Get our mesh grid rectangle:
305  // c-----------d
306  // | |
307  // | |
308  // | |
309  // a-----------b
310  Ogre::Vector3
311  a = WordMeshBox.getCorner(Ogre::AxisAlignedBox::FAR_LEFT_BOTTOM),
312  b = WordMeshBox.getCorner(Ogre::AxisAlignedBox::FAR_RIGHT_BOTTOM),
313  c = WordMeshBox.getCorner(Ogre::AxisAlignedBox::NEAR_RIGHT_BOTTOM),
314  d = WordMeshBox.getCorner(Ogre::AxisAlignedBox::NEAR_LEFT_BOTTOM);
315 
316  // Transform all corners to Ogre::Vector2 array
317  Ogre::Vector2 Corners2D[4] =
318  {Ogre::Vector2(a.x, a.z),
319  Ogre::Vector2(b.x, b.z),
320  Ogre::Vector2(c.x, c.z),
321  Ogre::Vector2(d.x, d.z)};
322 
323  // Determinate if Position is into our rectangle, we use a line intersection detection
324  // because our mesh rectangle can be rotated, if the number of collisions with the four
325  // segments AB, BC, CD, DA is one, the Position point is into the rectangle, else(if number
326  // of collisions are 0 or 2, the Position point is outside the rectangle.
327  int NumberOfCollisions = 0;
328  // Find a point wich isn't be inside the rectangle
329  Ogre::Vector2 DestPoint = Corners2D[0] + (Corners2D[1]-Corners2D[0])*2;
330  for (int k = 0; k < 3; k++)
331  {
332  if (Math::intersectionOfTwoLines(Corners2D[k], Corners2D[k+1], Position, DestPoint) != Ogre::Vector2::ZERO)
333  {
334  NumberOfCollisions ++;
335  }
336 
337  if (k == 2)
338  {
339  if (Math::intersectionOfTwoLines(Corners2D[3], Corners2D[0], Position, DestPoint) != Ogre::Vector2::ZERO)
340  {
341  NumberOfCollisions ++;
342  }
343  }
344  }
345  if (NumberOfCollisions == 1)
346  {
347  return true;
348  }
349 
350  return false;
351  }
352 
353  Ogre::Vector2 Mesh::getGridPosition(const Ogre::Vector2 &Position)
354  {
355  if (mOptions.MeshSize.Width == 0 && mOptions.MeshSize.Height == 0)
356  {
357  return Position;
358  }
359 
360  if (!isPointInGrid(Position))
361  {
362  return Ogre::Vector2(-1,-1);
363  }
364 
365  Ogre::AxisAlignedBox WordMeshBox = mEntity->getWorldBoundingBox();
366 
367  // Get our mesh grid rectangle: (Only a,b,c corners)
368  // c
369  // |
370  // |
371  // |
372  // a-----------b
373  Ogre::Vector3
374  a = WordMeshBox.getCorner(Ogre::AxisAlignedBox::FAR_LEFT_BOTTOM),
375  b = WordMeshBox.getCorner(Ogre::AxisAlignedBox::FAR_RIGHT_BOTTOM),
376  c = WordMeshBox.getCorner(Ogre::AxisAlignedBox::NEAR_LEFT_BOTTOM);
377 
378  // Transform all corners to Ogre::Vector2 array
379  Ogre::Vector2 Corners2D[3] =
380  {Ogre::Vector2(a.x, a.z),
381  Ogre::Vector2(b.x, b.z),
382  Ogre::Vector2(c.x, c.z)};
383 
384  // Get segments AB and AC
385  Ogre::Vector2 AB = Corners2D[1]-Corners2D[0],
386  AC = Corners2D[2]-Corners2D[0];
387 
388  // Find the X/Y position projecting the Position point to AB and AC segments.
389  Ogre::Vector2 XProjectedPoint = Position-AC,
390  YProjectedPoint = Position-AB;
391 
392  // Fint the intersections points
393  Ogre::Vector2 XPoint = Math::intersectionOfTwoLines(Corners2D[0],Corners2D[1],Position,XProjectedPoint),
394  YPoint = Math::intersectionOfTwoLines(Corners2D[0],Corners2D[2],Position,YProjectedPoint);
395 
396  // Find lengths
397  Ogre::Real ABLength = AB.length(),
398  ACLength = AC.length(),
399  XLength = (XPoint-Corners2D[0]).length(),
400  YLength = (YPoint-Corners2D[0]).length();
401 
402  // Find final x/y grid positions in [0,1] range
403  Ogre::Real XFinal = XLength / ABLength,
404  YFinal = YLength / ACLength;
405 
406  return Ogre::Vector2(XFinal,YFinal);
407  }
408 
409  const Ogre::Vector3 Mesh::getObjectSpacePosition(const Ogre::Vector3& WorldSpacePosition) const
410  {
411  Ogre::Affine3 mWorldMatrix;
412 
413  if (mCreated)
414  {
415  mWorldMatrix = mEntity->getParentSceneNode()->_getFullTransform();
416  }
417  else
418  {
419  Ogre::SceneNode *mTmpSN = new Ogre::SceneNode(0);
420  mTmpSN->setPosition(mHydrax->getPosition());
421 
422  mWorldMatrix = mTmpSN->_getFullTransform();
423 
424  delete mTmpSN;
425  }
426 
427  return mWorldMatrix.inverse()*(WorldSpacePosition);
428  }
429 
430  const Ogre::Vector3 Mesh::getWorldSpacePosition(const Ogre::Vector3& ObjectSpacePosition) const
431  {
432  Ogre::Affine3 mWorldMatrix;
433 
434  if (mCreated)
435  {
436  mWorldMatrix = mEntity->getParentSceneNode()->_getFullTransform();
437  }
438  else
439  {
440  Ogre::SceneNode *mTmpSN = new Ogre::SceneNode(0);
441  mTmpSN->setPosition(mHydrax->getPosition());
442 
443  mWorldMatrix = mTmpSN->_getFullTransform();
444 
445  delete mTmpSN;
446  }
447 
448  //return mWorldMatrix.transformAffine(ObjectSpacePosition);
449  return mWorldMatrix*(ObjectSpacePosition);
450  }
451 }
Hydrax::Mesh::create
void create()
Create our water mesh, geometry, entity, etc...
Definition: Mesh.cpp:117
Hydrax::Mesh::mOptions
Options mOptions
Mesh options.
Definition: Mesh.h:312
Hydrax::Mesh::mSubMesh
Ogre::SubMesh * mSubMesh
Ogre::Submesh pointer.
Definition: Mesh.h:318
Hydrax::Mesh::Options::MeshStrength
float MeshStrength
Water strength.
Definition: Mesh.h:137
Hydrax::Mesh::POS_VERTEX
Vertex struct for position data.
Definition: Mesh.h:76
Hydrax::Mesh::mEntity
Ogre::Entity * mEntity
Ogre::Entity pointer.
Definition: Mesh.h:320
Hydrax::Hydrax::getPosition
const Ogre::Vector3 & getPosition() const
Get water position.
Definition: Hydrax.h:413
Hydrax::Mesh::mMaterialName
Ogre::String mMaterialName
Material name.
Definition: Mesh.h:335
Hydrax::Module::Module::_createGeometry
virtual const bool _createGeometry(Mesh *mMesh) const
Create geometry in module(If special geometry is needed)
Definition: Module.h:117
Hydrax
Definition: CfgFileManager.cpp:28
Hydrax::Mesh::Options::MeshVertexType
VertexType MeshVertexType
Vertex type.
Definition: Mesh.h:139
Hydrax::Mesh::updateGeometry
bool updateGeometry(const int &numVer, void *verArray)
Update geomtry.
Definition: Mesh.cpp:281
Hydrax::Mesh::POS_UV_VERTEX
Vertex struct for position and uv data.
Definition: Mesh.h:68
Hydrax.h
Hydrax::Mesh::Mesh
Mesh(Hydrax *h)
Constructor.
Definition: Mesh.cpp:32
Hydrax::Mesh::mNumFaces
int mNumFaces
Number of faces.
Definition: Mesh.h:322
Hydrax::Math::intersectionOfTwoLines
static Ogre::Vector2 intersectionOfTwoLines(const Ogre::Vector2 &a, const Ogre::Vector2 &b, const Ogre::Vector2 &c, const Ogre::Vector2 &d)
Find the intersection point of two lines.
Definition: Help.cpp:29
Hydrax::Mesh::Options
Base Hydrax mesh options.
Definition: Mesh.h:93
Hydrax::Mesh::mMesh
Ogre::MeshPtr mMesh
Ogre::MeshPtr.
Definition: Mesh.h:316
Hydrax::Mesh::mSceneNode
Ogre::SceneNode * mSceneNode
Ogre::SceneNode pointer.
Definition: Mesh.h:332
Hydrax::Mesh::mNumVertices
int mNumVertices
Number of vertices.
Definition: Mesh.h:324
Hydrax::Mesh::VT_POS_NORM_UV
@ VT_POS_NORM_UV
Definition: Mesh.h:85
Hydrax::Mesh::getGridPosition
Ogre::Vector2 getGridPosition(const Ogre::Vector2 &Position)
Get the [0,1] range x/y grid position from a 2D world space x/z point.
Definition: Mesh.cpp:353
Hydrax::Mesh::setMaterialName
void setMaterialName(const Ogre::String &MaterialName)
Set mesh material.
Definition: Mesh.cpp:107
Hydrax::Hydrax::getModule
Module::Module * getModule()
Get our Hydrax::Module::Module.
Definition: Hydrax.h:381
Hydrax::Mesh::VT_POS_UV
@ VT_POS_UV
Definition: Mesh.h:87
Hydrax::Hydrax::getSceneManager
Ogre::SceneManager * getSceneManager()
Get scene manager.
Definition: Hydrax.h:309
Hydrax::Mesh::getObjectSpacePosition
const Ogre::Vector3 getObjectSpacePosition(const Ogre::Vector3 &WorldSpacePosition) const
Get the object-space position from world-space position.
Definition: Mesh.cpp:409
Hydrax::Mesh::_createGeometry
void _createGeometry()
Create mesh geometry.
Definition: Mesh.cpp:169
Hydrax::Mesh::remove
void remove()
Remove all resources.
Definition: Mesh.cpp:52
Hydrax::Mesh::mHydrax
Hydrax * mHydrax
Hydrax pointer.
Definition: Mesh.h:338
Hydrax::Mesh::VT_POS
@ VT_POS
Definition: Mesh.h:88
Hydrax::Mesh::Options::MeshComplexity
int MeshComplexity
Mesh complexity.
Definition: Mesh.h:133
Hydrax::Mesh::Options::MeshSize
Size MeshSize
Grid size (X/Z) world space.
Definition: Mesh.h:135
Hydrax::Mesh::mCreated
bool mCreated
Is _createGeometry() called?
Definition: Mesh.h:314
Mesh.h
Hydrax::Size::Width
int Width
Width value.
Definition: Help.h:43
Hydrax::Mesh::mVertexBuffer
Ogre::HardwareVertexBufferSharedPtr mVertexBuffer
Vertex buffer.
Definition: Mesh.h:327
Hydrax::Mesh::POS_NORM_VERTEX
Vertex struct for position and normals data.
Definition: Mesh.h:60
Hydrax::Mesh::isPointInGrid
bool isPointInGrid(const Ogre::Vector2 &Position)
Get if a Position point is inside of the grid.
Definition: Mesh.cpp:300
Hydrax::Mesh::getWorldSpacePosition
const Ogre::Vector3 getWorldSpacePosition(const Ogre::Vector3 &ObjectSpacePosition) const
Get the world-space position from object-space position.
Definition: Mesh.cpp:430
Hydrax::Mesh::setOptions
void setOptions(const Options &Options)
Update options.
Definition: Mesh.cpp:78
Hydrax::Mesh::~Mesh
~Mesh()
Destructor.
Definition: Mesh.cpp:47
Hydrax::Mesh::VT_POS_NORM
@ VT_POS_NORM
Definition: Mesh.h:86
Hydrax::Mesh::POS_NORM_UV_VERTEX
Vertex struct for position, normals and uv data.
Definition: Mesh.h:51
Hydrax::Size::Height
int Height
Height value.
Definition: Help.h:45
Hydrax::Mesh::mIndexBuffer
Ogre::HardwareIndexBufferSharedPtr mIndexBuffer
Index buffer.
Definition: Mesh.h:329