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