[ODE] Extracting terrain data from Demeter
Sandeep KL
dreamtheater39 at msn.com
Sat Aug 16 01:00:02 2003
Hi,
heres the code for a box-terrain collider.....
here, FindHeight is a function internally for my terrain.....
u can have ur own equivalent function for finding the height at any (x, z)
location on ur terrain......
also, i have pasted my FindHeight function (u may wanna use this for
reference)
regards,
San
// Checks for collision between a Landscape and a Box
int dCollideLandscapeBox (dGeomID o1, dGeomID o2, int flags, dContactGeom*
contact, int skip)
{
int num_contacts = 0;
// Get the side lengths of the box
dVector3 box_sides;
dGeomBoxGetLengths(o2, box_sides);
// Get the rotation of the box
const dReal *R = dGeomGetRotation(o2);
// Get the position of the box
const dReal *P = dGeomGetPosition(o2);
// Get the 8 points of the box
vector3 points[8];
points[0].x = R[0] * -box_sides[0]/2.0 + R[1] * -box_sides[1]/2.0 + R[2]
* -box_sides[2]/2.0;
points[0].y = R[4] * -box_sides[0]/2.0 + R[5] * -box_sides[1]/2.0 + R[6]
* -box_sides[2]/2.0;
points[0].z = R[8] * -box_sides[0]/2.0 + R[9] * -box_sides[1]/2.0 +
R[10]* -box_sides[2]/2.0;
points[1].x = R[0] * box_sides[0]/2.0 + R[1] * -box_sides[1]/2.0 + R[2]
* -box_sides[2]/2.0;
points[1].y = R[4] * box_sides[0]/2.0 + R[5] * -box_sides[1]/2.0 + R[6]
* -box_sides[2]/2.0;
points[1].z = R[8] * box_sides[0]/2.0 + R[9] * -box_sides[1]/2.0 +
R[10] * -box_sides[2]/2.0;
points[2].x = R[0] * box_sides[0]/2.0 + R[1] * box_sides[1]/2.0 + R[2]
* -box_sides[2]/2.0;
points[2].y = R[4] * box_sides[0]/2.0 + R[5] * box_sides[1]/2.0 + R[6]
* -box_sides[2]/2.0;
points[2].z = R[8] * box_sides[0]/2.0 + R[9] * box_sides[1]/2.0 + R[10]
* -box_sides[2]/2.0;
points[3].x = R[0] * -box_sides[0]/2.0 + R[1] * box_sides[1]/2.0 + R[2]
* -box_sides[2]/2.0;
points[3].y = R[4] * -box_sides[0]/2.0 + R[5] * box_sides[1]/2.0 + R[6]
* -box_sides[2]/2.0;
points[3].z = R[8] * -box_sides[0]/2.0 + R[9] * box_sides[1]/2.0 +
R[10] * -box_sides[2]/2.0;
points[4].x = R[0] * -box_sides[0]/2.0 + R[1] * -box_sides[1]/2.0 +
R[2] * box_sides[2]/2.0;
points[4].y = R[4] * -box_sides[0]/2.0 + R[5] * -box_sides[1]/2.0 +
R[6] * box_sides[2]/2.0;
points[4].z = R[8] * -box_sides[0]/2.0 + R[9] * -box_sides[1]/2.0 +
R[10] * box_sides[2]/2.0;
points[5].x = R[0] * box_sides[0]/2.0 + R[1] * -box_sides[1]/2.0 + R[2]
* box_sides[2]/2.0;
points[5].y = R[4] * box_sides[0]/2.0 + R[5] * -box_sides[1]/2.0 + R[6]
* box_sides[2]/2.0;
points[5].z = R[8] * box_sides[0]/2.0 + R[9] * -box_sides[1]/2.0 +
R[10] * box_sides[2]/2.0;
points[6].x = R[0] * box_sides[0]/2.0 + R[1] * box_sides[1]/2.0 + R[2]
* box_sides[2]/2.0;
points[6].y = R[4] * box_sides[0]/2.0 + R[5] * box_sides[1]/2.0 + R[6]
* box_sides[2]/2.0;
points[6].z = R[8] * box_sides[0]/2.0 + R[9] * box_sides[1]/2.0 + R[10]
* box_sides[2]/2.0;
points[7].x = R[0] * -box_sides[0]/2.0 + R[1] * box_sides[1]/2.0 + R[2]
* box_sides[2]/2.0;
points[7].y = R[4] * -box_sides[0]/2.0 + R[5] * box_sides[1]/2.0 + R[6]
* box_sides[2]/2.0;
points[7].z = R[8] * -box_sides[0]/2.0 + R[9] * box_sides[1]/2.0 +
R[10] * box_sides[2]/2.0;
dxLandscape* l = (dxLandscape*) dGeomGetClassData(o1);
float* heightfield = l->landscape_heightfield;
int pitch = l->landscape_width;
// Check all the points against the terrain
for (int p = 0; p < 8; p++)
{
// Add the position of the box to each point
points[p].x += P[0];
points[p].y += P[1];
points[p].z += P[2];
float land_height = FindHeight( points[p].x, points[p].z );
vector3 normal;
normal[0] = -vNormal.x;
normal[1] = -vNormal.y;
normal[2] = -vNormal.z;
float depth = land_height - points[p].y;
if (depth >= 0.0)
{
CONTACT(contact, num_contacts * skip)->normal[0] = normal.x;
CONTACT(contact, num_contacts * skip)->normal[1] = normal.y;
CONTACT(contact, num_contacts * skip)->normal[2] = normal.z;
CONTACT(contact, num_contacts * skip)->pos[0] = points[p].x;
CONTACT(contact, num_contacts * skip)->pos[1] = points[p].y;
CONTACT(contact, num_contacts * skip)->pos[2] = points[p].z;
CONTACT(contact, num_contacts * skip)->depth = depth;
CONTACT(contact, num_contacts * skip)->g1 = o1;
CONTACT(contact, num_contacts * skip)->g2 = o2;
num_contacts++;
if (num_contacts > 3) return num_contacts;
}
}
return num_contacts;
}
// findheight function - lot of app specific code here........though!
// find height(y) of the specific x,z location on the terrain
float FindHeight(float x,float z)
{
if(x<GRID_SIZE)x=GRID_SIZE;
if(x>(float)((TSize-1)*GRID_SIZE))x=(float)((TSize-1)*GRID_SIZE);
if(z<GRID_SIZE)z=GRID_SIZE;
if(z>(float)((TSize-1)*GRID_SIZE))z=(float)((TSize-1)*GRID_SIZE);
FindTerrainTriangles(x,z);
vector1=vTriangle[0]-vTriangle[1];
vector2=vTriangle[2]-vTriangle[1];
D3DXVec3Cross(&UP,&vector2,&vector1);
D3DXVec3Normalize(&UP,&UP);
vNormal=UP;
float d =
-((UP.x*vTriangle[0].x)+(UP.y*vTriangle[0].y)+(UP.z*vTriangle[0].z));
float ht = -((UP.x*x)+(UP.z*z)+d)/(UP.y);
return ht;
}
// return triangles in which the x,z point lies
void FindTerrainTriangles(float Tx, float Ty, bool getFake)
{
float xangle;
int TriX, TriY; // Polygon Indices of the meshobject
TriX=(int)(Tx/GRID_SIZE);
TriY=(int)(TSize-(Ty/GRID_SIZE));
if(TriX<0)TriX=0;if(TriX>TSize-2)TriX=TSize-2;
if(TriY<0)TriY=0;if(TriY>TSize-2)TriY=TSize-2;
vTriangle[0]=vTerrain[(TriX+1)+(TriY*(TSize+1))];
if(getFake && fHeights[(TriX+1)+(TriY*(TSize+1))].isFake)
vTriangle[0].y=fHeights[(TriX+1)+(TriY*(TSize+1))].y;
xangle=(float)atan(((Ty-vTriangle[0].z)/(Tx-vTriangle[0].x)));
if(xangle<0)xangle=-xangle;
iObsX=TriX;//if((int)Tx % GRID_SIZE > (GRID_SIZE))iObsX++;
iObsY=TriY;//if((int)Ty % GRID_SIZE < (GRID_SIZE))iObsY++;
if(xangle>DegtoRad(45)) //clockwise from top-right '_|'
{
vTriangle[1]=vTerrain[(TriX+1)+((TriY+1)*(TSize+1))];
vTriangle[2]=vTerrain[(TriX)+((TriY+1)*(TSize+1))];
if(getFake && fHeights[(TriX+1)+((TriY+1)*(TSize+1))].isFake)
vTriangle[1].y=fHeights[(TriX+1)+((TriY+1)*(TSize+1))].y;
if(getFake && fHeights[(TriX)+((TriY+1)*(TSize+1))].isFake)
vTriangle[2].y=fHeights[(TriX)+((TriY+1)*(TSize+1))].y;
//vector1=vTriangle[0]-vTriangle[1];
//vector2=vTriangle[2]-vTriangle[1];
//vNormal=FindNormal( Tx, Ty );
//vNormal=vNormalArray[1+(TriX*2)+(TriY*TSize)];
vector1=vTriangle[0]-vTriangle[1];
vector2=vTriangle[2]-vTriangle[1];
D3DXVec3Cross(&vNormal,&vector2,&vector1);
D3DXVec3Normalize(&vNormal,&vNormal);
}
else //clockwise from bottomleft '|/'
{
vTriangle[1]=vTerrain[(TriX)+((TriY+1)*(TSize+1))];
vTriangle[2]=vTerrain[(TriX)+((TriY)*(TSize+1))];
if(getFake && fHeights[(TriX)+((TriY+1)*(TSize+1))].isFake)
vTriangle[1].y=fHeights[(TriX)+((TriY+1)*(TSize+1))].y;
if(getFake && fHeights[(TriX)+((TriY)*(TSize+1))].isFake)
vTriangle[2].y=fHeights[(TriX)+((TriY)*(TSize+1))].y;
//vector1=vTriangle[0]-vTriangle[1];
//vector2=vTriangle[2]-vTriangle[1];
//vNormal=Normalize(CrossProduct(vector2,vector1));
//vNormal=vNormalArray[0+(TriX*2)+(TriY*TSize)];
vector1=vTriangle[0]-vTriangle[1];
vector2=vTriangle[2]-vTriangle[1];
D3DXVec3Cross(&vNormal,&vector2,&vector1);
D3DXVec3Normalize(&vNormal,&vNormal);
}
}
_________________________________________________________________
Formula 1 fan? This is for you!
http://server1.msn.co.in/sp03/formula2003/photogallery/gallery/gal3.asp Best
pics of the year.