[ODE] Extracting terrain data from Demeter
Sandeep KL
dreamtheater39 at msn.com
Fri Aug 15 13:00:02 2003
hi,
i got my terrain collider working finally!!
even if ur diagonal is the other way round, it should be easy to fix. all u
have to do is change the vertex orders in ur collision functions........it
is pretty straight forward........shouldnt be hard!
Heres the code for a collider (sphere - heightfield)
if u need more help on this.......send me a mail......i shall send u the
entire code for a sphere-heightfield and a box-heightfield collider......
hope this helps,
San
#define CONTACT(p,skip) ((dContactGeom*) (((char*)p) + (skip)))
// Checks for collision between a Landscape and a Sphere
int dCollideLandscapeSphere (dGeomID o1, dGeomID o2, int flags,
dContactGeom* contact, int skip)
{
// Get the centre & radius of the sphere
const dReal* centre = dGeomGetPosition(o2);
dReal radius = dGeomSphereGetRadius(o2);
vector3 centre_v(centre[0], centre[1], centre[2]);
dReal aabb2[6];
dGeomGetAABB (o2, aabb2);
int left = (int)floor(aabb2[0]/grid_size);
int right = (int)ceil(aabb2[1]/grid_size);
int top = (int)floor(aabb2[4]/grid_size);
int bottom = (int)ceil(aabb2[5]/grid_size);
int num_contacts = 0;
dxLandscape* l = (dxLandscape*) dGeomGetClassData(o1);
float* heightfield = l->landscape_heightfield;
int pitch = l->landscape_width;
struct collision_info
{
// v1--------v2
// | /|
// | / |
// | / |
// v3|-------v4
// v1,v2,v3 is nw (north-west) face
// v2,v4,v3 is se face
bool hit_nw_face; // used to indicate that nw face is in contact
with the sphere.
bool hit_se_face; // used to indicate that se face is in contact
with the sphere.
};
collision_info hits[128][128]; // Maximum sphere size is 128 metres in
diameter
// (or 128 units of whatever 1.0 units
is in length).
int j;
for (j = top; j <= bottom; j++)
{
for (int i = left; i <= right; i++)
{
if ((i > 0) && (i < l->landscape_width - 1) && (j > 0) && (j <
l->landscape_height - 1))
{
vector3 v1(i , getHeight(heightfield, pitch, i , j
), j );
vector3 v2(i + 1, getHeight(heightfield, pitch, i + 1, j
), j );
vector3 v3(i , getHeight(heightfield, pitch, i , j +
1), j + 1);
vector3 v4(i + 1, getHeight(heightfield, pitch, i + 1, j +
1), j + 1);
v1.x*=grid_size;
v1.z*=grid_size;
v2.x*=grid_size;
v2.z*=grid_size;
v3.x*=grid_size;
v3.z*=grid_size;
v4.x*=grid_size;
v4.z*=grid_size;
vector3 contact1;
bool hit = closestPointOnTriangleSurface(v1, v2, v3,
centre_v, contact1, radius);
hits[i - left][j - top].hit_nw_face = hit;
float distance = get_distance(contact1, centre[0],
centre[1], centre[2]);
if ((distance < radius) && hit && (num_contacts < 8) &&
!alreadyInContacts(contact, num_contacts, contact1,
skip))
{
float x = contact1.x;
float y = contact1.y;
float z = contact1.z;
vector3 normal(x - centre[0], y - centre[1], z -
centre[2]);
normal.normalize();
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;
vector3 contact_point(x,y,z);
CONTACT(contact, num_contacts * skip)->pos[0] =
contact_point.x;
CONTACT(contact, num_contacts * skip)->pos[1] =
contact_point.y;
CONTACT(contact, num_contacts * skip)->pos[2] =
contact_point.z;
CONTACT(contact, num_contacts * skip)->depth = radius -
distance;
CONTACT(contact, num_contacts * skip)->g1 = o1;
CONTACT(contact, num_contacts * skip)->g2 = o2;
num_contacts ++;
}
hit = closestPointOnTriangleSurface(v2, v4, v3, centre_v,
contact1, radius);
hits[i - left][j - top].hit_se_face = hit;
distance = get_distance(contact1, centre[0], centre[1],
centre[2]);
if ((distance < radius) && hit && (num_contacts < 8) &&
!alreadyInContacts(contact, num_contacts, contact1,
skip))
{
float x = contact1.x;
float y = contact1.y;
float z = contact1.z;
vector3 normal(x - centre[0], y - centre[1], z -
centre[2]);
normal.normalize();
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;
vector3 contact_point(x,y,z);
CONTACT(contact, num_contacts * skip)->pos[0] =
contact_point.x;
CONTACT(contact, num_contacts * skip)->pos[1] =
contact_point.y;
CONTACT(contact, num_contacts * skip)->pos[2] =
contact_point.z;
CONTACT(contact, num_contacts * skip)->depth = radius -
distance;
CONTACT(contact, num_contacts * skip)->g1 = o1;
CONTACT(contact, num_contacts * skip)->g2 = o2;
num_contacts ++;
}
}
}
}
for (j = top; j <= bottom; j++)
{
for (int i = left; i <= right; i++)
{
if ((i > 1) && (i < l->landscape_width - 1) && (j > 1) && (j <
l->landscape_height - 1))
{
vector3 v1(i , getHeight(heightfield, pitch, i , j
), j );
vector3 v2(i + 1, getHeight(heightfield, pitch, i + 1, j
), j );
vector3 v3(i , getHeight(heightfield, pitch, i , j +
1), j + 1);
vector3 v4(i + 1, getHeight(heightfield, pitch, i + 1, j +
1), j + 1);
v1.x*=grid_size;
v1.z*=grid_size;
v2.x*=grid_size;
v2.z*=grid_size;
v3.x*=grid_size;
v3.z*=grid_size;
v4.x*=grid_size;
v4.z*=grid_size;
vector3 contact1;
if (!hits[i - left ][j - top ].hit_nw_face &&
!hits[i - left ][j - top ].hit_se_face &&
((i != left) && !hits[i - left - 1 ][j - top
].hit_se_face) &&
((j != top ) && !hits[i - left ][j - top - 1
].hit_se_face))
{
contact1 = closestPointOnTriangle(v1, v2, v3, centre_v);
float distance = get_distance(contact1, centre[0],
centre[1], centre[2]);
if ((distance < radius) && (num_contacts < 8) &&
!alreadyInContacts(contact, num_contacts, contact1,
skip))
{
float x = contact1.x;
float y = contact1.y;
float z = contact1.z;
vector3 normal(x - centre[0], y - centre[1], z -
centre[2]);
normal.normalize();
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;
vector3 contact_point(x,y,z);
CONTACT(contact, num_contacts * skip)->pos[0] =
contact_point.x;
CONTACT(contact, num_contacts * skip)->pos[1] =
contact_point.y;
CONTACT(contact, num_contacts * skip)->pos[2] =
contact_point.z;
CONTACT(contact, num_contacts * skip)->depth =
radius - distance;
CONTACT(contact, num_contacts * skip)->g1 = o1;
CONTACT(contact, num_contacts * skip)->g2 = o2;
num_contacts ++;
}
contact1 = closestPointOnTriangle(v2, v4, v3, centre_v);
distance = get_distance(contact1, centre[0], centre[1],
centre[2]);
if ((distance < radius) && (num_contacts < 8) &&
!alreadyInContacts(contact, num_contacts, contact1,
skip))
{
float x = contact1.x;
float y = contact1.y;
float z = contact1.z;
vector3 normal(x - centre[0], y - centre[1], z -
centre[2]);
normal.normalize();
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;
vector3 contact_point(x,y,z);
CONTACT(contact, num_contacts * skip)->pos[0] =
contact_point.x;
CONTACT(contact, num_contacts * skip)->pos[1] =
contact_point.y;
CONTACT(contact, num_contacts * skip)->pos[2] =
contact_point.z;
CONTACT(contact, num_contacts * skip)->depth =
radius - distance;
CONTACT(contact, num_contacts * skip)->g1 = o1;
CONTACT(contact, num_contacts * skip)->g2 = o2;
num_contacts ++;
}
}
}
}
}
return num_contacts;
}
>From: Nate W <coding@natew.com>
>To: ode@q12.org
>Subject: Re: [ODE] Extracting terrain data from Demeter
>Date: Fri, 15 Aug 2003 01:27:29 -0700 (PDT)
>
>On Fri, 15 Aug 2003, Jan Ekholm wrote:
>
> > It refers to an example of how to extract Demeter terrain data, but
> > unfortunately gives no hint as to where that example can be found. I'd
> > rather avoid downloading the whole archive if someone happens to know
> > which month/year/thread to look for.
>
>http://q12.org/pipermail/ode/2003-January/002687.html
>
>Google searches the ODE mailing list really well if you put "site:q12.org"
>in the search string. I found that post with this query:
>http://www.google.com/search?q=site%3Aq12.org+demeter+nate&btnG=Google+Search
>
>Of course, I had the added advantage of knowing who wrote that post, and
>that made it a little easier to track down. :-)
>
> > Also, if someone has experience with this and think it is a stupid
> > idea or combination of tools to use, please let me know that before I
> > invest a lot of time in something that will fail. :)
>
>I'm using ODE and Demeter in my project, they work pretty well together.
>However, I think I got the diagonals wrong in the code I'm using (and thus
>in the sample code). Like, Demeter turns squares into two triangles by
>putting a diagonal edge, and I've got the diagonal going between the wrong
>vertices. At least I think that's the problem.... In sharp valleys it's
>sometimes clear that what's rendered isn't quite what's being collided.
>Most of the time it works great though, so I've been able to put off
>fixing this for a very long time. :-)
>
>--
>
>Nate Waddoups
>Redmond WA USA
>http://www.natew.com
>
>
>_______________________________________________
>ODE mailing list
>ODE@q12.org
>http://q12.org/mailman/listinfo/ode
_________________________________________________________________
Formula 1 fan? This is for you!
http://server1.msn.co.in/sp03/formula2003/photogallery/gallery/gal3.asp Best
pics of the year.