[ODE] Re: Problems w/ tri-collider and ODE 0.035
Nate W
coding at natew.com
Thu Jan 2 12:08:01 2003
On Thu, 2 Jan 2003, Chris Klein wrote:
> > > Also, if someone already has gotten ODE, tri-collider, OPCODE,
> > > Demeter, and OpenSceneGraph to play nice with each other, I would
> > > greatly appreciate seeing your source code.
>
> (Paul, I also have some code which may help you get your combination of
> libs working. I was using OSG and Demeter for a while though I am not
> anymore. I expect you're trying to feed the demeter terrain into the
> tricollider - unless demeter's changed in the last few months you can't
> actually get enough data from demeter to get vertex and polygon
> information from it! I had to hack demeter to give me access to the
> vertex data and tesselate it myself to give tricollider the tri's it
> wants. Email me separately and I'll see what I can dig up over the next
> few days.)
Sorry I'm late to this thread, but I got the ODE+TC+OPCODE+Demeter
combination to work together. The code to convert data from Demeter to
tri-collider follows...
The main thing I had to do to get ODE and Demeter to work together was to
build vertex and triangle arrays using Demeter's heightmap. Once I got
that taken care of, it basically "just worked."
The conversion is done in two steps because Juice supports multiple
physics libraries. First, I build the vertex and triangle arrays in a
simple physics-independent format, then I convert that data into the
format that ODE requires. The first step is the interesting part, and it
takes place in a Terrain class that is basically just a wrapper for
Demeter:
void Terrain::vBuildArrays ()
{
if (!m_pTerrain)
{
GenericUnexpected ("terrain disabled");
return;
}
// m_pTerrain is a pointer to a Demeter::Terrain object
const Demeter::Vector *pTerrainVertexArray = m_pTerrain->m_pVertices;
if (!pTerrainVertexArray)
{
GenericUnexpected ("terrain disabled");
return;
}
int iMaxX = 0, iMaxY = 0;
// wrapper for Demeter::Terrain::GetWidth and GetHeight
vGetDimensions (iMaxX, iMaxY);
m_iVertexCount = iMaxX * iMaxY;
m_iTriangleCount = (iMaxX - 1) * (iMaxY - 1) * 2;
delete m_pVertexArray;
delete m_pTriangleArray;
// class Terrain::Vertex
// {
// float x, y, z; // a trivial vector class
// };
m_pVertexArray = new Terrain::Vertex[m_iVertexCount];
// class Terrain::Triangle
// {
// int v1, v2, v3; // indices into a one-dimensional vertex array
// };
m_pTriangleArray = new Terrain::Triangle[m_iTriangleCount];
for (int iVertex = 0; iVertex < m_iVertexCount; iVertex++)
{
m_pVertexArray[iVertex].x =
pTerrainVertexArray[iVertex].x;
m_pVertexArray[iVertex].y =
pTerrainVertexArray[iVertex].y;
m_pVertexArray[iVertex].z =
pTerrainVertexArray[iVertex].z;
}
int iTriangle = 0;
int iIndex = 0;
for (int iY= 0; iY < iMaxY - 1; iY++)
{
for (int iX = 0; iX < iMaxX - 1; iX++)
{
iTriangle = (iY * (iMaxY - 1) * 2) + (iX * 2);
iIndex = (iY * iMaxX) + iX;
m_pTriangleArray[iTriangle].v1 = iIndex;
iIndex = (iY * iMaxX) + iX + 1;
m_pTriangleArray[iTriangle].v2 = iIndex;
iIndex = (iY * iMaxX) + iX + 1 + iMaxX;
m_pTriangleArray[iTriangle].v3 = iIndex;
iTriangle++;
iIndex = (iY * iMaxX) + iX;
m_pTriangleArray[iTriangle].v1 = iIndex;
iIndex = ((iY * iMaxX) + iX) + 1 + iMaxX;
m_pTriangleArray[iTriangle].v2 = iIndex;
iIndex = ((iY * iMaxX) + iX) + iMaxX;
m_pTriangleArray[iTriangle].v3 = iIndex;
}
}
}
Conversion to the ODE data structures is trivial:
void World::vCreateTerrain (Terrain *pTerrain)
{
if (!pTerrain)
return;
Terrain::Vertex *pVertices = null;
Terrain::Triangle *pTriangles = null;
int iVertexCount = 0;
int iTriangleCount = 0;
// get vertex data from the terrain wrapper
// vGetTriangles gets the data generated by Terrain::vBuildArrays
pTerrain->vGetTriangles (&pVertices, &iVertexCount, &pTriangles, &iTriangleCount);
if (!(pVertices && pTriangles))
return;
// convert vertex data to ODE's preferred format
m_pVertices = new dcVector3[iVertexCount];
for (int i = 0; i < iVertexCount; i++)
{
m_pVertices[i].x = (float) pVertices[i].x;
m_pVertices[i].y = (float) pVertices[i].y;
m_pVertices[i].z = (float) pVertices[i].z;
}
// create ODE's collision detection mesh object
m_Terrain = dCreateTriList (m_SpaceID, null, null);
// initialize the mesh with the vertex and triangle
// information taken from the terrain wrapper
dGeomTriListBuild(m_Terrain, m_pVertices, iVertexCount, &(pTriangles->v1), iTriangleCount * 3);
}
--
Also, I talked a bit with Clay Fowler, the guy who made Demeter. He said
that he was working on an ODE-Demeter collision detection system of his
own, not using tri-collider, so you might want to ask him about that.
Tri-collider is for arbitrary meshes, so there are probably some
optimizations possible when using height-map meshes - including a way to
address the "infinitely thin" problem that came up a while ago. If you
know you're dealing with a heightmap, then you should be able to compute
penetration depth somewhat more usefully than what tri-collider provides,
since, being a general-purpose mesh collider, it treats everything as a
thin mesh.
--
Nate Waddoups
Redmond WA USA
http://www.natew.com