Havok Collision Shapes from Custom Vertex and Index Data ?

Havok Collision Shapes from Custom Vertex and Index Data ?

Hi, because I'm using Blender, and have no way of obtaining and using 3DS Max/Maya/XSI, I'm stuck with converting the meshes on my own.
Do the vertices/indices need to be ordered in a specific way or what ?
I'm using OGRE as my rendering engine, and I would like to convert a simple 14-vertex level into a Havok collision shape, the code which I currently have and produces an incorrect shape is the following:

		static hkpRigidBody* createTriangleMesh(hkpWorld* pWorld, Ogre::Mesh* mesh, const Vector3& scale)
		{
			hkpExtendedMeshShape* meshShape = new hkpExtendedMeshShape(0.0f);

			Vector3* vertices;
			size_t vertex_count,index_count;
			unsigned int* indices;
			getMeshInformation(mesh, vertex_count, vertices, index_count, indices);

			hkVector4* hkVertices;

			for (int j = 0; j < vertex_count; j+=1 )
			{
				hkVertices[j] = hkVector4(vertices[j].x, vertices[j].y, vertices[j].z, 0);
			}

			hkpExtendedMeshShape::TrianglesSubpart part;

			part.m_vertexBase = (float*)hkVertices;
			part.m_vertexStriding = sizeof(float);
			part.m_numVertices = vertex_count;

			part.m_indexBase = indices;
			part.m_indexStriding = sizeof(unsigned int);
			part.m_numTriangleShapes = index_count/3;
			part.m_stridingType = hkpExtendedMeshShape::INDICES_INT16;

			meshShape->addTrianglesSubpart(part);

			hkpMoppCompilerInput* cmi = new hkpMoppCompilerInput();
			hkpMoppCode* code = hkpMoppUtility::buildCode(meshShape, *cmi);

			hkpMoppBvTreeShape* moppBvShape = new hkpMoppBvTreeShape(meshShape, code);

			hkpRigidBodyCinfo info;

			info.m_shape = moppBvShape;
			info.m_motionType = hkpMotion::MOTION_FIXED;

			hkpRigidBody* r = new hkpRigidBody(info);

			pWorld->addEntity;

			return r;
		}

BTW - I want to make an exporter for Blender, if possible. Where would I find what I need to read in order to acomplish that ?Here's the post on the OGRE3D Forums:http://www.ogre3d.org/forums/viewtopic.php?f=1&t=68747

6 Beiträge / 0 neu
Letzter Beitrag
Nähere Informationen zur Compiler-Optimierung finden Sie in unserem Optimierungshinweis.

HimindcalamityI don't look deeply in your code
But are you sure that this is correct :

part.m_stridingType = hkpExtendedMeshShape::INDICES_INT16;

Since your original index are stored as unsigned int (32 bytes) maybe change the enum to

hkpExtendedMeshShape::INDICES_INT32

can resolve yout problem !!! :)

Nah, that's not it, I already tried that.The real problem is probably in the way I pass my indices, or vertices.In any case something is very wrong.I looked at the exporter's XML format, and with all the meta data it was a mess, it cleaned up after disabling it, but I still don't get how a cube can have 72 vertex definitions...I think that an example of converting a publicly known, and well-used format into hkx/hkt would benefit the whole Havok community. (Or at least those of us who don't have the means to use 3DS Max or other commercial programs, and other potential users who are pushed away from this simple setback.)Here's the code I currently have:

		static hkpRigidBody* createTriangleMesh(hkpWorld* pWorld, Ogre::Mesh* mesh, const Vector3& scale)
		{
			hkpExtendedMeshShape* meshShape = new hkpExtendedMeshShape(0.0f);

			Vector3* vertices;
			size_t vertex_count,index_count;
			unsigned int* indices;
			getMeshInformation(mesh, vertex_count, vertices, index_count, indices);

			hkVector4* hkVertices;
			hkReal* vertexBuffer;
			int tmpCounter = 0;
			for (int j = 0; j < vertex_count; j+=1 )
			{
				vertexBuffer[tmpCounter]   = vertices[j].x * scale.x;
				vertexBuffer[tmpCounter+1]   = vertices[j].y * scale.y;
				vertexBuffer[tmpCounter+2]   = vertices[j].z * scale.z;

				tmpCounter += 3;
			}

			for (int i = 0; i < index_count; i++)
			{
				//indices[i] = i;
				std::cout << indices[i] << "n";
			}
			hkpExtendedMeshShape::TrianglesSubpart part;

			part.m_vertexBase = vertexBuffer;
			part.m_vertexStriding = sizeof(float) * 3;
			part.m_numVertices = vertex_count;

			part.m_indexBase = indices;
			part.m_indexStriding = sizeof(unsigned int);
			part.m_numTriangleShapes = index_count;
			part.m_stridingType = hkpExtendedMeshShape::INDICES_INT16;

			meshShape->addTrianglesSubpart(part);

			hkpMoppCompilerInput* cmi = new hkpMoppCompilerInput();
			hkpMoppCode* code = hkpMoppUtility::buildCode(meshShape, *cmi);

			hkpMoppBvTreeShape* moppBvShape = new hkpMoppBvTreeShape(meshShape, code);

			hkpRigidBodyCinfo info;

			info.m_shape = moppBvShape;
			info.m_motionType = hkpMotion::MOTION_FIXED;

			hkpRigidBody* r = new hkpRigidBody(info);

			pWorld->addEntity;

			return r;
		}
