1
///////////////////////////////////////////////////////////////////////////////
2
/// @file OgreEntityCollisionShape.cpp
3
/// @brief <TODO: insert file description here>
5
/// @author The OgreOpcode Team @date 28-05-2005
7
///////////////////////////////////////////////////////////////////////////////
9
/// This file is part of OgreOpcode.
11
/// A lot of the code is based on the Nebula Opcode Collision module, see docs/Nebula_license.txt
13
/// OgreOpcode is free software; you can redistribute it and/or
14
/// modify it under the terms of the GNU Lesser General Public
15
/// License as published by the Free Software Foundation; either
16
/// version 2.1 of the License, or (at your option) any later version.
18
/// OgreOpcode is distributed in the hope that it will be useful,
19
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
20
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21
/// Lesser General Public License for more details.
23
/// You should have received a copy of the GNU Lesser General Public
24
/// License along with OgreOpcode; if not, write to the Free Software
25
/// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27
///////////////////////////////////////////////////////////////////////////////
28
#include "OgreOpcodeExports.h"
29
#include "OgreEntityCollisionShape.h"
30
#include "OgreCollisionReporter.h"
31
#include "OgreCollisionManager.h"
32
#include "OgreOpcodeMath.h"
33
#include "OgreOpcodeUtils.h"
38
//------------------------------------------------------------------------
39
EntityCollisionShape::EntityCollisionShape(const Ogre::String& name)
40
: ICollisionShape(name),
46
//------------------------------------------------------------------------
47
EntityCollisionShape::~EntityCollisionShape()
49
if (mEntity && mEntity->hasSkeleton())
51
#ifdef BUILD_AGAINST_AZATHOTH
52
mEntity->removeSoftwareSkinningRequest(false);
54
mEntity->removeSoftwareAnimationRequest(false);
59
// Note that unlike PtrCollisionShape which creates a node, mParentNode is used
60
// as a reference to the Entity's parent SceneNode. We are not responsible for cleanup
64
//------------------------------------------------------------------------
65
///////////////////////////////////////////////////////////////////////////////
66
/// Counts how many indices (faces) and vertices an entity contains.
67
/// @param[in] entity Entity to count its data.
68
/// @param[out] index_count Number of indices.
69
/// @param[out] vertex_count Number of vertices.
70
/// @author Yavin from the Ogre4J team
71
///////////////////////////////////////////////////////////////////////////////
72
void EntityCollisionShape::countIndicesAndVertices(Entity * entity, size_t & index_count, size_t & vertex_count)
74
// Mesh * mesh = entity->getMesh().getPointer();
76
#ifdef BUILD_AGAINST_AZATHOTH
77
bool hwSkinning = entity->isHardwareSkinningEnabled();
79
bool hwSkinning = entity->isHardwareAnimationEnabled();
82
bool added_shared = false;
86
// Calculate how many vertices and indices we're going to need
87
for ( size_t i = 0; i < entity->getNumSubEntities(); ++i)
89
SubEntity* subEntity = entity->getSubEntity(i);
90
if (subEntity->isVisible()) {
91
SubMesh* submesh = subEntity->getSubMesh();
93
// We only need to add the shared vertices once
94
if(submesh->useSharedVertices)
98
vertex_count += submesh->parent->sharedVertexData->vertexCount;
104
vertex_count += submesh->vertexData->vertexCount;
108
index_count += submesh->indexData->indexCount;
114
//------------------------------------------------------------------------
115
//////////////////////////////////////////////////////////////////////////
116
/// Converts mesh vertex and face data into simple float arrays.
117
/// If the buffer parameters are null then that data is not converted.
118
/// @param[in] entity Entity to extract data from.
119
/// @param[out] vertexBuf Target vertex data array (can be null).
120
/// @param[in] size_t vertex_count Number of vertices.
121
/// @param[out] faceData Target face data array (can be null).
122
/// @param[int] index_count Number of indices.
123
/// @author Yavin from the Ogre4J team
124
//////////////////////////////////////////////////////////////////////////
125
void EntityCollisionShape::convertMeshData(Entity * entity,
126
float * vertexBuf, size_t vertex_count,
127
size_t * faceBuf, size_t index_count)
129
//---------------------------------------------------------------------
131
//---------------------------------------------------------------------
132
// MeshPtr mesh = entity->getMesh();
133
bool added_shared = false;
134
size_t current_offset = 0;
135
size_t shared_offset = 0;
136
size_t next_offset = 0;
137
size_t index_offset = 0;
140
bool useSoftwareBlendingVertices = entity->hasSkeleton();
142
if (useSoftwareBlendingVertices)
144
entity->_updateAnimation();
147
// Run through the submeshes again, adding the data into the arrays
148
for ( size_t i = 0; i < entity->getNumSubEntities(); ++i)
150
SubEntity* subEntity = entity->getSubEntity(i);
151
if (subEntity->isVisible()) {
152
SubMesh* submesh = subEntity->getSubMesh();
153
bool useSharedVertices = submesh->useSharedVertices;
157
//----------------------------------------------------------------
159
//----------------------------------------------------------------
160
const VertexData * vertex_data;
161
if(useSoftwareBlendingVertices)
162
#ifdef BUILD_AGAINST_AZATHOTH
163
vertex_data = useSharedVertices ? entity->_getSharedBlendedVertexData() : entity->getSubEntity(i)->_getBlendedVertexData();
165
vertex_data = useSharedVertices ? entity->_getSkelAnimVertexData() : entity->getSubEntity(i)->_getSkelAnimVertexData();
168
vertex_data = useSharedVertices ? submesh->parent->sharedVertexData : submesh->vertexData;
170
if((!useSharedVertices)||(useSharedVertices && !added_shared))
172
if(useSharedVertices)
175
shared_offset = current_offset;
178
const VertexElement* posElem =
179
vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
181
HardwareVertexBufferSharedPtr vbuf =
182
vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());
184
unsigned char* vertex =
185
static_cast<unsigned char*>(vbuf->lock(HardwareBuffer::HBL_READ_ONLY));
187
// There is _no_ baseVertexPointerToElement() which takes an Ogre::Real or a double
188
// as second argument. So make it float, to avoid trouble when Ogre::Real is
189
// comiled/typedefed as double:
192
#ifdef BUILD_AGAINST_AZATHOTH
193
if (useSoftwareBlendingVertices)
195
// Blended bone data is computed in world space.
196
// Opcode expects data in local coordinates.
197
Matrix4 xform = entity->_getParentNodeFullTransform().inverse();
199
for( size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize())
201
posElem->baseVertexPointerToElement(vertex, &pReal);
202
Vector3 v = Vector3(pReal[0],pReal[1],pReal[2]);
204
size_t n = current_offset*3 + j*3;
205
vertexBuf[n + 0] = v[0];
206
vertexBuf[n + 1] = v[1];
207
vertexBuf[n + 2] = v[2];
212
for( size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize())
214
posElem->baseVertexPointerToElement(vertex, &pReal);
215
size_t n = current_offset*3 + j*3;
216
vertexBuf[n + 0] = pReal[0];
217
vertexBuf[n + 1] = pReal[1];
218
vertexBuf[n + 2] = pReal[2];
223
for( size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize())
225
posElem->baseVertexPointerToElement(vertex, &pReal);
227
size_t n = current_offset*3 + j*3;
229
vertexBuf[n + 0] = pReal[0];
230
vertexBuf[n + 1] = pReal[1];
231
vertexBuf[n + 2] = pReal[2];
236
next_offset += vertex_data->vertexCount;
242
//----------------------------------------------------------------
244
//----------------------------------------------------------------
245
IndexData* index_data = submesh->indexData;
246
size_t numTris = index_data->indexCount / 3;
247
HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
249
bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IT_32BIT);
251
uint32 *pLong = static_cast<uint32*>(ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
252
uint16* pShort = reinterpret_cast<uint16*>(pLong);
255
size_t offset = (submesh->useSharedVertices)? shared_offset : current_offset;
257
if ( use32bitindexes )
259
for ( size_t k = 0; k < numTris*3; ++k)
261
faceBuf[index_offset++] = pLong[k] + static_cast<int>(offset);
266
for ( size_t k = 0; k < numTris*3; ++k)
268
faceBuf[index_offset++] = static_cast<int>(pShort[k]) + static_cast<int>(offset);
275
current_offset = next_offset;
280
//------------------------------------------------------------------------
281
/// <TODO: insert function description here>
282
/// @param [in, out] ent Entity * <TODO: insert parameter description here>
283
/// @return bool <TODO: insert return value description here>
284
bool EntityCollisionShape::load(Entity* ent)
287
assert(!mVertexBuf && !mFaceBuf);
290
if (mEntity->hasSkeleton())
292
#ifdef BUILD_AGAINST_AZATHOTH
293
mEntity->addSoftwareSkinningRequest(false);
295
mEntity->addSoftwareAnimationRequest(false);
299
mParentNode = mEntity->getParentSceneNode();
300
mFullTransform = mEntity->getParentSceneNode()->_getFullTransform();
301
//mParentNode->getWorldTransforms(&mFullTransform);
305
//------------------------------------------------------------------------
306
/// <TODO: insert function description here>
307
/// @return bool <TODO: insert return value description here>
308
bool EntityCollisionShape::rebuild()
312
// NOTE: Assuming presence or absence of skeleton hasn't changed!
314
size_t vertex_count = 0;
315
size_t index_count = 0;
316
countIndicesAndVertices(mEntity, index_count, vertex_count);
318
// Re-Allocate space for the vertices and indices
319
if (mVertexBuf && numVertices != vertex_count) {
320
delete [] mVertexBuf;
323
if (mFaceBuf && numFaces != index_count/3) {
329
mVertexBuf = new float[vertex_count * 3];
331
mFaceBuf = new size_t[index_count];
333
if (index_count > 0 && vertex_count > 0) {
334
convertMeshData(mEntity, mVertexBuf, vertex_count, mFaceBuf, index_count );
336
numFaces = index_count / 3;
337
numVertices = vertex_count;
339
opcMeshAccess.SetNbTriangles(numFaces);
340
opcMeshAccess.SetNbVertices(numVertices);
341
opcMeshAccess.SetPointers((IceMaths::IndexedTriangle*)mFaceBuf, (IceMaths::Point*)mVertexBuf);
342
//opcMeshAccess.SetStrides(sizeof(int) * 3, sizeof(float) * 3);
344
return _rebuildFromCachedData();
350
//------------------------------------------------------------------------
351
/// <TODO: insert function description here>
352
/// @return bool <TODO: insert return value description here>
353
bool EntityCollisionShape::refit()
355
// bail if we don't need to refit
356
if ( mShapeIsStatic )
359
assert(mEntity && mVertexBuf);
362
size_t vertex_count = 0;
363
size_t index_count = 0;
364
countIndicesAndVertices(mEntity, index_count, vertex_count);
365
assert(numVertices == vertex_count);
368
if (numVertices > 0) {
369
convertMeshData(mEntity, mVertexBuf, numVertices);
371
return _refitToCachedData();
376
//------------------------------------------------------------------------
377
/// <TODO: insert function description here>
378
/// @return bool <TODO: insert return value description here>
379
bool EntityCollisionShape::_refitToCachedData()
381
assert(mEntity && mVertexBuf);
384
if (!opcModel.Refit())
386
LogManager::getSingleton().logMessage(
387
"OgreOpcode::EntityCollisionShape::_refitToCachedData(): OPCODE Quick refit not possible with the given tree type.");
388
// Backup plan -- rebuild full tree
389
opcMeshAccess.SetPointers((IceMaths::IndexedTriangle*)mFaceBuf, (IceMaths::Point*)mVertexBuf);
390
Opcode::OPCODECREATE opcc;
391
_prepareOpcodeCreateParams(opcc);
392
opcModel.Build(opcc);
402
//------------------------------------------------------------------------
403
/// <TODO: insert function description here>
404
/// @return bool <TODO: insert return value description here>
405
bool EntityCollisionShape::_rebuildFromCachedData()
407
assert(mEntity && mVertexBuf && mFaceBuf);
409
Opcode::OPCODECREATE opcc;
410
_prepareOpcodeCreateParams(opcc);
411
opcModel.Build(opcc);
419
//------------------------------------------------------------------------
420
/// <TODO: insert function description here>
421
void EntityCollisionShape::createDummyNode()
425
mDummyNode = CollisionManager::getSingletonPtr()->getSceneManager()->getRootSceneNode()->createChildSceneNode(getName());
426
mDummyNode->attachObject(mEntity);
427
mDummyCreated = true;
433
//------------------------------------------------------------------------