[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.