Rigs of Rods 2023.09
Soft-body Physics Simulation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
Mesh.cpp
Go to the documentation of this file.
1/*
2--------------------------------------------------------------------------------
3This source file is part of Hydrax.
4Visit ---
5
6Copyright (C) 2008 Xavier Vergu�n Gonz�lez <xavierverguin@hotmail.com>
7 <xavyiy@gmail.com>
8
9This program is free software; you can redistribute it and/or modify it under
10the terms of the GNU Lesser General Public License as published by the Free Software
11Foundation; either version 2 of the License, or (at your option) any later
12version.
13
14This program is distributed in the hope that it will be useful, but WITHOUT
15ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
17
18You should have received a copy of the GNU Lesser General Public License along with
19this program; if not, write to the Free Software Foundation, Inc., 59 Temple
20Place - Suite 330, Boston, MA 02111-1307, USA, or go to
21http://www.gnu.org/copyleft/lesser.txt.
22--------------------------------------------------------------------------------
23*/
24
25#include "Mesh.h"
26
27#include "Hydrax.h"
28#include <OgreMatrix4.h>
29
30namespace 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
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.reset();
67 mSubMesh = 0;
68 mEntity = 0;
69 mNumFaces = 0;
70 mNumVertices = 0;
71 mVertexBuffer.reset();
72 mIndexBuffer.reset();
73 mMaterialName = "_NULL_";
74
75 mCreated = false;
76 }
77
79 {
80 if (mCreated)
81 {
82 Ogre::AxisAlignedBox meshBounds;
83
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
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 {
135 }
136 }
137
138 // End mesh creation
139 Ogre::AxisAlignedBox meshBounds;
140
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
262 Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
263 Ogre::HardwareIndexBuffer::IT_32BIT,
264 numEle,
265 Ogre::HardwareBuffer::HBU_STATIC, true);
266
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 {
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 {
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}
const Ogre::Vector3 & getPosition() const
Get water position.
Definition Hydrax.h:413
Module::Module * getModule()
Get our Hydrax::Module::Module.
Definition Hydrax.h:381
Ogre::SceneManager * getSceneManager()
Get scene manager.
Definition Hydrax.h:309
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
void _createGeometry()
Create mesh geometry.
Definition Mesh.cpp:169
Ogre::SubMesh * mSubMesh
Ogre::Submesh pointer.
Definition Mesh.h:318
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
void create()
Create our water mesh, geometry, entity, etc...
Definition Mesh.cpp:117
const Ogre::Vector3 getObjectSpacePosition(const Ogre::Vector3 &WorldSpacePosition) const
Get the object-space position from world-space position.
Definition Mesh.cpp:409
Hydrax * mHydrax
Hydrax pointer.
Definition Mesh.h:338
~Mesh()
Destructor.
Definition Mesh.cpp:47
Mesh(Hydrax *h)
Constructor.
Definition Mesh.cpp:32
void setMaterialName(const Ogre::String &MaterialName)
Set mesh material.
Definition Mesh.cpp:107
void remove()
Remove all resources.
Definition Mesh.cpp:52
@ VT_POS_NORM_UV
Definition Mesh.h:85
@ VT_POS_UV
Definition Mesh.h:87
@ VT_POS_NORM
Definition Mesh.h:86
Ogre::String mMaterialName
Material name.
Definition Mesh.h:335
Ogre::Entity * mEntity
Ogre::Entity pointer.
Definition Mesh.h:320
Ogre::SceneNode * mSceneNode
Ogre::SceneNode pointer.
Definition Mesh.h:332
void setOptions(const Options &Options)
Update options.
Definition Mesh.cpp:78
Ogre::HardwareVertexBufferSharedPtr mVertexBuffer
Vertex buffer.
Definition Mesh.h:327
Options mOptions
Mesh options.
Definition Mesh.h:312
bool updateGeometry(const int &numVer, void *verArray)
Update geomtry.
Definition Mesh.cpp:281
Ogre::HardwareIndexBufferSharedPtr mIndexBuffer
Index buffer.
Definition Mesh.h:329
int mNumFaces
Number of faces.
Definition Mesh.h:322
bool mCreated
Is _createGeometry() called?
Definition Mesh.h:314
int mNumVertices
Number of vertices.
Definition Mesh.h:324
Ogre::MeshPtr mMesh
Ogre::MeshPtr.
Definition Mesh.h:316
const Ogre::Vector3 getWorldSpacePosition(const Ogre::Vector3 &ObjectSpacePosition) const
Get the world-space position from object-space position.
Definition Mesh.cpp:430
bool isPointInGrid(const Ogre::Vector2 &Position)
Get if a Position point is inside of the grid.
Definition Mesh.cpp:300
virtual const bool _createGeometry(Mesh *mMesh) const
Create geometry in module(If special geometry is needed)
Definition Module.h:117
Base Hydrax mesh options.
Definition Mesh.h:94
VertexType MeshVertexType
Vertex type.
Definition Mesh.h:139
Size MeshSize
Grid size (X/Z) world space.
Definition Mesh.h:135
float MeshStrength
Water strength.
Definition Mesh.h:137
int MeshComplexity
Mesh complexity.
Definition Mesh.h:133
Vertex struct for position, normals and uv data.
Definition Mesh.h:52
Vertex struct for position and normals data.
Definition Mesh.h:61
Vertex struct for position and uv data.
Definition Mesh.h:69
Vertex struct for position data.
Definition Mesh.h:77
int Height
Height value.
Definition Help.h:45
int Width
Width value.
Definition Help.h:43