[solved] Retrieve correct vertices data from animated mesh
-
megatema
- Halfling
- Posts: 43
- Joined: Fri Mar 09, 2007 12:59 pm
- Location: Saint-Petersburg, Russia
- x 2
[solved] Retrieve correct vertices data from animated mesh
How can I retrieve vertices and indices data from animated mesh? I tried to use raycast algorithm (http://www.ogre3d.org/phpBB2/viewtopic.php?t=23440), but vertices and indices arrays don’t update while animation playing.
Last edited by megatema on Mon Jun 18, 2007 11:31 am, edited 1 time in total.
-
jacmoe
- OGRE Retired Moderator

- Posts: 20570
- Joined: Thu Jan 22, 2004 10:13 am
- Location: Denmark
- x 179
The article covers that. For animated meshes, you have to grab the data whenever it animates.
Look at OgreOpcode to see how we do that.
Look at OgreOpcode to see how we do that.
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
-
megatema
- Halfling
- Posts: 43
- Joined: Fri Mar 09, 2007 12:59 pm
- Location: Saint-Petersburg, Russia
- x 2
Hmmm…jacmoe wrote:The article covers that. For animated meshes, you have to grab the data whenever it animates.
Look at OgreOpcode to see how we do that.
Code: Select all
void CMainApplication::getMeshInformation(const Ogre::MeshPtr mesh,
size_t &vertex_count,
Ogre::Vector3* &vertices,
size_t &index_count,
unsigned long* &indices,
const Ogre::Vector3 &position,
const Ogre::Quaternion &orient,
const Ogre::Vector3 &scale)
{
bool added_shared = false;
size_t current_offset = 0;
size_t shared_offset = 0;
size_t next_offset = 0;
size_t index_offset = 0;
vertex_count = index_count = 0;
// Calculate how many vertices and indices we're going to need
for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
{
Ogre::SubMesh* submesh = mesh->getSubMesh( i );
// We only need to add the shared vertices once
if(submesh->useSharedVertices)
{
if( !added_shared )
{
vertex_count += mesh->sharedVertexData->vertexCount;
added_shared = true;
}
}
else
{
vertex_count += submesh->vertexData->vertexCount;
}
// Add the indices
index_count += submesh->indexData->indexCount;
}
// Allocate space for the vertices and indices
vertices = new Ogre::Vector3[vertex_count];
indices = new unsigned long[index_count];
added_shared = false;
// Run through the submeshes again, adding the data into the arrays
for ( unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
{
Ogre::SubMesh* submesh = mesh->getSubMesh(i);
Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData;
if((!submesh->useSharedVertices)||(submesh->useSharedVertices && !added_shared))
{
if(submesh->useSharedVertices)
{
added_shared = true;
shared_offset = current_offset;
}
const Ogre::VertexElement* posElem =
vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
Ogre::HardwareVertexBufferSharedPtr vbuf =
vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());
unsigned char* vertex =
static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
// There is _no_ baseVertexPointerToElement() which takes an Ogre::Real or a double
// as second argument. So make it float, to avoid trouble when Ogre::Real will
// be comiled/typedefed as double:
// Ogre::Real* pReal;
float* pReal;
//toLogEx("\nMesh name: %s",mesh->getName().c_str());
for( size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize())
{
posElem->baseVertexPointerToElement(vertex, &pReal);
Ogre::Vector3 pt(pReal[0], pReal[1], pReal[2]);
vertices[current_offset + j] = (orient * (pt * scale)) + position;
/*toLogEx("\n%d: %.2f %.2f %.2f",j,
vertices[current_offset + j].x,
vertices[current_offset + j].y,
vertices[current_offset + j].z);*/
}
vbuf->unlock();
next_offset += vertex_data->vertexCount;
}
Ogre::IndexData* index_data = submesh->indexData;
size_t numTris = index_data->indexCount / 3;
Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
unsigned long* pLong = static_cast<unsigned long*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong);
size_t offset = (submesh->useSharedVertices)? shared_offset : current_offset;
if ( use32bitindexes )
{
for ( size_t k = 0; k < numTris*3; ++k)
{
indices[index_offset++] = pLong[k] + static_cast<unsigned long>(offset);
}
}
else
{
for ( size_t k = 0; k < numTris*3; ++k)
{
indices[index_offset++] = static_cast<unsigned long>(pShort[k]) +
static_cast<unsigned long>(offset);
}
}
ibuf->unlock();
current_offset = next_offset;
}
}-
jacmoe
- OGRE Retired Moderator