And the result:

OK, progress, now at least Havok is spouting some info:

Collide\Mopp\Builder\Splitter\hkpMoppDefaultSplitter.cpp(773): [0xABBA2344] Warning : Could not find splitting plane for child

I also tried using Irrlicht and it's data (with intent to serialize it later), but that seems to result in this exact same thing - the error message above.Any ideas ?I searched but, amazingly Google doesn't give any results related to Havok (or in any way remotely related to programming in general) at all.Thanks to KungFooMasta for the code.

Thanks to KungFooMasta for the code.Current code:

		static hkpRigidBody* createTriangleMesh(hkpWorld* pWorld, Ogre::Entity* ent, const Vector3& scale)
		{
			size_t vertex_count;
			size_t index_count;
			Ogre::Vector3 pos;
			Ogre::Quaternion ori;
			Ogre::Vector3 rScale;
			Ogre::Vector3* vertices;
			unsigned long* indices;
			_getMeshInformation(ent, vertex_count, vertices, index_count, indices, pos, ori, rScale);
			// Create Extended Mesh Shape
			hkpExtendedMeshShape* shape = new hkpExtendedMeshShape();
			{
				hkpExtendedMeshShape::TrianglesSubpart part;
				part.m_numTriangleShapes	= index_count;
				part.m_numVertices			= vertex_count;
				part.m_vertexBase			= (float*)vertices;
				part.m_stridingType         = hkpExtendedMeshShape::INDICES_INT32;
				part.m_vertexStriding		= sizeof(float) * 3;
				part.m_indexBase			= indices;
				part.m_indexStriding		= sizeof(unsigned long) * 3;
				part.m_numTriangleShapes	= index_count/3;

				shape->addTrianglesSubpart( part );
			}

			hkpMoppCompilerInput* cmi = new hkpMoppCompilerInput();
			hkpMoppCode* code = hkpMoppUtility::buildCode(shape, *cmi);

			hkpMoppBvTreeShape* moppBvShape = new hkpMoppBvTreeShape(shape, code);

			hkpRigidBodyCinfo info;

			info.m_shape = moppBvShape;
			info.m_motionType = hkpMotion::MOTION_FIXED;

			hkpRigidBody* r = new hkpRigidBody(info);

			pWorld->addEntity;

			return r;
		}

http://www.ogre3d.org/forums/viewtopic.php?f=1&t=68747
^^^ Thread on the OGRE Forums ^^^

Hey, there's a couple minor things here:

part.m_numTriangleShapes    = index_count; // wrong
//...
part.m_numTriangleShapes    = index_count/3; // but then fixed
part.m_vertexStriding       = sizeof(float) * 3; // best to use sizeof(Ogre::Vector3) just to be safe
hkpMoppCompilerInput* cmi = new hkpMoppCompilerInput(); // This is an unnecessary new. Just create hkpMoppCompilerInput on the stack so you don't leak.

