void YGEBodyAsset::update(long delta){
		if(!hasBody){

			createBody();
		} else {

		double second = delta / 1000000.0f;
		double m = 1; //second * 1000; 

		dBodySetAngularDamping(bodyId, angularDamping * second);
		dBodySetLinearDamping(bodyId, linearDamping * second);

		dBodyAddTorque(bodyId, torqueAccum.x * m, torqueAccum.y * m, torqueAccum.z * m);
		dBodyAddForce(bodyId, forceAccum.x * m, forceAccum.y * m, forceAccum.z * m);

		
		const dReal* pos = dBodyGetPosition (bodyId);
		const dReal* rot = dBodyGetQuaternion(bodyId);
		parent->setPosition(YGEMath::Vector3(pos[0], pos[1], pos[2]));
		parent->setOrientation(YGEMath::Quaternion(rot[0], rot[1], rot[2], rot[3]));
		}
	}
示例#2
0
int main(int argc, char* argv[])
{
    //-----------------------------------------------------------------------
    // INITIALIZATION
    //-----------------------------------------------------------------------

    printf ("\n");
    printf ("-----------------------------------\n");
    printf ("CHAI3D\n");
    printf ("Demo: 43-ODE-tool\n");
    printf ("Copyright 2003-2011\n");
    printf ("-----------------------------------\n");
    printf ("\n\n");
    printf ("Instructions:\n\n");
    printf ("- Use haptic device and user switch to manipulate cubes \n");
    printf ("\n\n");
    printf ("Keyboard Options:\n\n");
    printf ("[h] - Display help menu\n");;
    printf ("[1] - Enable gravity\n");
    printf ("[2] - Disable gravity\n");
    printf ("\n");
    printf ("[3] - decrease linear haptic gain\n");
    printf ("[4] - increase linear haptic gain\n");
    printf ("[5] - decrease angular haptic gain\n");
    printf ("[6] - increase angular haptic gain\n");
    printf ("\n");
    printf ("[7] - decrease linear stiffness\n");
    printf ("[8] - increase linear stiffness\n");
    printf ("[9] - decrease angular stiffness\n");
    printf ("[0] - increase angular stiffness\n");
    printf ("\n");
    printf ("[x] - Exit application\n");
    printf ("\n\n");

    // parse first arg to try and locate resources
    resourceRoot = string(argv[0]).substr(0,string(argv[0]).find_last_of("/\\")+1);


    //-----------------------------------------------------------------------
    // 3D - SCENEGRAPH
    //-----------------------------------------------------------------------

    // create a new world.
    world = new cWorld();

    // set the background color of the environment
    // the color is defined by its (R,G,B) components.
    world->setBackgroundColor(0.0, 0.0, 0.0);

    // create a camera and insert it into the virtual world
    camera = new cCamera(world);
    world->addChild(camera);

    // position and oriente the camera
    camera->set( cVector3d (3.0, 0.0, 0.3),    // camera position (eye)
                 cVector3d (0.0, 0.0, 0.0),    // lookat position (target)
                 cVector3d (0.0, 0.0, 1.0));   // direction of the "up" vector

    // set the near and far clipping planes of the camera
    // anything in front/behind these clipping planes will not be rendered
    camera->setClippingPlanes(0.01, 10.0);
    camera->setUseShadowCasting(false);

    // create a light source and attach it to the camera
    light = new cSpotLight(world);
    camera->addChild(light);                   // attach light to camera
    light->setEnabled(true);                   // enable light source
    light->setLocalPos(cVector3d( 0.0, 0.5, 0.0));  // position the light source
    light->setDir(cVector3d(-3.0,-0.5, 0.0));  // define the direction of the light beam
    light->m_ambient.set(0.6, 0.6, 0.6);
    light->m_diffuse.set(0.8, 0.8, 0.8);
    light->m_specular.set(0.8, 0.8, 0.8);


    frame = new cGenericObject();
    //world->addChild(frame);
    frame->setShowFrame(true);
    line = new cShapeLine(cVector3d(0,0,0), cVector3d(0,0,0));
    //world->addChild(line);

    //-----------------------------------------------------------------------
    // 2D - WIDGETS
    //-----------------------------------------------------------------------

    // create a 2D bitmap logo
    logo = new cBitmap();

    // add logo to the front plane
    camera->m_frontLayer->addChild(logo);

    // load a "chai3d" bitmap image file
    logo->setImage (NEW_CHAI3D_LOGO());

    // position the logo at the bottom left of the screen (pixel coordinates)
    logo->setLocalPos(10, 10, 0);

    // scale the logo along its horizontal and vertical axis
    logo->setZoom(0.25, 0.25);

    // here we replace all black pixels (0,0,0) of the logo bitmap
    // with transparent black pixels (0, 0, 0, 0). This allows us to make
    // the background of the logo look transparent.
    logo->m_image->setTransparentColor(0x00, 0x00, 0x00, 0x00);

    // enable transparency
    logo->setUseTransparency(true);


    //-----------------------------------------------------------------------
    // HAPTIC DEVICES / TOOLS
    //-----------------------------------------------------------------------

    // create a haptic device handler
    handler = new cHapticDeviceHandler();

    // get access to the first available haptic device
    handler->getDevice(hapticDevice, 0);

    // retrieve information about the current haptic device
    cHapticDeviceInfo info;
    if (hapticDevice)
    {
        info = hapticDevice->getSpecifications();
    }

    // read the scale factor between the physical workspace of the haptic
    // device and the virtual workspace defined for the tool
    workspaceScaleFactor = 1.5 / info.m_workspaceRadius;

    //-----------------------------------------------------------------------
    // COMPOSE THE VIRTUAL SCENE
    //-----------------------------------------------------------------------

    // create an ODE world to simulate dynamic bodies
    ODEWorld = new cODEWorld(world);

    // add ODE world as a node inside world
    world->addChild(ODEWorld);

    // set some gravity
    ODEWorld->setGravity(cVector3d(0.0, 0.0, -9.81));

    // create a new ODE object that is automatically added to the ODE world
    ODEBody0 = new cODEGenericBody(ODEWorld);
    ODEBody1 = new cODEGenericBody(ODEWorld);
    ODEBody2 = new cODEGenericBody(ODEWorld);

    // create a virtual mesh  that will be used for the geometry
    // representation of the dynamic body
    cMesh* object0 = new cMesh();
    cMesh* object1 = new cMesh();
    cMesh* object2 = new cMesh();

    // crate a cube mesh
    double boxSize = 0.4;
    createCube(object0, boxSize);
    createCube(object1, boxSize);
    createCube(object2, boxSize);

    // define some material properties for each cube
    cMaterial mat0, mat1, mat2;
    mat0.m_ambient.set(0.8, 0.1, 0.4);
    mat0.m_diffuse.set(1.0, 0.15, 0.5);
    mat0.m_specular.set(1.0, 0.2, 0.8);
    mat0.setDynamicFriction(0.8);
    mat0.setStaticFriction(0.8);
    object0->setMaterial(mat0);

    mat1.m_ambient.set(0.2, 0.6, 0.0);
    mat1.m_diffuse.set(0.2, 0.8, 0.0);
    mat1.m_specular.set(0.2, 1.0, 0.0);
    mat1.setDynamicFriction(0.8);
    mat1.setStaticFriction(0.8);
    object1->setMaterial(mat1);

    mat2.m_ambient.set(0.0, 0.2, 0.6);
    mat2.m_diffuse.set(0.0, 0.2, 0.8);
    mat2.m_specular.set(0.0, 0.2, 1.0);
    mat2.setDynamicFriction(0.8);
    mat2.setStaticFriction(0.8);
    object2->setMaterial(mat2);

    // add mesh to ODE object
    ODEBody0->setImageModel(object0);
    ODEBody1->setImageModel(object1);
    ODEBody2->setImageModel(object2);

    // create a dynamic model of the ODE object. Here we decide to use a box just like
    // the object mesh we just defined
    ODEBody0->createDynamicBox(boxSize, boxSize, boxSize);
    ODEBody1->createDynamicBox(boxSize, boxSize, boxSize, false, cVector3d(1,1,1));
    ODEBody2->createDynamicBox(boxSize, boxSize, boxSize);

    // define some mass properties for each cube
    ODEBody0->setMass(0.05);
    ODEBody1->setMass(0.05);
    ODEBody2->setMass(0.05);

    // set position of each cube
    cVector3d tmpvct;
    tmpvct = cVector3d(0.0,-0.6, -0.5);
    ODEBody0->setPosition(tmpvct);
    tmpvct = cVector3d(0.0, 0.6, -0.5);
    ODEBody1->setPosition(tmpvct);
    tmpvct = cVector3d(0.0, 0.0, -0.5);
    ODEBody2->setPosition(tmpvct);

    // rotate central cube of 45 degrees (just to show hoe this works!)
    cMatrix3d rot;
    rot.identity();
    rot.rotateAboutGlobalAxisRad(cVector3d(0,0,1), cDegToRad(45));
    ODEBody0->setRotation(rot);

    // we create 6 static walls to contains the 3 cubes within a limited workspace
    ODEGPlane0 = new cODEGenericBody(ODEWorld);
    ODEGPlane1 = new cODEGenericBody(ODEWorld);
    ODEGPlane2 = new cODEGenericBody(ODEWorld);
    ODEGPlane3 = new cODEGenericBody(ODEWorld);
    ODEGPlane4 = new cODEGenericBody(ODEWorld);
    ODEGPlane5 = new cODEGenericBody(ODEWorld);

    double size = 1.0;
    ODEGPlane0->createStaticPlane(cVector3d(0.0, 0.0,  2.0 *size), cVector3d(0.0, 0.0 ,-1.0));
    ODEGPlane1->createStaticPlane(cVector3d(0.0, 0.0, -size), cVector3d(0.0, 0.0 , 1.0));
    ODEGPlane2->createStaticPlane(cVector3d(0.0,  size, 0.0), cVector3d(0.0,-1.0, 0.0));
    ODEGPlane3->createStaticPlane(cVector3d(0.0, -size, 0.0), cVector3d(0.0, 1.0, 0.0));
    ODEGPlane4->createStaticPlane(cVector3d( size, 0.0, 0.0), cVector3d(-1.0,0.0, 0.0));
    ODEGPlane5->createStaticPlane(cVector3d(-0.8 * size, 0.0, 0.0), cVector3d( 1.0,0.0, 0.0));

    // create a virtual tool
    ODETool = new cODEGenericBody(ODEWorld);
    cMesh* objectTool = new cMesh();
    createCube(objectTool, boxSize);

    // define some material properties for each cube
    cMaterial matTool;
    matTool.m_ambient.set(0.4, 0.4, 0.4);
    matTool.m_diffuse.set(0.8, 0.8, 0.8);
    matTool.m_specular.set(1.0, 1.0, 1.0);
    matTool.setDynamicFriction(0.8);
    matTool.setStaticFriction(0.8);
    objectTool->setMaterial(matTool);

    // add mesh to ODE object
    ODETool->setImageModel(objectTool);
    ODETool->createDynamicBox(boxSize, boxSize, boxSize);

    // define some mass properties for each cube
    ODETool->setMass(0.01);
    dBodySetAngularDamping(ODETool->m_ode_body, 0.04);
    dBodySetLinearDamping(ODETool->m_ode_body, 0.04);


    //////////////////////////////////////////////////////////////////////////
    // Create some reflexion
    //////////////////////////////////////////////////////////////////////////

    // we create an intermediate node to which we will attach
    // a copy of the object located inside the world
    cGenericObject* reflexion = new cGenericObject();

    // set this object as a ghost node so that no haptic interactions or
    // collision detecting take place within the child nodes added to the
    // reflexion node.
    reflexion->setGhostEnabled(true);

    // add reflexion node to world
    world->addChild(reflexion);

    // turn off culling on each object (objects now get rendered on both sides)
    object0->setUseCulling(false, true);
    object1->setUseCulling(false, true);
    object2->setUseCulling(false, true);

    // create a symmetry rotation matrix (z-plane)
    cMatrix3d rotRefexion;
    rotRefexion.set(1.0, 0.0, 0.0,
                    0.0, 1.0, 0.0,
                    0.0, 0.0, -1.0);
    reflexion->setLocalRot(rotRefexion);
    reflexion->setLocalPos(0.0, 0.0, -2.005);

    // add objects to the world
    reflexion->addChild(ODEWorld);

    //////////////////////////////////////////////////////////////////////////
    // Create a Ground
    //////////////////////////////////////////////////////////////////////////

    // create mesh to model ground surface
    cMesh* ground = new cMesh();
    world->addChild(ground);

    // create 4 vertices (one at each corner)
    double groundSize = 2.0;
    int vertices0 = ground->newVertex(-groundSize, -groundSize, 0.0);
    int vertices1 = ground->newVertex( groundSize, -groundSize, 0.0);
    int vertices2 = ground->newVertex( groundSize,  groundSize, 0.0);
    int vertices3 = ground->newVertex(-groundSize,  groundSize, 0.0);

    // compose surface with 2 triangles
    ground->newTriangle(vertices0, vertices1, vertices2);
    ground->newTriangle(vertices0, vertices2, vertices3);

    // compute surface normals
    ground->computeAllNormals();

    // position ground at the right level
    ground->setLocalPos(0.0, 0.0, -1.0);

    // define some material properties and apply to mesh
    cMaterial matGround;
    matGround.setDynamicFriction(0.7);
    matGround.setStaticFriction(1.0);
    matGround.m_ambient.set(0.0, 0.0, 0.0);
    matGround.m_diffuse.set(0.0, 0.0, 0.0);
    matGround.m_specular.set(0.0, 0.0, 0.0);
    ground->setMaterial(matGround);

    // enable and set transparency level of ground
    ground->setTransparencyLevel(0.7);
    ground->setUseTransparency(true);


    //-----------------------------------------------------------------------
    // OPEN GL - WINDOW DISPLAY
    //-----------------------------------------------------------------------

    // initialize GLUT
    glutInit(&argc, argv);

    // retrieve the resolution of the computer display and estimate the position
    // of the GLUT window so that it is located at the center of the screen
    int screenW = glutGet(GLUT_SCREEN_WIDTH);
    int screenH = glutGet(GLUT_SCREEN_HEIGHT);
    int windowPosX = (screenW - WINDOW_SIZE_W) / 2;
    int windowPosY = (screenH - WINDOW_SIZE_H) / 2;

    // initialize the OpenGL GLUT window
    glutInitWindowPosition(windowPosX, windowPosY);
    glutInitWindowSize(WINDOW_SIZE_W, WINDOW_SIZE_H);
    glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
    glutCreateWindow(argv[0]);
    glutDisplayFunc(updateGraphics);
    glutKeyboardFunc(keySelect);
    glutReshapeFunc(resizeWindow);
    glutSetWindowTitle("CHAI3D");

    // create a mouse menu (right button)
    glutCreateMenu(menuSelect);
    glutAddMenuEntry("full screen", OPTION_FULLSCREEN);
    glutAddMenuEntry("window display", OPTION_WINDOWDISPLAY);
    glutAttachMenu(GLUT_RIGHT_BUTTON);


    //-----------------------------------------------------------------------
    // START SIMULATION
    //-----------------------------------------------------------------------

    // simulation in now running
    simulationRunning = true;

    // create a thread which starts the main haptics rendering loop
    cThread* hapticsThread = new cThread();
    hapticsThread->start(updateHaptics, CTHREAD_PRIORITY_HAPTICS);

    // start the main graphics rendering loop
    glutTimerFunc(30, graphicsTimer, 0);
    glutMainLoop();

    // close everything
    close();

    // exit
    return (0);
    }