- Posts: 20570
- Joined: Thu Jan 22, 2004 10:13 am
- Location: Denmark
- x 179
If you're using animated meshes using hardware skinning, you will need to tell Ogre to generate skeletal animation vertex data in software, otherwise it won't.
This is for performance reasons.
You start by issuing this command:
Then use this:
Do not forget to remove the software animation request when done:
This is for performance reasons.
You start by issuing this command:
Code: Select all
mEntity->addSoftwareAnimationRequest(false);
Code: Select all
//------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
/// Counts how many indices (faces) and vertices an entity contains.
/// @param[in] entity Entity to count its data.
/// @param[out] index_count Number of indices.
/// @param[out] vertex_count Number of vertices.
/// @author Yavin from the Ogre4J team
///////////////////////////////////////////////////////////////////////////////
void MeshCollisionShape::countIndicesAndVertices(Entity * entity, size_t & index_count, size_t & vertex_count)
{
Mesh * mesh = entity->getMesh().getPointer();
bool added_shared = false;
index_count = 0;
vertex_count = 0;
// Calculate how many vertices and indices we're going to need
for ( unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
{
SubMesh* submesh = mesh->getSubMesh( i );
// We only need to add the shared vertices once
if(submesh->useSharedVertices)
{
if( !added_shared )
{
vertex_count += mesh->sharedVertexData->vertexCount;
added_shared = true;
}
}
else
{
vertex_count += submesh->vertexData->vertexCount;
}
// Add the indices
index_count += submesh->indexData->indexCount;
}
}
//------------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
/// Converts mesh vertex and face data into simple float arrays.
/// If the buffer parameters are null then that data is not converted.
/// @param[in] entity Entity to extract data from.
/// @param[out] vertexBuf Target vertex data array (can be null).
/// @param[in] size_t vertex_count Number of vertices.
/// @param[out] faceData Target face data array (can be null).
/// @param[int] index_count Number of indices.
/// @author Yavin from the Ogre4J team
//////////////////////////////////////////////////////////////////////////
void MeshCollisionShape::convertMeshData(Entity * entity,
float * vertexBuf, size_t vertex_count,
size_t * faceBuf, size_t index_count)
{
//---------------------------------------------------------------------
// CONVERT MESH DATA
//---------------------------------------------------------------------
MeshPtr mesh = entity->getMesh();
bool added_shared = false;
size_t current_offset = 0;
size_t shared_offset = 0;
size_t next_offset = 0;
size_t index_offset = 0;
int numOfSubs = 0;
bool useSoftwareBlendingVertices = entity->hasSkeleton();
if (useSoftwareBlendingVertices)
{
entity->_updateAnimation();
}
// Run through the submeshes again, adding the data into the arrays
for ( size_t i = 0; i < mesh->getNumSubMeshes(); ++i)
{
SubMesh* submesh = mesh->getSubMesh(i);
bool useSharedVertices = submesh->useSharedVertices;
if (vertexBuf)
{
//----------------------------------------------------------------
// GET VERTEXDATA
//----------------------------------------------------------------
const VertexData * vertex_data;
if(useSoftwareBlendingVertices)
vertex_data = useSharedVertices ? entity->_getSkelAnimVertexData() : entity->getSubEntity(i)->_getSkelAnimVertexData();
else
vertex_data = useSharedVertices ? mesh->sharedVertexData : submesh->vertexData;
if((!useSharedVertices)||(useSharedVertices && !added_shared))
{
if(useSharedVertices)
{
added_shared = true;
shared_offset = current_offset;
}
const VertexElement* posElem =
vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
HardwareVertexBufferSharedPtr vbuf =
vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());
unsigned char* vertex =
static_cast<unsigned char*>(vbuf->lock(HardwareBuffer::HBL_READ_ONLY));
// There is _no_ baseVertexPointerToElement() which takes an Ogre::Real or a double
// as second argument. So make it float, to avoid trouble when Ogre::Real is
// comiled/typedefed as double:
float* pReal;
for( size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize())
{
posElem->baseVertexPointerToElement(vertex, &pReal);
size_t n = current_offset*3 + j*3;
vertexBuf[n + 0] = pReal[0];
vertexBuf[n + 1] = pReal[1];
vertexBuf[n + 2] = pReal[2];
}
vbuf->unlock();
next_offset += vertex_data->vertexCount;
}
}
if (faceBuf)
{
//----------------------------------------------------------------
// GET INDEXDATA
//----------------------------------------------------------------
IndexData* index_data = submesh->indexData;
size_t numTris = index_data->indexCount / 3;
HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IT_32BIT);
uint32 *pLong = static_cast<uint32*>(ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
uint16* pShort = reinterpret_cast<uint16*>(pLong);
size_t offset = (submesh->useSharedVertices)? shared_offset : current_offset;
if ( use32bitindexes )
{
for ( size_t k = 0; k < numTris*3; ++k)
{
faceBuf[index_offset++] = pLong[k] + static_cast<int>(offset);
}
}
else
{
for ( size_t k = 0; k < numTris*3; ++k)
{
faceBuf[index_offset++] = static_cast<int>(pShort[k]) + static_cast<int>(offset);
}
}
ibuf->unlock();
}
current_offset = next_offset;
}
}
Code: Select all
mEntity->removeSoftwareAnimationRequest(false);
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
-
megatema
- Halfling
- Posts: 43
- Joined: Fri Mar 09, 2007 12:59 pm
- Location: Saint-Petersburg, Russia
- x 2
Re: Retrieve correct vertices data from animated mesh
Thanx, I'll try it.
-
jacmoe
- OGRE Retired Moderator

- Posts: 20570
- Joined: Thu Jan 22, 2004 10:13 am
- Location: Denmark
- x 179
Nice code, Yavin! OgreOpcode simply wouldn't be the same without 'em! 
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