That said, I don't see anything particularly wrong with your mesh building code. From that warning either _getMeshInformation() has bugs, or there could be something funky about your asset. I would recommend double checking the output from _getMeshInformation() - does it give the expected number of indices, vertices? Are they all present and valid? Have you tried debugging with simple assets (a box)? Does _getMeshInformation() return temporary buffers that get destroyed later? hkpExtendedMeshShape does not own it's triangle/index information so be sure not to destroy it.

Just in case your mesh is huge, by default hkpExtendedMeshShape only supports "2^20 triangles = 1048576" (see comments in hkpExtendedMeshShape.h).

Keep in mind you don't have to create a MOPP from your shape. hkpExtendedMeshShape should handle degenerate triangles. Does the mesh work without creating a mopp from it?

If you don't mind posting or PMing me your mesh asset after building the hkpExtendedMeshShape I could take a look at it. This will write out an hkpExtendedMeshShape to a file:

hkOstream os( "mesh.hkt" );
hkpHavokSnapshot::save( myExtendedMesh, hkpExtendedMeshShapeClass, os.getStreamWriter() );

Cheers,
Tyler

A month late. Fully working code in the Ogre forums. I paste here just in case:

    std::vector>            *verticesOut;
    std::vector>   *indicesOut;
    MeshPtr mesh = MeshManager::getSingleton().load( "MyMeshName",
                                        ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME );

    Mesh::SubMe****erator subMe**** = mesh->getSubMe****erator();
    while( subMe****.hasMoreElements() )
    {
       SubMesh *subMesh = subMe****.getNext();

       //Reserve enough memory for our vertex buffer
       verticesOut->push_back( std::vector() );
       std::vector &vertices = verticesOut->back();
       vertices.reserve( subMesh->vertexData->vertexCount * 3 );

       //Copy vertices
       const VertexElement *vertElement = subMesh->vertexData->vertexDeclaration->
                                           findElementBySemantic( VES_POSITION );
       const size_t vertexSize =
                subMesh->vertexData->vertexDeclaration->getVertexSize(vertElement->getSource());
       const HardwareVertexBufferSharedPtr &vertexBuf = subMesh->vertexData->vertexBufferBinding->
                                                 getBuffer( vertElement->getSource() );

       unsigned char const *pBuffer = static_cast
                                  (vertexBuf->lock( HardwareBuffer::HBL_READ_ONLY ));
       for( size_t i=0; ivertexData->vertexCount; ++i )
       {
          float const *pPos = reinterpret_cast(pBuffer + vertElement->getOffset());
          vertices.push_back( *pPos++ );
          vertices.push_back( *pPos++ );
          vertices.push_back( *pPos++ );
          pBuffer += vertexSize;
       }

       vertexBuf->unlock();

       //Reserve enough memory for our index buffer
       indicesOut->push_back( std::vector() );
       std::vector &indices = indicesOut->back();
       indices.reserve( subMesh->indexData->indexCount );

       //Copy indices
       const HardwareIndexBufferSharedPtr indexBuffer = subMesh->indexData->indexBuffer;
       unsigned short const *pIndices = static_cast
                                     (indexBuffer->lock( HardwareBuffer::HBL_READ_ONLY ));
       for( size_t i=0; iindexData->indexCount; ++i )
          indices.push_back( *pIndices++ );

       indexBuffer->unlock();
    }

    hkpExtendedMeshShape *meshShape = new hkpExtendedMeshShape();

    for( size_t i=0; iaddTrianglesSubpart( part );
    }

    hkpMoppCode* moppCode = hkpMoppUtility::buildCode( meshShape, hkpMoppCompilerInput() );

    hkpMoppBvTreeShape *retVal = new hkpMoppBvTreeShape( meshShape, moppCode );
    hkpMeshWeldingUtility::computeWeldingInfo( meshShape, retVal,
                                     hkpWeldingUtility::WELDING_TYPE_ANTICLOCKWISE );
    moppCode->removeReference();
    meshShape->removeReference();

Hope it helps anyone else looking for it.

Matias N. Goldberg Intel Havok Physics Innovation Contest Winner * Most Innovative Use of Physics in a Game (2nd Place) * Best Physics Knowledge Base Entry (2nd Place)

Melden Sie sich an, um einen Kommentar zu hinterlassen.