Advertisement

Bullet Physics - How can I convert btHeightfieldTerrainShape to btTriangleMeshShape?

Started by February 20, 2022 02:32 AM
0 comments, last by SharkBladder 2 years, 8 months ago

hello.

I found that btStridingMeshInterface is required to create btBvhTriangleMeshShape.

But all I have is as much data as (Width * Height) for btTerrainHeightfieldShape. There is no index information on the data.

Then, I found this post on Forum : viewtopic.php?p=38852&hilit=btTriangleI ... ray#p38852

so I modify that codes like this :

	auto TerrainShape = new btHeightfieldTerrainShape(mWidth * mTerrainScale.x, mDepth * mTerrainScale.z, mHeightmapData, minHeight, maxHeight, 1, false);
	TerrainShape->setLocalScaling(btVector3(1, mTerrainScale.y, 1));

	btVector3 aabbMin, aabbMax;
	for (int k = 0; k < 3; k++)
	{
		aabbMin[k] = -BT_LARGE_FLOAT;
		aabbMax[k] = BT_LARGE_FLOAT;
	}

	std::vector<XMFLOAT3> vertices;
	std::vector<unsigned short> Targetindices;

	btTriangleCollector collector;
	collector.m_pVerticesOut = &vertices;
	collector.m_pIndicesOut = &Targetindices;

	TerrainShape->processAllTriangles(&collector, aabbMin, aabbMax);

	mVertexArray = std::make_shared<btTriangleIndexVertexArray>();

	btIndexedMesh tempMesh;
	mVertexArray->addIndexedMesh(tempMesh, PHY_FLOAT);

	btIndexedMesh& mesh = mVertexArray->getIndexedMeshArray()[0];

	const int32_t VERTICES_PER_TRIANGLE = 3;
	size_t numIndices = Targetindices.size();
	mesh.m_numTriangles = numIndices / VERTICES_PER_TRIANGLE;

	if (numIndices < std::numeric_limits<int16_t>::max())
	{
		mesh.m_triangleIndexBase = new unsigned char[sizeof(int16_t) * (size_t)numIndices];
		mesh.m_indexType = PHY_SHORT;
		mesh.m_triangleIndexStride = VERTICES_PER_TRIANGLE * sizeof(int16_t);
	}
	else
	{
		mesh.m_triangleIndexBase = new unsigned char[sizeof(int32_t) * (size_t)numIndices];
		mesh.m_indexType = PHY_INTEGER;
		mesh.m_triangleIndexStride = VERTICES_PER_TRIANGLE * sizeof(int32_t);
	}
	mesh.m_numVertices = vertices.size();
	mesh.m_vertexBase = new unsigned char[VERTICES_PER_TRIANGLE * sizeof(btScalar) * (size_t)mesh.m_numVertices];
	mesh.m_vertexStride = VERTICES_PER_TRIANGLE * sizeof(btScalar);

	btScalar* vertexData = static_cast<btScalar*>((void*)(mesh.m_vertexBase));

	for (int32_t i = 0; i < mesh.m_numVertices; ++i)
	{
		int32_t j = i * VERTICES_PER_TRIANGLE;
		const XMFLOAT3& point = vertices[i];
		vertexData[j] = point.x;
		vertexData[j + 1] = point.y;
		vertexData[j + 2] = point.z;
	}

	if (numIndices < std::numeric_limits<int16_t>::max())
	{
		int16_t* indices = static_cast<int16_t*>((void*)(mesh.m_triangleIndexBase));
		for (int32_t i = 0; i < numIndices; ++i) {
			indices[i] = (int16_t)Targetindices[i];
		}
	}
	else
	{
		int32_t* indices = static_cast<int32_t*>((void*)(mesh.m_triangleIndexBase));
		for (int32_t i = 0; i < numIndices; ++i) {
			indices[i] = Targetindices[i];
		}
	}

	btBvhTriangleMeshShape* shape = new btBvhTriangleMeshShape(mVertexArray.get(), true);


	btTransform btTerrainTransform;
	btTerrainTransform.setIdentity();
	btTerrainTransform.setOrigin(btVector3(0, 0, 0));

	mBtRigidBody = physics->CreateRigidBody(0.0f, btTerrainTransform, shape);

What I try to do is simple. make btHeightfieldTerrainShape, and collect all triangle data by TriangleCallback(collector) and make btTriangleIndexVertexArray by that data sets.

problem is data that I collected seems wrong.

if this codes works well, mBtRigdBody's AABB must be min(-511.5, 4, -511.5), max(511.5, 242, 511.5),
but, actually what i got is min(-511.5, -105.389..., -511.5), max(511.5, 25.8... ,-500.5)


definitely wrong values.

I think btTriangleIndexVertexArray doesn't have right data of terrain, but I can't find where's wrong.

please help.

This topic is closed to new replies.

Advertisement