I'm using code based on http://wiki.ogre3d.org/RetrieveVertexData, which first does a ray query followed by a mesh check to see if we actually hit the mesh.
The ray query works fine, but it uses bounding boxes and since I need to be able to pick an object out of many that are packed closely together, this isn't good enough.
The code used to work fine for Ogre 1.9 and it will build after some minor (v1 namespace) corrections, but the results are useless.
It comes down to a problem in getting the vertex information. At some point in this code, this call is made: posElem->baseVertexPointerToElement(vertex, &pReal);
For the first 8 vertices the results seem in a reasonable range, but it's hard to check if they're really correct. After that the rest has really strange big or tiny values, in the order of 1e15 or 1e33 etc. The values do seem to be consistent between calls and even between application runs, but completely useless for triangle intersection checks.
I'm guessing that this has something to do with the packed storage of values, but I don't know how to fix it. So I'm hoping someone here has the solution for this problem

ARRAY_PACKED_REALS is set to 4 (default)
I have attached debugger screenshots, one for vertex 0 (which seems ok), one for vertex 8 (which is the first that is definitely wrong) and one with a snapshot of the resulting vertices. If more information is needed to pinpoint the problem, please let me know.
Code: Select all
// Get the mesh information for the given mesh.
// Code found on this forum link: http://www.ogre3d.org/wiki/index.php/RetrieveVertexData
void getMeshInformation(const Ogre::v1::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::v1::SubMesh* submesh = mesh->getSubMesh( i );
// We only need to add the shared vertices once
if (submesh->useSharedVertices)
{
if( !added_shared )
{
vertex_count += mesh->sharedVertexData[0]->vertexCount;
added_shared = true;
}
}
else
{
vertex_count += submesh->vertexData[0]->vertexCount;
}
// Add the indices
index_count += submesh->indexData[0]->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::v1::SubMesh* submesh = mesh->getSubMesh(i);
Ogre::v1::VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData[0] : submesh->vertexData[0];
if((!submesh->useSharedVertices)||(submesh->useSharedVertices && !added_shared))
{
if(submesh->useSharedVertices)
{
added_shared = true;
shared_offset = current_offset;
}
const Ogre::v1::VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
Ogre::v1::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());
unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::v1::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 compiled/typedefed as double:
// Ogre::Real* pReal;
float* pReal = nullptr;
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;
// assert(abs(vertices[current_offset + j][0]) < 1000.0f);
}
vbuf->unlock();
next_offset += vertex_data->vertexCount;
}
Ogre::v1::IndexData* index_data = submesh->indexData[0];
size_t numTris = index_data->indexCount / 3;
Ogre::v1::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
bool use32bitindexes = (ibuf->getType() == Ogre::v1::HardwareIndexBuffer::IT_32BIT);
unsigned long* pLong = static_cast<unsigned long*>(ibuf->lock(Ogre::v1::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;
}
}



Thanks in advance
