ogre有一个RaySceneQuery的类,在默认场景管理器下,这个类返回一组RaySceneQueryResultEntry,他们都是通过包围盒进行的检测,由于包围盒过于简陋,我们可以再进行更精细的基于面的射线碰撞检测。
主要注意的就是mesh的构造方式,是否用了index,index是16位还是32位,其他的没什么了,射线到三角的检测函数取自dx例子,ogre自己也提供了,不过我感觉不太好用。
另外,mesh的顶点格式还要注意,position不一定独享其所在的source段,可能包含其它信息比如顶点色。所以我们必须计算一个偏移量。
废话少说,看代码。
bool IntersectMesh( const Ogre::Ray &ray, const Entity *pEntity, int *SubEntityIndex, Vector3 *IntersectTriangleA, Vector3 *IntersectTriangleB, Vector3 *IntersectTriangleC, float *t, float *u, float *v )
{
int numSubEntities = pEntity->getNumSubEntities();
{
int numSubEntities = pEntity->getNumSubEntities();
for ( int i = 0; i<numSubEntities; i++ )
{
//get VertexData and IndexData
Ogre::SubEntity *pSubEntity = pEntity->getSubEntity( i );
Ogre::VertexData *pSubEntityVertexData = pSubEntity->getVertexDataForBinding();
Ogre::SubMesh *pSubMesh = pSubEntity->getSubMesh();
Ogre::IndexData *pSubEntityIndexData = pSubMesh->indexData;
{
//get VertexData and IndexData
Ogre::SubEntity *pSubEntity = pEntity->getSubEntity( i );
Ogre::VertexData *pSubEntityVertexData = pSubEntity->getVertexDataForBinding();
Ogre::SubMesh *pSubMesh = pSubEntity->getSubMesh();
Ogre::IndexData *pSubEntityIndexData = pSubMesh->indexData;
//read buffer
Ogre::VertexBufferBinding::VertexBufferBindingMap ghm_VBBM = pSubEntityVertexData->vertexBufferBinding->getBindings();
int iPositonIndex = -1;
//find position buffer
DWORD ElementCount = (DWORD)pSubEntityVertexData->vertexDeclaration->getElementCount();
for ( DWORD k = 0; k < ElementCount; i++)
{
const VertexElement *ghm_VE = pSubEntityVertexData->vertexDeclaration->getElement( k );
if ( ghm_VE->getSemantic() == VES_POSITION ) //we are just interested in position
{
//bingo,get it
iPositonIndex = k;
break;
}
}
Ogre::VertexBufferBinding::VertexBufferBindingMap ghm_VBBM = pSubEntityVertexData->vertexBufferBinding->getBindings();
int iPositonIndex = -1;
//find position buffer
DWORD ElementCount = (DWORD)pSubEntityVertexData->vertexDeclaration->getElementCount();
for ( DWORD k = 0; k < ElementCount; i++)
{
const VertexElement *ghm_VE = pSubEntityVertexData->vertexDeclaration->getElement( k );
if ( ghm_VE->getSemantic() == VES_POSITION ) //we are just interested in position
{
//bingo,get it
iPositonIndex = k;
break;
}
}
if ( iPositonIndex == -1 ) //can't find position buffer
return false;
return false;
//read vertex buffer
Ogre::VertexBufferBinding::VertexBufferBindingMap::iterator vbbm_interator = ghm_VBBM.find( iPositonIndex );
size_t vertexbuffersize = vbbm_interator->second->getNumVertices() * vbbm_interator->second->getVertexSize(); //buffer size
BYTE *VertexBuffer = new BYTE[vertexbuffersize]; //build vertex buffer
vbbm_interator->second->readData( 0, vertexbuffersize, VertexBuffer );
//float *fVertexBuffer = (float*)VertexBuffer;
Ogre::VertexBufferBinding::VertexBufferBindingMap::iterator vbbm_interator = ghm_VBBM.find( iPositonIndex );
size_t vertexbuffersize = vbbm_interator->second->getNumVertices() * vbbm_interator->second->getVertexSize(); //buffer size
BYTE *VertexBuffer = new BYTE[vertexbuffersize]; //build vertex buffer
vbbm_interator->second->readData( 0, vertexbuffersize, VertexBuffer );
//float *fVertexBuffer = (float*)VertexBuffer;
size_t PositionElementOffset = vbbm_interator->second->getVertexSize() - 12; //得到顶点之外的字节数
//check index
Ogre::RenderOperation roSub;
pSubMesh->_getRenderOperation( roSub );
if ( roSub.useIndexes ) //使用index
{
//read index buffer
size_t indexbuffersize = pSubEntityIndexData->indexBuffer->getNumIndexes() * pSubEntityIndexData->indexBuffer->getIndexSize(); //buffer size
BYTE *IndexBuffer = new BYTE[indexbuffersize]; //build index buffer
//check index
Ogre::RenderOperation roSub;
pSubMesh->_getRenderOperation( roSub );
if ( roSub.useIndexes ) //使用index
{
//read index buffer
size_t indexbuffersize = pSubEntityIndexData->indexBuffer->getNumIndexes() * pSubEntityIndexData->indexBuffer->getIndexSize(); //buffer size
BYTE *IndexBuffer = new BYTE[indexbuffersize]; //build index buffer
//read data
pSubEntityIndexData->indexBuffer->readData( 0, indexbuffersize, IndexBuffer );
size_t numfaces = pSubEntityIndexData->indexBuffer->getNumIndexes() / 3;
//进行射线碰撞检测,很慢啊。。。。。。55555
//check index type
if ( pSubEntityIndexData->indexBuffer->getType() == Ogre::HardwareIndexBuffer::IT_16BIT )
{
short *iIndexBuffer = (short*)IndexBuffer;
for ( size_t j = 0; j<numfaces; j++ )
{
float fa,fb,fc;
memcpy( &fa, &VertexBuffer[ iIndexBuffer[ j * 3 ] * sizeof(float) * 3 + ( iIndexBuffer[ j * 3 ] * PositionElementOffset ) ], sizeof(float) );
memcpy( &fb, &VertexBuffer[ iIndexBuffer[ j * 3 ] * sizeof(float) * 3 + sizeof(float) + ( iIndexBuffer[ j * 3 ] * PositionElementOffset ) ], sizeof(float) );
memcpy( &fc, &VertexBuffer[ iIndexBuffer[ j * 3 ] * sizeof(float) * 3 + sizeof(float) * 2 + ( iIndexBuffer[ j * 3 ] * PositionElementOffset ) ], sizeof(float) );
Vector3 t1 = Vector3( fa, fb, fc );
//check index type
if ( pSubEntityIndexData->indexBuffer->getType() == Ogre::HardwareIndexBuffer::IT_16BIT )
{
short *iIndexBuffer = (short*)IndexBuffer;
for ( size_t j = 0; j<numfaces; j++ )
{
float fa,fb,fc;
memcpy( &fa, &VertexBuffer[ iIndexBuffer[ j * 3 ] * sizeof(float) * 3 + ( iIndexBuffer[ j * 3 ] * PositionElementOffset ) ], sizeof(float) );
memcpy( &fb, &VertexBuffer[ iIndexBuffer[ j * 3 ] * sizeof(float) * 3 + sizeof(float) + ( iIndexBuffer[ j * 3 ] * PositionElementOffset ) ], sizeof(float) );
memcpy( &fc, &VertexBuffer[ iIndexBuffer[ j * 3 ] * sizeof(float) * 3 + sizeof(float) * 2 + ( iIndexBuffer[ j * 3 ] * PositionElementOffset ) ], sizeof(float) );
Vector3 t1 = Vector3( fa, fb, fc );
memcpy( &fa, &VertexBuffer[ iIndexBuffer[ j * 3 + 1 ] * sizeof(float) * 3 + ( iIndexBuffer[ j * 3 + 1 ] * PositionElementOffset ) ], sizeof(float) );
memcpy( &fb, &VertexBuffer[ iIndexBuffer[ j * 3 + 1 ] * sizeof(float) * 3 + sizeof(float) + ( iIndexBuffer[ j * 3 + 1 ] * PositionElementOffset ) ], sizeof(float) );
memcpy( &fc, &VertexBuffer[ iIndexBuffer[ j * 3 + 1 ] * sizeof(float) * 3 + sizeof(float) * 2 + ( iIndexBuffer[ j * 3 + 1 ] * PositionElementOffset ) ], sizeof(float) );
Vector3 t2 = Vector3( fa, fb, fc );
memcpy( &fb, &VertexBuffer[ iIndexBuffer[ j * 3 + 1 ] * sizeof(float) * 3 + sizeof(float) + ( iIndexBuffer[ j * 3 + 1 ] * PositionElementOffset ) ], sizeof(float) );
memcpy( &fc, &VertexBuffer[ iIndexBuffer[ j * 3 + 1 ] * sizeof(float) * 3 + sizeof(float) * 2 + ( iIndexBuffer[ j * 3 + 1 ] * PositionElementOffset ) ], sizeof(float) );
Vector3 t2 = Vector3( fa, fb, fc );
memcpy( &fa, &VertexBuffer[ iIndexBuffer[ j * 3 + 2 ] * sizeof(float) * 3 + ( iIndexBuffer[ j * 3 + 2 ] * PositionElementOffset ) ], sizeof(float) );
memcpy( &fb, &VertexBuffer[ iIndexBuffer[ j * 3 + 2 ] * sizeof(float) * 3 + sizeof(float) + ( iIndexBuffer[ j * 3 + 2 ] * PositionElementOffset ) ], sizeof(float) );
memcpy( &fc, &VertexBuffer[ iIndexBuffer[ j * 3 + 2 ] * sizeof(float) * 3 + sizeof(float) * 2 + ( iIndexBuffer[ j * 3 + 2 ] * PositionElementOffset ) ], sizeof(float) );
Vector3 t3 = Vector3( fa, fb, fc );
memcpy( &fb, &VertexBuffer[ iIndexBuffer[ j * 3 + 2 ] * sizeof(float) * 3 + sizeof(float) + ( iIndexBuffer[ j * 3 + 2 ] * PositionElementOffset ) ], sizeof(float) );
memcpy( &fc, &VertexBuffer[ iIndexBuffer[ j * 3 + 2 ] * sizeof(float) * 3 + sizeof(float) * 2 + ( iIndexBuffer[ j * 3 + 2 ] * PositionElementOffset ) ], sizeof(float) );
Vector3 t3 = Vector3( fa, fb, fc );
bool rt = IntersectTriangle( ray.getOrigin(), ray.getDirection(), t1, t2, t3, t, u, v );
if ( rt )
{
SAFE_DELETE_ARRAY( VertexBuffer );
SAFE_DELETE_ARRAY( IndexBuffer );
{
SAFE_DELETE_ARRAY( VertexBuffer );
SAFE_DELETE_ARRAY( IndexBuffer );
if ( SubEntityIndex )
{
*SubEntityIndex = i;
}
if ( IntersectTriangleA && IntersectTriangleB && IntersectTriangleC )
{
*IntersectTriangleA = t1;
*IntersectTriangleB = t2;
*IntersectTriangleC = t3;
}
return true;
}
}
{
*SubEntityIndex = i;
}
if ( IntersectTriangleA && IntersectTriangleB && IntersectTriangleC )
{
*IntersectTriangleA = t1;
*IntersectTriangleB = t2;
*IntersectTriangleC = t3;
}
return true;
}
}
}
else //this is 32 bit index
{
long *iIndexBuffer = (long*)IndexBuffer;
for ( size_t j = 0; j<numfaces; j++ )
{
float fa,fb,fc;
memcpy( &fa, &VertexBuffer[ iIndexBuffer[ j * 3 ] * sizeof(float) * 3 + ( iIndexBuffer[ j * 3 ] * PositionElementOffset ) ], sizeof(float) );
memcpy( &fb, &VertexBuffer[ iIndexBuffer[ j * 3 ] * sizeof(float) * 3 + sizeof(float) + ( iIndexBuffer[ j * 3 ] * PositionElementOffset ) ], sizeof(float) );
memcpy( &fc, &VertexBuffer[ iIndexBuffer[ j * 3 ] * sizeof(float) * 3 + sizeof(float) * 2 + ( iIndexBuffer[ j * 3 ] * PositionElementOffset ) ], sizeof(float) );
Vector3 t1 = Vector3( fa, fb, fc );
else //this is 32 bit index
{
long *iIndexBuffer = (long*)IndexBuffer;
for ( size_t j = 0; j<numfaces; j++ )
{
float fa,fb,fc;
memcpy( &fa, &VertexBuffer[ iIndexBuffer[ j * 3 ] * sizeof(float) * 3 + ( iIndexBuffer[ j * 3 ] * PositionElementOffset ) ], sizeof(float) );
memcpy( &fb, &VertexBuffer[ iIndexBuffer[ j * 3 ] * sizeof(float) * 3 + sizeof(float) + ( iIndexBuffer[ j * 3 ] * PositionElementOffset ) ], sizeof(float) );
memcpy( &fc, &VertexBuffer[ iIndexBuffer[ j * 3 ] * sizeof(float) * 3 + sizeof(float) * 2 + ( iIndexBuffer[ j * 3 ] * PositionElementOffset ) ], sizeof(float) );
Vector3 t1 = Vector3( fa, fb, fc );
memcpy( &fa, &VertexBuffer[ iIndexBuffer[ j * 3 + 1 ] * sizeof(float) * 3 + ( iIndexBuffer[ j * 3 + 1 ] * PositionElementOffset ) ], sizeof(float) );
memcpy( &fb, &VertexBuffer[ iIndexBuffer[ j * 3 + 1 ] * sizeof(float) * 3 + sizeof(float) + ( iIndexBuffer[ j * 3 + 1 ] * PositionElementOffset ) ], sizeof(float) );
memcpy( &fc, &VertexBuffer[ iIndexBuffer[ j * 3 + 1 ] * sizeof(float) * 3 + sizeof(float) * 2 + ( iIndexBuffer[ j * 3 + 1 ] * PositionElementOffset ) ], sizeof(float) );
Vector3 t2 = Vector3( fa, fb, fc );
memcpy( &fb, &VertexBuffer[ iIndexBuffer[ j * 3 + 1 ] * sizeof(float) * 3 + sizeof(float) + ( iIndexBuffer[ j * 3 + 1 ] * PositionElementOffset ) ], sizeof(float) );
memcpy( &fc, &VertexBuffer[ iIndexBuffer[ j * 3 + 1 ] * sizeof(float) * 3 + sizeof(float) * 2 + ( iIndexBuffer[ j * 3 + 1 ] * PositionElementOffset ) ], sizeof(float) );
Vector3 t2 = Vector3( fa, fb, fc );
memcpy( &fa, &VertexBuffer[ iIndexBuffer[ j * 3 + 2 ] * sizeof(float) * 3 + ( iIndexBuffer[ j * 3 + 2 ] * PositionElementOffset ) ], sizeof(float) );
memcpy( &fb, &VertexBuffer[ iIndexBuffer[ j * 3 + 2 ] * sizeof(float) * 3 + sizeof(float) + ( iIndexBuffer[ j * 3 + 2 ] * PositionElementOffset ) ], sizeof(float) );
memcpy( &fc, &VertexBuffer[ iIndexBuffer[ j * 3 + 2 ] * sizeof(float) * 3 + sizeof(float) * 2 + ( iIndexBuffer[ j * 3 + 2 ] * PositionElementOffset ) ], sizeof(float) );
Vector3 t3 = Vector3( fa, fb, fc );
memcpy( &fb, &VertexBuffer[ iIndexBuffer[ j * 3 + 2 ] * sizeof(float) * 3 + sizeof(float) + ( iIndexBuffer[ j * 3 + 2 ] * PositionElementOffset ) ], sizeof(float) );
memcpy( &fc, &VertexBuffer[ iIndexBuffer[ j * 3 + 2 ] * sizeof(float) * 3 + sizeof(float) * 2 + ( iIndexBuffer[ j * 3 + 2 ] * PositionElementOffset ) ], sizeof(float) );
Vector3 t3 = Vector3( fa, fb, fc );
bool rt = IntersectTriangle( ray.getOrigin(), ray.getDirection(), t1, t2, t3, t, u, v );
if ( rt )
{
SAFE_DELETE_ARRAY( VertexBuffer );
SAFE_DELETE_ARRAY( IndexBuffer );
if ( rt )
{
SAFE_DELETE_ARRAY( VertexBuffer );
SAFE_DELETE_ARRAY( IndexBuffer );
if ( SubEntityIndex )
{
*SubEntityIndex = i;
}
if ( IntersectTriangleA && IntersectTriangleB && IntersectTriangleC )
{
*IntersectTriangleA = t1;
*IntersectTriangleB = t2;
*IntersectTriangleC = t3;
}
return true;
}
}
}
{
*SubEntityIndex = i;
}
if ( IntersectTriangleA && IntersectTriangleB && IntersectTriangleC )
{
*IntersectTriangleA = t1;
*IntersectTriangleB = t2;
*IntersectTriangleC = t3;
}
return true;
}
}
}
SAFE_DELETE_ARRAY( VertexBuffer );
SAFE_DELETE_ARRAY( IndexBuffer );
}
else //don't use index
{
//get face number
size_t numfaces = vbbm_interator->second->getNumVertices() / 3;
for ( size_t j = 0; j<numfaces; j++ )
{
float fa,fb,fc;
memcpy( &fa, &VertexBuffer[ j * 9 + j * 9 * PositionElementOffset ], sizeof(float) );
memcpy( &fb, &VertexBuffer[ j * 9 + sizeof(float) + ( j * 9 + sizeof(float) ) * PositionElementOffset ], sizeof(float) );
memcpy( &fc, &VertexBuffer[ j * 9 + sizeof(float) * 2 + ( j * 9 + sizeof(float) * 2 ) * PositionElementOffset ], sizeof(float) );
Vector3 t1 = Vector3( fa, fb, fc );
SAFE_DELETE_ARRAY( IndexBuffer );
}
else //don't use index
{
//get face number
size_t numfaces = vbbm_interator->second->getNumVertices() / 3;
for ( size_t j = 0; j<numfaces; j++ )
{
float fa,fb,fc;
memcpy( &fa, &VertexBuffer[ j * 9 + j * 9 * PositionElementOffset ], sizeof(float) );
memcpy( &fb, &VertexBuffer[ j * 9 + sizeof(float) + ( j * 9 + sizeof(float) ) * PositionElementOffset ], sizeof(float) );
memcpy( &fc, &VertexBuffer[ j * 9 + sizeof(float) * 2 + ( j * 9 + sizeof(float) * 2 ) * PositionElementOffset ], sizeof(float) );
Vector3 t1 = Vector3( fa, fb, fc );
memcpy( &fb, &VertexBuffer[ j * 9 + sizeof(float) * 3 + ( j * 9 + sizeof(float) * 3 ) * PositionElementOffset ], sizeof(float) );
memcpy( &fb, &VertexBuffer[ j * 9 + sizeof(float) * 4 + ( j * 9 + sizeof(float) * 4 ) * PositionElementOffset ], sizeof(float) );
memcpy( &fc, &VertexBuffer[ j * 9 + sizeof(float) * 5 + ( j * 9 + sizeof(float) * 5 ) * PositionElementOffset ], sizeof(float) );
Vector3 t2 = Vector3( fa, fb, fc );
memcpy( &fb, &VertexBuffer[ j * 9 + sizeof(float) * 4 + ( j * 9 + sizeof(float) * 4 ) * PositionElementOffset ], sizeof(float) );
memcpy( &fc, &VertexBuffer[ j * 9 + sizeof(float) * 5 + ( j * 9 + sizeof(float) * 5 ) * PositionElementOffset ], sizeof(float) );
Vector3 t2 = Vector3( fa, fb, fc );
memcpy( &fb, &VertexBuffer[ j * 9 + sizeof(float) * 6 + ( j * 9 + sizeof(float) * 6 ) * PositionElementOffset ], sizeof(float) );
memcpy( &fb, &VertexBuffer[ j * 9 + sizeof(float) * 7 + ( j * 9 + sizeof(float) * 7 ) * PositionElementOffset ], sizeof(float) );
memcpy( &fc, &VertexBuffer[ j * 9 + sizeof(float) * 8 + ( j * 9 + sizeof(float) * 8 ) * PositionElementOffset ], sizeof(float) );
Vector3 t3 = Vector3( fa, fb, fc );
memcpy( &fb, &VertexBuffer[ j * 9 + sizeof(float) * 7 + ( j * 9 + sizeof(float) * 7 ) * PositionElementOffset ], sizeof(float) );
memcpy( &fc, &VertexBuffer[ j * 9 + sizeof(float) * 8 + ( j * 9 + sizeof(float) * 8 ) * PositionElementOffset ], sizeof(float) );
Vector3 t3 = Vector3( fa, fb, fc );
bool rt = IntersectTriangle( ray.getOrigin(), ray.getDirection(), t1, t2, t3, t, u, v );
if ( rt )
{
SAFE_DELETE_ARRAY( VertexBuffer );
if ( SubEntityIndex )
{
*SubEntityIndex = i;
}
if ( IntersectTriangleA && IntersectTriangleB && IntersectTriangleC )
{
*IntersectTriangleA = t1;
*IntersectTriangleB = t2;
*IntersectTriangleC = t3;
}
return true;
}
}
}
{
*SubEntityIndex = i;
}
if ( IntersectTriangleA && IntersectTriangleB && IntersectTriangleC )
{
*IntersectTriangleA = t1;
*IntersectTriangleB = t2;
*IntersectTriangleC = t3;
}
return true;
}
}
}
}
return false;
}