void PhysicsBody::changed(ConstFieldMaskArg whichField, 
        UInt32            origin,
        BitVector         details)
{
    Inherited::changed(whichField, origin, details);

    //Do not respond to changes that have a Sync origin
    if(origin & ChangedOrigin::Sync)
    {
        return;
    }

    if(whichField & WorldFieldMask)
    {
        if(_BodyID != 0)
        {
            dBodyDestroy(_BodyID);
        }

        if(getWorld() != NULL)
        {
            _BodyID = dBodyCreate(getWorld()->getWorldID());
        }
    }
    if(   ((whichField & PositionFieldMask)
                || (whichField & WorldFieldMask))
            && getWorld() != NULL)
    {
        dBodySetPosition(_BodyID, getPosition().x(),getPosition().y(),getPosition().z());
    }
    if(   ((whichField & RotationFieldMask)
                || (whichField & WorldFieldMask))
            && getWorld() != NULL)
    {
        dMatrix3 rotation;
        Vec4f v1 =  getRotation()[0];
        Vec4f v2 =  getRotation()[1];
        Vec4f v3 =  getRotation()[2];
        rotation[0]   = v1.x();
        rotation[1]   = v1.y();
        rotation[2]   = v1.z();
        rotation[3]   = 0;
        rotation[4]   = v2.x();
        rotation[5]   = v2.y();
        rotation[6]   = v2.z();
        rotation[7]   = 0;
        rotation[8]   = v3.x();
        rotation[9]   = v3.y();
        rotation[10]  = v3.z();
        rotation[11]  = 0;
        dBodySetRotation(_BodyID, rotation);
    }
    if(   ((whichField & QuaternionFieldMask)
                || (whichField & WorldFieldMask))
            && getWorld() != NULL)
    {
        dQuaternion q;
        q[0]=getQuaternion().w();
        q[1]=getQuaternion().x();
        q[2]=getQuaternion().y();
        q[3]=getQuaternion().z();
        dBodySetQuaternion(_BodyID,q);
    }
    if(   ((whichField & LinearVelFieldMask)
                || (whichField & WorldFieldMask))
            && getWorld() != NULL)
    {
        dBodySetLinearVel(_BodyID, getLinearVel().x(),getLinearVel().y(),getLinearVel().z());
    }
    if(   ((whichField & AngularVelFieldMask)
                || (whichField & WorldFieldMask))
            && getWorld() != NULL)
    {
        dBodySetAngularVel(_BodyID, getAngularVel().x(),getAngularVel().y(),getAngularVel().z());
    }
    if(   ((whichField & ForceFieldMask)
                || (whichField & WorldFieldMask))
            && getWorld() != NULL)
    {
        dBodySetForce(_BodyID, getForce().x(),getForce().y(),getForce().z());
    }
    if(   ((whichField & TorqueFieldMask)
                || (whichField & WorldFieldMask))
            && getWorld() != NULL)
    {
        dBodySetTorque(_BodyID, getTorque().x(),getTorque().y(),getTorque().z());
    }
    if(   ((whichField & AutoDisableFlagFieldMask)
                || (whichField & WorldFieldMask))
            && getWorld() != NULL)
    {
        dBodySetAutoDisableFlag(_BodyID, getAutoDisableFlag());
    }
    if(   ((whichField & AutoDisableLinearThresholdFieldMask)
                || (whichField & WorldFieldMask))
            && getWorld() != NULL)
    {
        dBodySetAutoDisableLinearThreshold(_BodyID, getAutoDisableLinearThreshold());
    }
    if(   ((whichField & AutoDisableAngularThresholdFieldMask)
                || (whichField & WorldFieldMask))
            && getWorld() != NULL)
    {
        dBodySetAutoDisableAngularThreshold(_BodyID, getAutoDisableAngularThreshold());
    }
    if(   ((whichField & AutoDisableStepsFieldMask)
                || (whichField & WorldFieldMask))
            && getWorld() != NULL)
    {
        dBodySetAutoDisableSteps(_BodyID, getAutoDisableSteps());
    }
    if(   ((whichField & AutoDisableTimeFieldMask)
                || (whichField & WorldFieldMask))
            && getWorld() != NULL)
    {
        dBodySetAutoDisableTime(_BodyID, getAutoDisableTime());
    }
    if(   ((whichField & FiniteRotationModeFieldMask)
                || (whichField & WorldFieldMask))
            && getWorld() != NULL)
    {
        dBodySetFiniteRotationMode(_BodyID, getFiniteRotationMode());
    }
    if(   ((whichField & FiniteRotationModeFieldMask)
                || (whichField & WorldFieldMask))
            && getWorld() != NULL)
    {
        dBodySetFiniteRotationMode(_BodyID, getFiniteRotationMode());
    }
    if(   ((whichField & FiniteRotationAxisFieldMask)
                || (whichField & WorldFieldMask))
            && getWorld() != NULL)
    {
        dBodySetFiniteRotationAxis(_BodyID, getFiniteRotationAxis().x(),getFiniteRotationAxis().y(),getFiniteRotationAxis().z());
    }
    if(   ((whichField & GravityModeFieldMask)
                || (whichField & WorldFieldMask))
            && getWorld() != NULL)
    {
        dBodySetGravityMode(_BodyID, getGravityMode());
    }
    if(   ((whichField & LinearDampingFieldMask)
                || (whichField & WorldFieldMask))
            && getWorld() != NULL)
    {
        dBodySetLinearDamping(_BodyID, getLinearDamping());
    }
    if(   ((whichField & AngularDampingFieldMask)
                || (whichField & WorldFieldMask))
            && getWorld() != NULL)
    {
        dBodySetAngularDamping(_BodyID, getAngularDamping());
    }
    if(   ((whichField & LinearDampingThresholdFieldMask)
                || (whichField & WorldFieldMask))
            && getWorld() != NULL)
    {
        dBodySetLinearDampingThreshold(_BodyID, getLinearDampingThreshold());
    }
    if(   ((whichField & AngularDampingThresholdFieldMask)
                || (whichField & WorldFieldMask))
            && getWorld() != NULL)
    {
        dBodySetAngularDampingThreshold(_BodyID, getAngularDampingThreshold());
    }
    if(   ((whichField & MaxAngularSpeedFieldMask)
                || (whichField & WorldFieldMask))
            && getWorld() != NULL)
    {
        if(getMaxAngularSpeed() >= 0.0)
        {
            dBodySetMaxAngularSpeed(_BodyID, getMaxAngularSpeed());
        }
        else
        {
            dBodySetMaxAngularSpeed(_BodyID, dInfinity);
        }
    }

    if(   ((whichField & MassFieldMask)
                || (whichField & WorldFieldMask))
            && getWorld() != NULL)
    {
        dMass TheMass;
        dBodyGetMass(_BodyID, &TheMass);

        TheMass.mass = getMass();

        dBodySetMass(_BodyID, &TheMass);
    }
    if(   ((whichField & MassCenterOfGravityFieldMask)
                || (whichField & WorldFieldMask))
            && getWorld() != NULL)
    {
        //dMass TheMass;
        //dBodyGetMass(_BodyID, &TheMass);

        ////TheMass.c[0] = getMassCenterOfGravity().x();
        ////TheMass.c[1] = getMassCenterOfGravity().y();
        ////TheMass.c[2] = getMassCenterOfGravity().z();

        //Vec4f v1 =  getMassInertiaTensor()[0];
        //Vec4f v2 =  getMassInertiaTensor()[1];
        //Vec4f v3 =  getMassInertiaTensor()[2];
        //TheMass.I[0]   = v1.x();
        //TheMass.I[1]   = v1.y();
        //TheMass.I[2]   = v1.z();
        //TheMass.I[3]   = getMassCenterOfGravity().x();
        //TheMass.I[4]   = v2.x();
        //TheMass.I[5]   = v2.y();
        //TheMass.I[6]   = v2.z();
        //TheMass.I[7]   = getMassCenterOfGravity().y();
        //TheMass.I[8]   = v3.x();
        //TheMass.I[9]   = v3.y();
        //TheMass.I[10]  = v3.z();
        //TheMass.I[11]  = getMassCenterOfGravity().z();

        //dBodySetMass(_BodyID, &TheMass);
    }
    if(   ((whichField & MassInertiaTensorFieldMask)
                || (whichField & WorldFieldMask))
            && getWorld() != NULL)
    {
        dMass TheMass;
        dBodyGetMass(_BodyID, &TheMass);

        Vec4f v1 =  getMassInertiaTensor()[0];
        Vec4f v2 =  getMassInertiaTensor()[1];
        Vec4f v3 =  getMassInertiaTensor()[2];
        TheMass.I[0]   = v1.x();
        TheMass.I[1]   = v1.y();
        TheMass.I[2]   = v1.z();
        TheMass.I[3]   = 0;
        TheMass.I[4]   = v2.x();
        TheMass.I[5]   = v2.y();
        TheMass.I[6]   = v2.z();
        TheMass.I[7]   = 0;
        TheMass.I[8]   = v3.x();
        TheMass.I[9]   = v3.y();
        TheMass.I[10]  = v3.z();
        TheMass.I[11]  = 0;

        dBodySetMass(_BodyID, &TheMass);
    }
    if(   ((whichField & KinematicFieldMask)
                || (whichField & WorldFieldMask))
            && getWorld() != NULL)
    {
        if(getKinematic())
        {
            dBodySetKinematic(_BodyID);
        }
        else
        {
            dBodySetDynamic(_BodyID);
        }
    }
}
示例#4
0
void Simulation::staticCollisionCallback(Simulation* simulation, dGeomID geomId1, dGeomID geomId2)
{
  ASSERT(!dGeomIsSpace(geomId1));
  ASSERT(!dGeomIsSpace(geomId2));

#ifndef NDEBUG
  {
    dBodyID bodyId1 = dGeomGetBody(geomId1);
    dBodyID bodyId2 = dGeomGetBody(geomId2);
    ASSERT(bodyId1 || bodyId2);

    Body* body1 = bodyId1 ? (Body*)dBodyGetData(bodyId1) : 0;
    Body* body2 = bodyId2 ? (Body*)dBodyGetData(bodyId2) : 0;
    ASSERT(!body1 || !body2 || body1->rootBody != body2->rootBody);
  }
#endif

  dContact contact[32];
  int collisions = dCollide(geomId1, geomId2, 32, &contact[0].geom, sizeof(dContact));
  if(collisions <= 0)
    return;

  Geometry* geometry1 = (Geometry*)dGeomGetData(geomId1);
  Geometry* geometry2 = (Geometry*)dGeomGetData(geomId2);

  if(geometry1->collisionCallbacks && !geometry2->immaterial)
  {
    for(std::list<SimRobotCore2::CollisionCallback*>::iterator i = geometry1->collisionCallbacks->begin(), end = geometry1->collisionCallbacks->end(); i != end; ++i)
      (*i)->collided(*geometry1, *geometry2);
    if(geometry1->immaterial)
      return;
  }
  if(geometry2->collisionCallbacks && !geometry1->immaterial)
  {
    for(std::list<SimRobotCore2::CollisionCallback*>::iterator i = geometry2->collisionCallbacks->begin(), end = geometry2->collisionCallbacks->end(); i != end; ++i)
      (*i)->collided(*geometry2, *geometry1);
    if(geometry2->immaterial)
      return;
  }

  dBodyID bodyId1 = dGeomGetBody(geomId1);
  dBodyID bodyId2 = dGeomGetBody(geomId2);
  ASSERT(bodyId1 || bodyId2);

  float friction = 1.f;
  if(geometry1->material && geometry2->material)
  {
    if(!geometry1->material->getFriction(*geometry2->material, friction))
      friction = 1.f;

    float rollingFriction;
    if(bodyId1)
      switch(dGeomGetClass(geomId1))
      {
        case dSphereClass:
        case dCCylinderClass:
        case dCylinderClass:
          if(geometry1->material->getRollingFriction(*geometry2->material, rollingFriction))
          {
            dBodySetAngularDamping(bodyId1, 0.2);
            Vector3<> linearVel;
            ODETools::convertVector(dBodyGetLinearVel(bodyId1), linearVel);
            linearVel -= Vector3<>(linearVel).normalize(std::min(linearVel.abs(), rollingFriction * simulation->scene->stepLength));
            dBodySetLinearVel(bodyId1, linearVel.x, linearVel.y, linearVel.z);
          }
          break;
      }
    if(bodyId2)
      switch(dGeomGetClass(geomId2))
      {
        case dSphereClass:
        case dCCylinderClass:
        case dCylinderClass:
          if(geometry2->material->getRollingFriction(*geometry1->material, rollingFriction))
          {
            dBodySetAngularDamping(bodyId2, 0.2);
            Vector3<> linearVel;
            ODETools::convertVector(dBodyGetLinearVel(bodyId2), linearVel);
            linearVel -= Vector3<>(linearVel).normalize(std::min(linearVel.abs(), rollingFriction * simulation->scene->stepLength));
            dBodySetLinearVel(bodyId2, linearVel.x, linearVel.y, linearVel.z);
          }
          break;
      }
  }

  for(dContact* cont = contact, * end = contact + collisions; cont < end; ++cont)
  {
    cont->surface.mode = simulation->scene->contactMode | dContactApprox1;
    cont->surface.mu = friction;

    /*
    cont->surface.bounce = 0.f;
    cont->surface.bounce_vel = 0.001f;
    cont->surface.slip1 = 0.f;
    cont->surface.slip2 = 0.f;
    */
    cont->surface.soft_erp = simulation->scene->contactSoftERP;
    cont->surface.soft_cfm = simulation->scene->contactSoftCFM;

    dJointID c = dJointCreateContact(simulation->physicalWorld, simulation->contactGroup, cont);
    ASSERT(bodyId1 == dGeomGetBody(cont->geom.g1));
    ASSERT(bodyId2 == dGeomGetBody(cont->geom.g2));
    dJointAttach(c, bodyId1, bodyId2);
  }
  ++simulation->collisions;
  simulation->contactPoints += collisions;
}