static void printGeom (PrintingContext &c, dxGeom *g)
{
    unsigned long category = dGeomGetCategoryBits (g);
    if (category != (unsigned long)(~0)) {
        c.printIndent();
        fprintf (c.file,"category_bits = %lu\n",category);
    }
    unsigned long collide = dGeomGetCollideBits (g);
    if (collide != (unsigned long)(~0)) {
        c.printIndent();
        fprintf (c.file,"collide_bits = %lu\n",collide);
    }
    if (!dGeomIsEnabled (g)) {
        c.print ("disabled",1);
    }
    switch (g->type) {
        case dSphereClass: printSphere (c,g); break;
        case dBoxClass: printBox (c,g); break;
        case dCapsuleClass: printCapsule (c,g); break;
        case dCylinderClass: printCylinder (c,g); break;
        case dPlaneClass: printPlane (c,g); break;
        case dRayClass: printRay (c,g); break;
        case dConvexClass: printConvex (c,g); break;
        case dTriMeshClass: printTriMesh (c,g); break;
        case dHeightfieldClass: printHeightfieldClass (c,g); break;
    }
}
/***************************************************************************\
 *                           Instance methods                              *
\***************************************************************************/
void PhysicsPlaneGeom::onCreate(const PhysicsPlaneGeom *)
{
	PhysicsPlaneGeomPtr tmpPtr(*this);
	tmpPtr->id = dCreatePlane(0, 0, 0, 1, 0);
	PhysicsPlaneGeomBase::setParams(tmpPtr->getParams());
    PhysicsGeomBase::setCategoryBits(dGeomGetCategoryBits(id));
    PhysicsGeomBase::setCollideBits(dGeomGetCollideBits(id));
}
Beispiel #3
0
int get_phys_geom_attr_i(dGeomID geom, int p)
{
    switch (p)
    {
    case GEOM_ATTR_CATEGORY: return dGeomGetCategoryBits(geom);
    case GEOM_ATTR_COLLIDER: return dGeomGetCollideBits (geom);
    case GEOM_ATTR_RESPONSE: return get_data(geom)->response;
    case GEOM_ATTR_CALLBACK: return get_data(geom)->callback;
    }
    return 0;
}
Beispiel #4
0
/*-------------------------------------------------------------------------*\
-  public                                                                 -
\*-------------------------------------------------------------------------*/
void PhysicsTriMeshGeom::onCreate(const PhysicsTriMeshGeom *)
{
    PhysicsTriMeshGeomPtr tmpPtr(*this);
    tmpPtr->id = dCreateTriMesh(0, 0, 0, 0, 0);
    data = 0;
    numVertices = 0;
    numFaces = 0;
    vertexData = 0;
    faceData = 0;
    normalData = 0;
    geoNode=NullFC;
    PhysicsGeomBase::setCategoryBits(dGeomGetCategoryBits(id));
    PhysicsGeomBase::setCollideBits(dGeomGetCollideBits(id));
}
Beispiel #5
0
static void callback(void *data, dGeomID o1, dGeomID o2)
{
    dBodyID b1 = dGeomGetBody(o1);
    dBodyID b2 = dGeomGetBody(o2);

    if (b1 && b2 && dAreConnectedExcluding(b1, b2, dJointTypeContact))
        return;

    /* Two geoms associated with the same body do not collide. */

    if (b1 == 0 || b2 == 0 || b1 != b2)
    {
        dContact contact[MAX_CONTACTS];
        size_t sz = sizeof (dContact);
        int i, n;

        /* Find and enumerate all collision points. */

        if ((n = dCollide(o1, o2, MAX_CONTACTS, &contact[0].geom, sz)))
        {
            struct geom_data *d1 = get_data(o1);
            struct geom_data *d2 = get_data(o2);

            /* Compute collision parameters from geom parameters. */

            dReal bounce    = MAX(d1->bounce,   d2->bounce);
            dReal friction  = MIN(d1->friction, d2->friction);
            dReal soft_erp  = MIN(d1->soft_erp, d2->soft_erp);
            dReal soft_cfm  = MAX(d1->soft_cfm, d2->soft_cfm);

            unsigned long category1 = dGeomGetCategoryBits(o1);
            unsigned long category2 = dGeomGetCategoryBits(o2);

            if (b1) dBodyEnable(b1);
            if (b2) dBodyEnable(b2);

            /* Create a contact joint for each collision, if requsted. */

            if ((category1 & d2->response) ||
                (category2 & d1->response))
                for (i = 0; i < n; ++i)
                    if (dGeomGetClass(contact[0].geom.g1) != dRayClass &&
                        dGeomGetClass(contact[0].geom.g2) != dRayClass)
                    {
                        dJointID c;

                        contact[i].surface.mode = dContactBounce
                                                | dContactSoftCFM
                                                | dContactSoftERP;

                        contact[i].surface.mu         = friction;
                        contact[i].surface.bounce     = bounce;
                        contact[i].surface.soft_cfm   = soft_cfm;
                        contact[i].surface.soft_erp   = soft_erp;
                        contact[i].surface.bounce_vel = (dReal) 0.10;

                        c = dJointCreateContact(world, group, contact + i);
                        dJointAttach(c, b1, b2);
                    }

            /* Report contacts to the Lua script, if requested. */

            if ((category1 & d2->callback) ||
                (category2 & d1->callback))
                for (i = 0; i < n; ++i)
                {
                    float p[3];
                    float v[3];

                    p[0] = (float) contact[i].geom.pos[0];
                    p[1] = (float) contact[i].geom.pos[1];
                    p[2] = (float) contact[i].geom.pos[2];

                    v[0] = (float) contact[i].geom.normal[0];
                    v[1] = (float) contact[i].geom.normal[1];
                    v[2] = (float) contact[i].geom.normal[2];

                    do_contact_script(d1->entity, d2->entity,
                                      p, v, (float) contact[i].geom.depth);
                }
        }
    }
}
Beispiel #6
0
unsigned long ODE_Particle::getCategoryBits()
{                        
    return dGeomGetCategoryBits(geom);           
}
void PhysicsCapsuleGeom::onCreate(const PhysicsCapsuleGeom *)
{
	_GeomID = dCreateCapsule(0, getRadius(), getLength());
    setCategoryBits(dGeomGetCategoryBits(_GeomID));
    setCollideBits(dGeomGetCollideBits(_GeomID));
}
void PhysicsPlaneGeom::onCreate(const PhysicsPlaneGeom *)
{
    _GeomID = dCreatePlane(0, getParameters().x(), getParameters().y(), getParameters().z(), getParameters().w());
    setCategoryBits(dGeomGetCategoryBits(_GeomID));
    setCollideBits(dGeomGetCollideBits(_GeomID));
}
Beispiel #9
0
unsigned long ODEGeom::getGeomCategoryBits()
{                        
    return dGeomGetCategoryBits(geom);           
}
void PhysicsSpace::collisionCallback (dGeomID o1, dGeomID o2)
{
    StatRealElem *NCollisionTestsStatElem = StatCollector::getGlobalElem(PhysicsHandler::statNCollisionTests);
    if(NCollisionTestsStatElem) { NCollisionTestsStatElem->add(1.0f); }

    if (dGeomIsSpace (o1) || dGeomIsSpace (o2))
    {
        // colliding a space with something
        dSpaceCollide2 (o1,o2,reinterpret_cast<void *>(this),&PhysicsSpace::collisionCallback);
        // collide all geoms internal to the space(s)
        if (dGeomIsSpace (o1)) dSpaceCollide (dGeomGetSpace(o1),reinterpret_cast<void *>(this),&PhysicsSpace::collisionCallback);
        if (dGeomIsSpace (o2)) dSpaceCollide (dGeomGetSpace(o2),reinterpret_cast<void *>(this),&PhysicsSpace::collisionCallback);
    }
    else
    {
        _DiscardCollision = false;

        // colliding two non-space geoms, so generate contact
        // points between o1 and o2
        Int32 numContacts = dCollide(o1, o2, _ContactJoints.size(), 
            &(_ContactJoints[0].geom), sizeof(dContact));
    
        StatRealElem *NCollisionsStatElem = StatCollector::getGlobalElem(PhysicsHandler::statNCollisions);
        if(NCollisionsStatElem) { NCollisionsStatElem->add(static_cast<Real32>(numContacts)); }

        if(numContacts>0)
        {
            Vec3f v1,v2,normal;
            Pnt3f position;
            dVector3 odeVec;
            Real32 projectedNormalSpeed;
            for (Int32 i=0; i < numContacts; i++)
            {
                normal += Vec3f(&_ContactJoints[i].geom.normal[0]);
                position += Vec3f(&_ContactJoints[i].geom.pos[0]);
                if(dGeomGetBody(o1))
                {
                    dBodyGetPointVel(dGeomGetBody(o1), _ContactJoints[i].geom.pos[0], _ContactJoints[i].geom.pos[1], _ContactJoints[i].geom.pos[2],odeVec);
                    v1 += Vec3f(&odeVec[0]);
                }
                if(dGeomGetBody(o2))
                {
                    dBodyGetPointVel(dGeomGetBody(o2), _ContactJoints[i].geom.pos[0], _ContactJoints[i].geom.pos[1], _ContactJoints[i].geom.pos[2],odeVec);
                    v2 += Vec3f(&odeVec[0]);
                }
            }

            normal = normal * (1.0f/static_cast<Real32>(numContacts));
            position = position * (1.0f/static_cast<Real32>(numContacts));
            v1 = v1 * (1.0f/static_cast<Real32>(numContacts));
            v2 = v2 * (1.0f/static_cast<Real32>(numContacts));
            projectedNormalSpeed = (v1+v2).projectTo(normal);

            //TODO: Add a way to get the PhysicsGeomUnrecPtr from the GeomIDs so that the PhysicsGeomUnrecPtr can be 
            //sent to the collision event
            produceCollision(position,
                                normal,
                                NULL,
                                NULL,
                                dGeomGetCategoryBits(o1),
                                dGeomGetCollideBits (o1),
                                dGeomGetCategoryBits(o2),
                                dGeomGetCollideBits (o2),
                                v1,
                                v2,
                                osgAbs(projectedNormalSpeed));

            UInt32 Index(0);
            for(; Index<_CollisionListenParamsVec.size() ; ++Index)
            {
                if((dGeomGetCategoryBits(o1) & _CollisionListenParamsVec[Index]._Category) || (dGeomGetCategoryBits(o2) & _CollisionListenParamsVec[Index]._Category))
                {
                    break;
                }
            }
            if(Index < _CollisionListenParamsVec.size())
            {
                for(UInt32 i(0); i<_CollisionListenParamsVec.size() ; ++i)
                {
                    if( ((dGeomGetCategoryBits(o1) & _CollisionListenParamsVec[i]._Category) || (dGeomGetCategoryBits(o2) & _CollisionListenParamsVec[i]._Category)) &&
                         (osgAbs(projectedNormalSpeed) >= _CollisionListenParamsVec[i]._SpeedThreshold)
                        )
                    {
                        //TODO: Add a way to get the PhysicsGeomUnrecPtr from the GeomIDs so that the PhysicsGeomUnrecPtr can be 
                        //sent to the collision event
                        produceCollision(_CollisionListenParamsVec[i]._Listener,
                                position,
                                normal,
                                NULL,
                                NULL,
                                dGeomGetCategoryBits(o1),
                                dGeomGetCollideBits (o1),
                                dGeomGetCategoryBits(o2),
                                dGeomGetCollideBits (o2),
                                v1,
                                v2,
                                osgAbs(projectedNormalSpeed));
                    }
                }
            }
        }
        if(!_DiscardCollision)
        {
            // add these contact points to the simulation
            for (Int32 i=0; i < numContacts; i++)
            {

                getCollisionContact(dGeomGetCategoryBits(o1), dGeomGetCategoryBits(o2))->updateODEContactJoint(_ContactJoints[i]);
                dJointID jointId = dJointCreateContact(_CollideWorldID, 
                    _ColJointGroupId, 
                    &_ContactJoints[i]);

                dJointAttach(jointId, dGeomGetBody(o1), dGeomGetBody(o2));
            }
        }
    }
}
void SimpleTrackedVehicleEnvironment::nearCallbackGrouserTerrain(dGeomID o1, dGeomID o2) {
    dBodyID b1 = dGeomGetBody(o1);
    dBodyID b2 = dGeomGetBody(o2);
    if(b1 && b2 && dAreConnectedExcluding(b1, b2, dJointTypeContact)) return;

    // body of the whole vehicle
    dBodyID vehicleBody = ((SimpleTrackedVehicle*)this->v)->vehicleBody;

    unsigned long geom1Categories = dGeomGetCategoryBits(o1);

    // speeds of the belts
    const dReal leftBeltSpeed = ((SimpleTrackedVehicle*)this->v)->leftTrack->getVelocity();
    const dReal rightBeltSpeed = ((SimpleTrackedVehicle*)this->v)->rightTrack->getVelocity();

    dReal beltSpeed = 0; // speed of the belt which is in collision and examined right now
    if (geom1Categories & Category::LEFT) {
        beltSpeed = leftBeltSpeed;
    } else {
        beltSpeed = rightBeltSpeed;
    }

    // the desired linear and angular speeds (set by desired track velocities)
    const dReal linearSpeed = (leftBeltSpeed + rightBeltSpeed) / 2;
    const dReal angularSpeed = (leftBeltSpeed - rightBeltSpeed) * steeringEfficiency / tracksDistance;

    // radius of the turn the robot is doing
    const dReal desiredRotationRadiusSigned = (fabs(angularSpeed) < 0.1) ?
                                                dInfinity : // is driving straight
                                                ((fabs(linearSpeed) < 0.1) ?
                                                    0 : // is rotating about a single point
                                                    linearSpeed / angularSpeed // general movement
                                                );


    dVector3 yAxisGlobal; // vector pointing from vehicle body center in the direction of +y axis
    dVector3 centerOfRotation; // at infinity if driving straight, so we need to distinguish the case
    { // compute the center of rotation
        dBodyVectorToWorld(vehicleBody, 0, 1, 0, yAxisGlobal);

        dCopyVector3(centerOfRotation, yAxisGlobal);
        // make the unit vector as long as we need (and change orientation if needed; the radius is a signed number)
        dScaleVector3(centerOfRotation, desiredRotationRadiusSigned);

        const dReal *vehicleBodyPos = dBodyGetPosition(vehicleBody);
        dAddVectors3(centerOfRotation, centerOfRotation, vehicleBodyPos);
    }

    int maxContacts = 20;
    dContact contact[maxContacts];
    int numContacts = dCollide(o1, o2, maxContacts, &contact[0].geom, sizeof(dContact));

    for(size_t i = 0; i < numContacts; i++) {
        dVector3 contactInVehiclePos; // position of the contact point relative to vehicle body
        dBodyGetPosRelPoint(vehicleBody, contact[i].geom.pos[0], contact[i].geom.pos[1], contact[i].geom.pos[2], contactInVehiclePos);

        dVector3 beltDirection; // vector tangent to the belt pointing in the belt's movement direction
        dCalcVectorCross3(beltDirection, contact[i].geom.normal, yAxisGlobal);
        if (beltSpeed > 0) {
            dNegateVector3(beltDirection);
        }

        if (desiredRotationRadiusSigned != dInfinity) { // non-straight drive

            dVector3 COR2Contact; // vector pointing from the center of rotation to the contact point
            dSubtractVectors3(COR2Contact, contact[i].geom.pos, centerOfRotation);
            // the friction force should be perpendicular to COR2Contact
            dCalcVectorCross3(contact[i].fdir1, contact[i].geom.normal, COR2Contact);

            const dReal linearSpeedSignum = (fabs(linearSpeed) > 0.1) ? sgn(linearSpeed) : 1;

            // contactInVehiclePos[0] > 0 means the contact is in the front part of the track
            if (sgn(angularSpeed) * sgn(dCalcVectorDot3(yAxisGlobal, contact[i].fdir1)) !=
                    sgn(contactInVehiclePos[0]) * linearSpeedSignum) {
                dNegateVector3(contact[i].fdir1);
            }

        } else { // straight drive

            dCalcVectorCross3(contact[i].fdir1, contact[i].geom.normal, yAxisGlobal);

            if (dCalcVectorDot3(contact[i].fdir1, beltDirection) < 0) {
                dNegateVector3(contact[i].fdir1);
            }

        }

        // use friction direction and motion1 to simulate the track movement
        contact[i].surface.mode = dContactFDir1 | dContactMotion1 | dContactMu2;
        contact[i].surface.mu = 0.5;
        contact[i].surface.mu2 = 10;
        // the dot product <beltDirection,fdir1> is the cosine of the angle they form (because both are unit vectors)
        contact[i].surface.motion1 = -dCalcVectorDot3(beltDirection, contact[i].fdir1) * fabs(beltSpeed) * 0.07;

        // friction force visualization
        dMatrix3 forceRotation;
        dVector3 vec;
        dBodyVectorToWorld(vehicleBody, 1, 0, 0, vec);
        dRFrom2Axes(forceRotation, contact[i].fdir1[0], contact[i].fdir1[1], contact[i].fdir1[2], vec[0], vec[1], vec[2]);
        posr data;
        dCopyVector3(data.pos, contact[i].geom.pos);
        dCopyMatrix4x3(data.R, forceRotation);
        forces.push_back(data);

        dJointID c = dJointCreateContact(this->world, this->contactGroup, &contact[i]);
        dJointAttach(c, b1, b2);
        if(!isValidCollision(o1, o2, contact[i]))
            this->badCollision = true;
        if(config.contact_grouser_terrain.debug)
            this->contacts.push_back(contact[i].geom);
    }
}