コード例 #1
0
void updateHaptics(void)
{
	// start haptic device
	hapticDevice->open();

	// simulation clock
    cPrecisionClock simClock;
    simClock.start(true);

	double kp, kr;
	kp = 0.0;
	kr = 0.0;

	cMatrix3d prevRotTool;
	prevRotTool.identity();

    // main haptic simulation loop
    while(simulationRunning)
    {
        // retrieve simulation time and compute next interval
        double time = simClock.getCurrentTimeSeconds();
        double nextSimInterval = simClock.stop();//0.0005;//cClamp(time, 0.00001, 0.0002);
        
		// reset clock
        simClock.reset();
        simClock.start();

        // compute global reference frames for each object
        world->computeGlobalPositions(true);

        // update position and orientation of tool
		cVector3d posDevice;
		cMatrix3d rotDevice;
		hapticDevice->getPosition(posDevice);
		hapticDevice->getRotation(rotDevice);

		// scale position of device
		posDevice.mul(workspaceScaleFactor);

		// read position of tool
		cVector3d posTool = ODETool->getLocalPos();
		cMatrix3d rotTool = ODETool->getLocalRot();

		// compute position and angular error between tool and haptic device
		cVector3d deltaPos = (posDevice - posTool);
		cMatrix3d deltaRot = cMul(cTranspose(rotTool), rotDevice);
		double angle;
		cVector3d axis;
		deltaRot.toAngleAxis(angle, axis);
		
		// compute force and torque to apply to tool
		cVector3d force, torque;
		force = linStiffness * deltaPos;
		ODETool->addExternalForce(force);

		torque = cMul((angStiffness * angle), axis);
		rotTool.mul(torque);	
		ODETool->addExternalTorque(torque);

		// update data for display
		frame->setLocalRot(deltaRot);
		
		// compute force and torque to apply to haptic device
		force = -linG * force;
		torque = -angG * torque;
		line->m_pointB = torque;

        // send forces to device
		hapticDevice->setForceAndTorqueAndGripperForce(force, torque, 0.0);

		if (linG < linGain)
		{
			linG = linG + 0.1 * time * linGain;
		}
		else
		{
			linG = linGain;
		}

		if (angG < angGain)
		{
			angG = angG + 0.1 * time * angGain;
		}
		else
		{
			angG = angGain;
		}

        // update simulation
        ODEWorld->updateDynamics(nextSimInterval);
    }

    // exit haptics thread
    simulationFinished = true;
}
コード例 #2
0
ファイル: CWorld.cpp プロジェクト: DanGrise/HugMe
//===========================================================================
bool cWorld::computeCollisionDetection(
        cVector3d& a_segmentPointA, const cVector3d& a_segmentPointB,
        cGenericObject*& a_colObject, cTriangle*& a_colTriangle, cVector3d& a_colPoint,
        double& a_colDistance, const bool a_visibleObjectsOnly, int a_proxyCall)
{
    // initialize objects for collision detection calls
    cGenericObject* t_colObject;
    cTriangle *t_colTriangle;
    cVector3d t_colPoint;
    bool hit = false;
    double colSquareDistance = CHAI_LARGE;
    double t_colSquareDistance = colSquareDistance;

    // get the transpose of the local rotation matrix
    cMatrix3d transLocalRot;
    m_localRot.transr(transLocalRot);

    // convert second endpoint of the segment into local coordinate frame
    cVector3d localSegmentPointB = a_segmentPointB;
    localSegmentPointB.sub(m_localPos);
    transLocalRot.mul(localSegmentPointB);

    // r_segmentPointA is the value that we will return in a_segmentPointA
    // at the end; it should be unchanged from the received value of
    // a_segmentPointA, unless the collision that will be returned is with
    // a moving object, in which case it will be adjusted so that it is in the
    // same location relative to the moving object as it was at the previous
    // haptic iteration; this is necessary so that the proxy algorithm gets the
    // correct new proxy position
    cVector3d r_segmentPointA = a_segmentPointA;

    // check for collisions with all children of this world
    unsigned int nChildren = m_children.size();
    for (unsigned int i=0; i<nChildren; i++)
		{
        // start with the first segment point as it was received
        cVector3d l_segmentPointA = a_segmentPointA;

        // convert first endpoint of the segment into local coordinate frame
        cVector3d localSegmentPointA = l_segmentPointA;
        localSegmentPointA.sub(m_localPos);
				transLocalRot.mul(localSegmentPointA);

        // if this is a first call from the proxy algorithm, and the current
        // child is a dynamic object, adjust the first segment endpoint so that
        // it is in the same position relative to the moving object as it was
        // at the previous haptic iteration
        if ((a_proxyCall == 1) && (m_children[i]->m_historyValid))
            AdjustCollisionSegment(l_segmentPointA,localSegmentPointA,m_children[i]);

        // call this child's collision detection function to see if it (or any
        // of its descendants) are intersected by the segment
				int coll = m_children[i]->computeCollisionDetection(localSegmentPointA, localSegmentPointB,
                      t_colObject, t_colTriangle, t_colPoint, t_colSquareDistance, a_visibleObjectsOnly, a_proxyCall);

        // if a collision was found with this child, and this collision is
        // closer than any others found so far...
        if ((coll == 1) && (t_colSquareDistance < colSquareDistance))
        {
            // record that there has been a collision
            hit = true;

            // set the return parameters with information about this collision
            // (they may be overwritten if a closer collision is found later
            // on in this loop)
            a_colObject = t_colObject;
            a_colTriangle = t_colTriangle;
            a_colPoint = t_colPoint;

            // this is now the shortest distance to a collision found so far
            colSquareDistance = t_colSquareDistance;

            // convert collision point into parent coordinate frame
            m_localRot.mul(a_colPoint);
            a_colPoint.add(m_localPos);

            // localSegmentPointA's position (as possibly modified in the
            // call to the child's collision detector), converted back to
            // the global coordinate frame, is currently the proxy position
            // we will want to return (unless we find a closer collision later on)
            r_segmentPointA = cAdd(cMul(m_localRot,localSegmentPointA), m_localPos);
        }
		}

    // for optimization reasons, the collision detectors only computes the
    // squared distance between a_segmentA and collision point; this
    // computes a square root to obtain the actual distance.
    a_colDistance = sqrt(colSquareDistance);

    // set the value of the actual parameter for the first segment point; this
    // is the proxy position when called by the proxy algorithm, and may be
    // different from the value passed in this parameter if the closest collision
    // was with a moving object
    a_segmentPointA = r_segmentPointA;

    // return whether there was a collision between the segment and this world
    return (hit);
}
コード例 #3
0
void updateHaptics(void)
{
    // simulation clock
    cPrecisionClock simClock;
    simClock.start(true);

    // reset haptics activation clock
    startHapticsClock.reset();
	startHapticsClock.start();
	bool hapticsReady = false;

    // main haptic simulation loop
    while(simulationRunning)
    {
        // wait for some time before enabling haptics
		if (!hapticsReady)
		{
			if (startHapticsClock.getCurrentTimeSeconds() > 3.0)
			{
				hapticsReady = true;
			}
		}

        // compute global reference frames for each object
        world->computeGlobalPositions(true);

        // update position and orientation of tool
        tool->updatePose();

        // compute interaction forces
        tool->computeInteractionForces();

        // check if the tool is touching an object
        cGenericObject* object = tool->m_proxyPointForceModel->m_contactPoint0->m_object;

        // read user switch status
        bool userSwitch = tool->getUserSwitch(0);

        // if the tool is currently grasping an object we simply update the interaction grasp force
        // between the tool and the object (modeled by a virtual spring)
        if (graspActive && userSwitch)
        {
            // retrieve latest position and orientation of grasped ODE object in world coordinates
            cMatrix3d globalGraspObjectRot = graspObject->getGlobalRot();
            cVector3d globalGraspObjectPos = graspObject->getGlobalPos();

            // compute the position of the grasp point on object in global coordinates
            cVector3d globalGraspPos = globalGraspObjectPos + cMul(globalGraspObjectRot, graspPos);

            // retrieve the position of the tool in global coordinates
            cVector3d globalToolPos  = tool->getProxyGlobalPos();

            // compute the offset between the tool and grasp point on the object
            cVector3d offset = globalToolPos - globalGraspPos;

            // model a spring between both points
            double STIFFNESS = 4;
            cVector3d force = STIFFNESS * offset;

            // apply attraction force (grasp) onto object
            graspObject->addGlobalForceAtGlobalPos(force, globalGraspPos);

            // scale magnitude and apply opposite force to haptic device
            tool->m_lastComputedGlobalForce.add(cMul(-1.0, force));

            // update both end points of the line which is used for display purposes only
            graspLine->m_pointA = globalGraspPos;
            graspLine->m_pointB = globalToolPos;
        }

        // the user is not or no longer currently grasping the object
        else
        {
            // was the user grasping the object at the previous simulation loop
            if (graspActive)
            {
                // we disable grasping
                graspActive = false;

                // we hide the virtual line between the tool and the grasp point
                graspLine->setShowEnabled(false);

                // we enable haptics interaction between the tool and the previously grasped object
                if (graspObject != NULL)
                {
                    graspObject->m_imageModel->setHapticEnabled(true, true);
                }
            }

            // the user is touching an object
            if (object != NULL)
            {
                // check if object is attached to an external ODE parent
                cGenericType* externalParent = object->getExternalParent();
                cODEGenericBody* ODEobject = dynamic_cast<cODEGenericBody*>(externalParent);
                if (ODEobject != NULL)
                {
                    // get position of tool
                    cVector3d pos = tool->m_proxyPointForceModel->m_contactPoint0->m_globalPos;

                    // check if user has enabled the user switch to gras the object
                    if (userSwitch)
                    {
                        // a new object is being grasped
                        graspObject = ODEobject;

                        // retrieve the grasp position on the object in local coordinates
                        graspPos    = tool->m_proxyPointForceModel->m_contactPoint0->m_localPos;

                        // grasp in now active!
                        graspActive = true;

                        // enable small line which display the offset between the tool and the grasp point
                        graspLine->setShowEnabled(true);

                        // disable haptic interaction between the tool and the grasped device.
                        // this is performed for stability reasons.
                        graspObject->m_imageModel->setHapticEnabled(false, true);
                    }

                    // retrieve the haptic interaction force being applied to the tool
                    cVector3d force = tool->m_lastComputedGlobalForce;

                    // apply haptic force to ODE object
                    cVector3d tmpfrc = cNegate(force);
                    if (hapticsReady)
                    {
                        ODEobject->addGlobalForceAtGlobalPos(tmpfrc, pos);
                    }
                }
            }
        }

        // send forces to device
        tool->applyForces();

        // retrieve simulation time and compute next interval
        double time = simClock.getCurrentTimeSeconds();
        double nextSimInterval = cClamp(time, 0.001, 0.004);

        // reset clock
        simClock.reset();
        simClock.start();

        // update simulation
        ODEWorld->updateDynamics(nextSimInterval);
    }

    // exit haptics thread
    simulationFinished = true;
}
コード例 #4
0
//===========================================================================
bool cEffectMagnet::computeForce(const cVector3d& a_toolPos,
                                  const cVector3d& a_toolVel,
                                  const unsigned int& a_toolID,
                                  cVector3d& a_reactionForce)
{
    // compute distance from object to tool
    double distance = cDistance(a_toolPos, m_parent->m_interactionProjectedPoint);

    // get parameters of magnet
    double magnetMaxForce = m_parent->m_material.getMagnetMaxForce();
    double magnetMaxDistance = m_parent->m_material.getMagnetMaxDistance();
    double stiffness = m_parent->m_material.getStiffness();
    double forceMagnitude = 0;

    if ((distance > 0) && (distance < magnetMaxDistance) && (stiffness > 0))
    {
        double limitLinearModel = magnetMaxForce / stiffness;
        cClamp(limitLinearModel, 0.0, 0.5 * distance);

        if (distance < limitLinearModel)
        {
            // apply local linear model near magnet
            forceMagnitude = stiffness * distance;
        }
        else
        {
            // compute quadratic model
            cMatrix3d sys;
            sys.m[0][0] = limitLinearModel * limitLinearModel;
            sys.m[0][1] = limitLinearModel;
            sys.m[0][2] = 1.0;
            sys.m[1][0] = magnetMaxDistance * magnetMaxDistance;
            sys.m[1][1] = magnetMaxDistance;
            sys.m[1][2] = 1.0;
            sys.m[2][0] = 2.0 * limitLinearModel;
            sys.m[2][1] = 1.0;
            sys.m[2][2] = 0.0;
            sys.invert();

            cVector3d param;
            sys.mulr(cVector3d(magnetMaxForce, 0.0, -1.0), param);

            // apply quadratic model
            double val = distance - limitLinearModel;
            forceMagnitude = param.x * val * val + param.y * val + param.z;
        }

        // compute magnetic force
        a_reactionForce = cMul(forceMagnitude, cNormalize(cSub(m_parent->m_interactionProjectedPoint, a_toolPos)));

        // add damping component
        double viscosity = m_parent->m_material.getViscosity();
        cVector3d viscousForce = cMul(-viscosity, a_toolVel);
        a_reactionForce.add(viscousForce);

        return (true);
    }
    else
    {
        // the tool is located outside the magnet zone
        a_reactionForce.zero();
        return (false);
    }
}
コード例 #5
0
ファイル: 10-oring.cpp プロジェクト: osung/Haptic-Xylophone
void updateHaptics(void)
{
    // reset clock
    simClock.reset();

    // main haptic simulation loop
    while(simulationRunning)
    {
        // compute global reference frames for each object
        world->computeGlobalPositions(true);

        // update position and orientation of tool
        tool->updatePose();

        // compute interaction forces
        tool->computeInteractionForces();

        // send forces to device
        tool->applyForces();

        // retrieve and update the force that is applied on each object

        // stop the simulation clock
        simClock.stop();

        // read the time increment in seconds
        double timeInterval = simClock.getCurrentTimeSeconds();

        // restart the simulation clock
        simClock.reset();
        simClock.start();

        // get position of cursor in global coordinates
        cVector3d toolPos = tool->m_deviceGlobalPos;

        // get position of object in global coordinates
        cVector3d objectPos = object->getGlobalPos();

        // compute a vector from the center of mass of the object (point of rotation) to the tool
        cVector3d vObjectCMToTool = cSub(toolPos, objectPos);

        // compute acceleration based on the interaction forces
        // between the tool and the object
        cVector3d rotAcc(0,0,0);
        if (vObjectCMToTool.length() > 0.0)
        {
            // get the last force applied to the cursor in global coordinates
            // we negate the result to obtain the opposite force that is applied on the
            // object
            cVector3d toolForce = cNegate(tool->m_lastComputedGlobalForce);

            // compute effective force to take into account the fact the object
            // can only rotate around a its center mass and not translate
            cVector3d effectiveForce = toolForce - cProject(toolForce, vObjectCMToTool);

            // compute the resulting torque
            cVector3d torque = cMul(vObjectCMToTool.length(), cCross( cNormalize(vObjectCMToTool), effectiveForce));

            // update rotational acceleration
            const double OBJECT_INERTIA = 0.4;
            rotAcc = (1.0 / OBJECT_INERTIA) * torque;
        }

        // update rotational velocity
        rotVel.add(timeInterval * rotAcc);

        // set a threshold on the rotational velocity term
        const double ROT_VEL_MAX = 10.0;
        double velMag = rotVel.length();
        if (velMag > ROT_VEL_MAX)
        {
            rotVel.mul(ROT_VEL_MAX / velMag);
        }

        // add some damping too
        const double DAMPING_GAIN = 0.1;
        rotVel.mul(1.0 - DAMPING_GAIN * timeInterval);

        // if user switch is pressed, set velocity to zero
        if (tool->getUserSwitch(0) == 1)
        {
            rotVel.zero();
        }

        // compute the next rotation configuration of the object
        if (rotVel.length() > CHAI_SMALL)
        {
            object->rotate(cNormalize(rotVel), timeInterval * rotVel.length());
        }
    }
    
    // exit haptics thread
    simulationFinished = true;
}
コード例 #6
0
ファイル: main.cpp プロジェクト: remis/chai3d
void hapticsLoop(void* a_pUserData)
{
    // read the position of the haptic device
    cursor->updatePose();

    // compute forces between the cursor and the environment
    cursor->computeForces();

    // stop the simulation clock
    g_clock.stop();

    // read the time increment in seconds
    double increment = g_clock.getCurrentTime() / 1000000.0;

    // restart the simulation clock
    g_clock.initialize();
    g_clock.start();

    // get position of cursor in global coordinates
    cVector3d cursorPos = cursor->m_deviceGlobalPos;

    // compute velocity of cursor;
    timeCounter = timeCounter + increment;
    if (timeCounter > 0.01)
    {
        cursorVel = (cursorPos - lastCursorPos) / timeCounter;
        lastCursorPos = cursorPos;
        timeCounter = 0;
    }

    // get position of torus in global coordinates
    cVector3d objectPos = object->getGlobalPos();

    // compute the velocity of the sphere at the contact point
    cVector3d contactVel = cVector3d(0.0, 0.0, 0.0);
    if (rotVelocity.length() > CHAI_SMALL)
    {
        cVector3d projection = cProjectPointOnLine(cursorPos, objectPos, rotVelocity);
        cVector3d vpc = cursorPos - projection;
        if (vpc.length() > CHAI_SMALL)
        {
            contactVel = vpc.length() * rotVelocity.length() * cNormalize(cCross(rotVelocity, vpc));
        }
    }

    // get the last force applied to the cursor in global coordinates
    cVector3d cursorForce = cursor->m_lastComputedGlobalForce;

    // compute friction force
    cVector3d friction = -40.0 * cursorForce.length() * cProjectPointOnPlane((cursorVel - contactVel), cVector3d(0.0, 0.0, 0.0), (cursorPos - objectPos));

    // add friction force to cursor
    cursor->m_lastComputedGlobalForce.add(friction);

    // update rotational velocity
    if (friction.length() > CHAI_SMALL)
    {
        rotVelocity.add( cMul(-10.0 * increment, cCross(cSub(cursorPos, objectPos), friction)));
    }

    // add some damping...
    //rotVelocity.mul(1.0 - increment);
    
    // compute the next rotation of the torus
    if (rotVelocity.length() > CHAI_SMALL)
    {
        object->rotate(cNormalize(rotVelocity), increment * rotVelocity.length());
    }

    // send forces to haptic device
    cursor->applyForces();
}
コード例 #7
0
ファイル: 23-tooth.cpp プロジェクト: flair2005/chai3d
void updateHaptics(void)
{
    // main haptic simulation loop
    while(simulationRunning)
    {
        // update position and orientation of tool
        tool->updatePose();

        // compute interaction forces
        tool->computeInteractionForces();

        // send forces to device
        tool->applyForces();

        // if the haptic device does track orientations, we automatically
        // oriente the drill to remain perpendicular to the tooth
        cVector3d pos = tool->m_proxyPointForceModel->getProxyGlobalPosition();
        cMatrix3d rot = tool->m_deviceGlobalRot;

        if (info.m_sensedRotation == false)
        {
            cVector3d pos = tool->m_proxyPointForceModel->getProxyGlobalPosition();
            rot.identity();

            cVector3d vx, vy, vz;
            cVector3d zUp (0,0,1);
            cVector3d yUp (0,1,0);
            vx = pos - tooth->getPos();
            if (vx.length() > 0.001)
            {
                vx.normalize();

                if (cAngle(vx,zUp) > 0.001)
                {
                    vy = cCross(zUp, vx);
                    vy.normalize();
                    vz = cCross(vx, vy);
                    vz.normalize();

                }
                else
                {
                    vy = cCross(yUp, vx);
                    vy.normalize();
                    vz = cCross(vx, vy);
                    vz.normalize();
                }

                rot.setCol(vx, vy, vz);
                drill->setRot(rot);
            }
        }


        int button = tool->getUserSwitch(0);
        if (button == 0)
        {
            lastPosDevice = pos;
            lastRotDevice = rot;
            lastPosObject = tooth->getPos();
            lastRotObject = tooth->getRot();
            lastDeviceObjectPos = cTrans(lastRotDevice) * ((lastPosObject - lastPosDevice) + 0.01*cNormalize(lastPosObject - lastPosDevice));
            lastDeviceObjectRot = cMul(cTrans(lastRotDevice), lastRotObject);
            tooth->setHapticEnabled(true, true);
            tool->setShowEnabled(true, true);
            drill->setShowEnabled(true, true);
        }
        else
        {
            tool->setShowEnabled(false, true);
            drill->setShowEnabled(false, true);
            cMatrix3d rotDevice01 = cMul(cTrans(lastRotDevice), rot);
            cMatrix3d newRot =  cMul(rot, lastDeviceObjectRot);
            cVector3d newPos = cAdd(pos, cMul(rot, lastDeviceObjectPos));
            tooth->setPos(newPos);
            tooth->setRot(newRot);
            world->computeGlobalPositions(true);
            tooth->setHapticEnabled(false, true);
        }

        // compute global reference frames for each object
        world->computeGlobalPositions(true);

#ifdef _WIN32
        Sleep(1);
#else
        usleep(1000);
#endif
    }

    // exit haptics thread
    simulationFinished = true;
}
コード例 #8
0
ファイル: carro.cpp プロジェクト: capaca/Destroyer3D
Carro::Carro(dynamicWorld* world):dynamicObject(world,0.5*LARGURACARRO*COMPRIMENTOCARRO,true) {

        steeringAngle = 0;

        //Instancia o chassi e o meio
        meio = new cGenericObject();
        chassi = new cGenericObject();
        meio->addChild(chassi);

        //Adiciona o meio ao carro propriamente dito
        this->addChild(meio);

        //Inicializa a roda1
        roda1 = new cMesh(world);
        roda1->loadFromFile("roda_simples.obj");
        roda1->computeBoundaryBox(true);
        cVector3d min = roda1->getBoundaryMin();
        cVector3d max = roda1->getBoundaryMax();
        cVector3d meio = cMul(-0.5,cAdd(min,max));
        cVector3d span = cSub(max, min);

        for(int i=0;i<roda1->getNumVertices(true);i++)
                roda1->getVertex(i,true)->translate(meio);

        double size = cMax(span.x, cMax(span.y, span.z));
        double scaleFactor = 2*RAIORODA / size;
        roda1->scale(scaleFactor);
        chassi->addChild(roda1);
        roda1->translate(0,RAIORODA,LARGURACARRO/2.0);
        roda1->rotate(cVector3d(1,0,0),3.1415/2.0);

        //Instancia e inicializa a roda2
        roda2 = new cMesh(world);
        roda2->loadFromFile("roda_simples.obj");

        for(int i=0;i<roda2->getNumVertices(true);i++)
                roda2->getVertex(i,true)->translate(meio);

        roda2->scale(scaleFactor);
        chassi->addChild(roda2);
        roda2->translate(0,RAIORODA,-LARGURACARRO/2.0);
        roda2->rotate(cVector3d(1,0,0),-3.1415/2.0);

        //Instanci os eixos do carro
        eixo1 = new cGenericObject();
        chassi->addChild(eixo1);
        eixo2 = new cGenericObject();
        chassi->addChild(eixo2);

        //Instancia e inicializa a roda3
        roda3 = new cMesh(world);
        roda3->loadFromFile("roda_simples.obj");
        for(int i=0;i<roda3->getNumVertices(true);i++)
                roda3->getVertex(i,true)->translate(meio);

        roda3->scale(scaleFactor);
        eixo1->addChild(roda3);
        eixo1->translate(DISTANCIAEIXOS,RAIORODA,LARGURACARRO/2.0);
        roda3->rotate(cVector3d(1,0,0),3.1415/2.0);

        //Instancia e inicializa a roda4
        roda4 = new cMesh(world);
        roda4->loadFromFile("roda_simples.obj");
        for(int i=0;i<roda4->getNumVertices(true);i++)
                roda4->getVertex(i,true)->translate(meio);

        roda4->scale(scaleFactor);
        eixo2->addChild(roda4);
        eixo2->translate(DISTANCIAEIXOS,RAIORODA,-LARGURACARRO/2.0);
        roda4->rotate(cVector3d(1,0,0),-3.1415/2.0);

        //Instancia e inicializa a carroceria
        carroceria = new cMesh(world);
        carroceria->loadFromFile("ferrari.3ds");
        chassi->addChild(carroceria);
        carroceria->computeBoundaryBox(true);
        min = carroceria->getBoundaryMin();
        max = carroceria->getBoundaryMax();
        span = cSub(max, min);
        meio = cMul(-0.5,cAdd(min,max));

        for(int i=0;i<carroceria->getNumVertices(true);i++)
                carroceria->getVertex(i,true)->translate(meio);
        size = cMax(span.x, cMax(span.y, span.z));
        scaleFactor = COMPRIMENTOCARRO / size;
        carroceria->scale(scaleFactor);
        carroceria->rotate(cVector3d(0,1,0),3.1415/2.0);
        carroceria->rotate(cVector3d(0,0,1),3.1415/2.0);

        //recalcula dimensões
        carroceria->computeBoundaryBox(true);
        min = carroceria->getBoundaryMin();
        max = carroceria->getBoundaryMax();
        span = cSub(max, min);
        double altura= cMin(span.x, cMin(span.y, span.z));

        // posiciona carroceria: assumindo que altura do chão é 0.3* raio da roda
        // levanta meia altura para chao ficar no plano x,z
        carroceria->translate(DISTANCIAEIXOS/1.85,altura*0.5+RAIORODA*0.3,0);
        carroceria->useColors(true, true);
        carroceria->useMaterial(false,true);
}
コード例 #9
0
ファイル: CCamera.cpp プロジェクト: ChellaVignesh/ros_haptics
//===========================================================================
bool cCamera::select(const int a_windowPosX,
                     const int a_windowPosY,
                     const int a_windowWidth,
                     const int a_windowHeight,
                     cCollisionRecorder& a_collisionRecorder,
                     cCollisionSettings& a_collisionSettings)
{
    // sanity check
    if ((a_windowWidth <= 0) || (a_windowHeight <= 0)) return (false);
    
    // clear collision recorder
    a_collisionRecorder.clear();

    // update my m_globalPos and m_globalRot variables
    m_parentWorld->computeGlobalPositions(false);

    // init variable to store result
    bool result = false;
    if (m_perspectiveMode)
    {

        // make sure we have a legitimate field of view
        if (fabs(m_fieldViewAngle) < 0.001f) { return (false); }

        // compute the ray that leaves the eye point at the appropriate angle
        //
        // m_fieldViewAngle / 2.0 would correspond to the _top_ of the window
        double distCam = (a_windowHeight / 2.0f) / cTanDeg(m_fieldViewAngle / 2.0f);

        cVector3d selectRay;
        selectRay.set(-distCam,
                       (a_windowPosX - (a_windowWidth / 2.0f)),
                       ((a_windowHeight / 2.0f) - a_windowPosY));
        selectRay.normalize();

        selectRay = cMul(m_globalRot, selectRay);

        // create a point that's way out along that ray
        cVector3d selectPoint = cAdd(m_globalPos, cMul(100000, selectRay));

        // search for intersection between the ray and objects in the world
        result = m_parentWorld->computeCollisionDetection(
                                    m_globalPos,
                                    selectPoint,
                                    a_collisionRecorder,
                                    a_collisionSettings);
    }
    else
    {
        double hw = (double)(a_windowWidth) * 0.5;
        double hh = (double)(a_windowHeight)* 0.5;
        double aspect = hw / hh;
        
        double offsetX = ((a_windowPosX - hw) / hw) * 0.5 * m_orthographicWidth;
        double offsetY =-((a_windowPosY - hh) / hh) * 0.5 * (m_orthographicWidth / aspect);

        cVector3d pos = cAdd(m_globalPos, 
                             cMul(offsetX, m_globalRot.getCol1()), 
                             cMul(offsetY, m_globalRot.getCol2()));

        // create a point that's way out along that ray
        cVector3d selectPoint = cAdd(pos, cMul(100000,  cNegate(m_globalRot.getCol0())));

        result = m_parentWorld->computeCollisionDetection(pos,
                                                          selectPoint,
                                                          a_collisionRecorder,
                                                          a_collisionSettings);
    }

    // return result
    return (result);
}
コード例 #10
0
ファイル: CGELMesh.cpp プロジェクト: jateeq/FYDP
//===========================================================================
void cGELMesh::connectVerticesToSkeleton(bool a_connectToNodesOnly)
{
    // get number of vertices
    int numVertices = m_gelVertices.size();

    // for each deformable vertex we search for the nearest sphere or link
    for (int i=0; i<numVertices; i++)
    {
        // get current deformable vertex
        cGELVertex* curVertex = &m_gelVertices[i];

        // get current vertex position
        cVector3d pos = curVertex->m_vertex->getPos();

        // initialize constant
        double min_distance = 99999999999999999.0;
        cGELSkeletonNode* nearest_node = NULL;
        cGELSkeletonLink* nearest_link = NULL;

        // search for the nearest node
		list<cGELSkeletonNode*>::iterator itr;
        for(itr = m_nodes.begin(); itr != m_nodes.end(); ++itr)
        {
            cGELSkeletonNode* nextNode = *itr;
            double distance = cDistance(pos, nextNode->m_pos);
            if (distance < min_distance)
            {
                min_distance = distance;
                nearest_node = nextNode;
                nearest_link = NULL;
            }
        }

        // search for the nearest link if any
        if (!a_connectToNodesOnly)
        {
            list<cGELSkeletonLink*>::iterator j;
            for(j = m_links.begin(); j != m_links.end(); ++j)
            {
                cGELSkeletonLink* nextLink = *j;
                double angle0 = cAngle(nextLink->m_wLink01, cSub(pos, nextLink->m_node0->m_pos));
                double angle1 = cAngle(nextLink->m_wLink10, cSub(pos, nextLink->m_node1->m_pos));

                if ((angle0 < (CHAI_PI / 2.0)) && (angle1 < (CHAI_PI / 2.0)))
                {
                    cVector3d p = cProjectPointOnLine(pos,
                                                      nextLink->m_node0->m_pos,
                                                      nextLink->m_wLink01);

                    double distance = cDistance(pos, p);

                    if (distance < min_distance)
                    {
                        min_distance = distance;
                        nearest_node = NULL;
                        nearest_link = nextLink;
                    }
                }
            }
        }

        // attach vertex to nearest node if it exists
        if (nearest_node != NULL)
        {
            curVertex->m_node = nearest_node;
            curVertex->m_link = NULL;
            cVector3d posRel = cSub(pos, nearest_node->m_pos);
            curVertex->m_massParticle->m_pos = cMul(cTrans(nearest_node->m_rot), posRel);
        }

        // attach vertex to nearest link if it exists
        else if (nearest_link != NULL)
        {
            curVertex->m_node = NULL;
            curVertex->m_link = nearest_link;

            cMatrix3d rot;
            rot.setCol( nearest_link->m_A0,
                        nearest_link->m_B0,
                        nearest_link->m_wLink01);
            cVector3d posRel = cSub(pos, nearest_link->m_node0->m_pos);
            curVertex->m_massParticle->m_pos = cMul(cInv(rot), posRel);
        }
    }
}
コード例 #11
0
//==============================================================================
bool cTriangleArray::computeCollision(const unsigned int a_triangleIndex,
                                      cGenericObject* a_object,
                                      cVector3d& a_segmentPointA,
                                      cVector3d& a_segmentPointB,
                                      cCollisionRecorder& a_recorder,
                                      cCollisionSettings& a_settings) const
{
    // verify that triangle is active
    if (!m_allocated[a_triangleIndex]) { return (false); }

    // temp variables
    bool hit = false;
    cVector3d collisionPoint;
    cVector3d collisionNormal;
    double collisionDistanceSq = C_LARGE;
    double collisionPointV01 = 0.0;
    double collisionPointV02 = 0.0;

    // retrieve information about which side of the triangles need to be checked
    cMaterialPtr material = a_object->m_material;
    bool checkFrontSide = material->getHapticTriangleFrontSide();
    bool checkBackSide = material->getHapticTriangleBackSide();

    // retrieve vertex positions
    cVector3d vertex0 = m_vertices->getLocalPos(getVertexIndex0(a_triangleIndex));
    cVector3d vertex1 = m_vertices->getLocalPos(getVertexIndex1(a_triangleIndex));
    cVector3d vertex2 = m_vertices->getLocalPos(getVertexIndex2(a_triangleIndex));

    // If m_collisionRadius == 0, we search for a possible intersection between
    // the segment AB and the triangle defined by its three vertices V0, V1, V2.
    if (a_settings.m_collisionRadius == 0.0)
    {
        // check for collision between segment and triangle only
        if (cIntersectionSegmentTriangle(a_segmentPointA,
                                         a_segmentPointB,
                                         vertex0,
                                         vertex1,
                                         vertex2,
                                         checkFrontSide,
                                         checkBackSide,
                                         collisionPoint,
                                         collisionNormal,
                                         collisionPointV01,
                                         collisionPointV02))
        {
            hit = true;
            collisionDistanceSq = cDistanceSq(a_segmentPointA, collisionPoint);
        }
    }


    // If m_collisionRadius > 0, we search for a possible intersection between
    // the segment AB and the shell of the selected triangle which is described
    // by its three vertices and m_collisionRadius.
    else
    {
        cVector3d t_collisionPoint, t_collisionNormal;
        double t_collisionDistanceSq;
        cVector3d normal = cComputeSurfaceNormal(vertex0, vertex1, vertex2);
        cVector3d offset; normal.mulr(a_settings.m_collisionRadius, offset);
        cVector3d t_vertex0, t_vertex1, t_vertex2;
        double t_collisionPointV01, t_collisionPointV02, t_collisionPointV12;

        // check for collision between segment and triangle upper shell
        vertex0.addr(offset, t_vertex0);
        vertex1.addr(offset, t_vertex1);
        vertex2.addr(offset, t_vertex2);
        if (cIntersectionSegmentTriangle(a_segmentPointA,
                                         a_segmentPointB,
                                         t_vertex0,
                                         t_vertex1,
                                         t_vertex2,
                                         checkFrontSide,
                                         false,
                                         collisionPoint,
                                         collisionNormal,
                                         collisionPointV01,
                                         collisionPointV02))
        {
            hit = true;
            collisionDistanceSq = cDistanceSq(a_segmentPointA, collisionPoint);
        }

        // check for collision between segment and triangle lower shell
        vertex0.subr(offset, t_vertex0);
        vertex1.subr(offset, t_vertex1);
        vertex2.subr(offset, t_vertex2);
        if (cIntersectionSegmentTriangle(a_segmentPointA,
                                         a_segmentPointB,
                                         t_vertex0,
                                         t_vertex1,
                                         t_vertex2,
                                         false,
                                         checkBackSide,
                                         t_collisionPoint,
                                         t_collisionNormal,
                                         t_collisionPointV01,
                                         t_collisionPointV02))
        {
            hit = true;
            t_collisionDistanceSq = cDistanceSq(a_segmentPointA, t_collisionPoint);
            if (t_collisionDistanceSq <= collisionDistanceSq)
            {
                collisionPoint = t_collisionPoint;
                collisionNormal = t_collisionNormal;
                collisionDistanceSq = t_collisionDistanceSq;
                collisionPointV01 = t_collisionPointV01;
                collisionPointV02 = t_collisionPointV02;
            }
        }

        // check for collision between sphere located at vertex 0.
        // if the starting point (a_segmentPointA) is located inside
        // the sphere, we ignore the collision to avoid remaining
        // stuck inside the triangle.
        cVector3d t_p, t_n;
        double t_c;
        if (cIntersectionSegmentSphere(a_segmentPointA,
                                       a_segmentPointB,
                                       vertex0,
                                       a_settings.m_collisionRadius,
                                       t_collisionPoint,
                                       t_collisionNormal,
                                       t_p,
                                       t_n) > 0)
        {
            hit = true;
            t_collisionDistanceSq = cDistanceSq(a_segmentPointA, t_collisionPoint);
            if (t_collisionDistanceSq <= collisionDistanceSq)
            {
                collisionPoint = t_collisionPoint;
                collisionNormal = t_collisionNormal;
                collisionDistanceSq = t_collisionDistanceSq;
                collisionPointV01 = 0.0;
                collisionPointV02 = 0.0;
            }
        }


        // check for collision between sphere located at vertex 1.
        // if the starting point (a_segmentPointA) is located inside
        // the sphere, we ignore the collision to avoid remaining
        // stuck inside the triangle.
        if (cIntersectionSegmentSphere(a_segmentPointA,
                                       a_segmentPointB,
                                       vertex1,
                                       a_settings.m_collisionRadius,
                                       t_collisionPoint,
                                       t_collisionNormal,
                                       t_p,
                                       t_n) > 0)
        {
            hit = true;
            t_collisionDistanceSq = cDistanceSq(a_segmentPointA, t_collisionPoint);
            if (t_collisionDistanceSq <= collisionDistanceSq)
            {
                collisionPoint = t_collisionPoint;
                collisionNormal = t_collisionNormal;
                collisionDistanceSq = t_collisionDistanceSq;
                collisionPointV01 = 1.0;
                collisionPointV02 = 0.0;
            }
        }


        // check for collision between sphere located at vertex 2.
        // if the starting point (a_segmentPointA) is located inside
        // the sphere, we ignore the collision to avoid remaining
        // stuck inside the triangle.
        if (cIntersectionSegmentSphere(a_segmentPointA,
                                       a_segmentPointB,
                                       vertex2,
                                       a_settings.m_collisionRadius,
                                       t_collisionPoint,
                                       t_collisionNormal,
                                       t_p,
                                       t_n) > 0)
        {
            hit = true;
            t_collisionDistanceSq = cDistanceSq(a_segmentPointA, t_collisionPoint);
            if (t_collisionDistanceSq <= collisionDistanceSq)
            {
                collisionPoint = t_collisionPoint;
                collisionNormal = t_collisionNormal;
                collisionDistanceSq = t_collisionDistanceSq;
                collisionPointV01 = 0.0;
                collisionPointV02 = 1.0;
            }
        }

        // check for collision between segment and triangle edge01 shell.
        // if the starting point (a_segmentPointA) is located inside
        // the cylinder, we ignore the collision to avoid remaining
        // stuck inside the triangle.
        if (cIntersectionSegmentToplessCylinder(a_segmentPointA,
                                                a_segmentPointB,
                                                vertex0,
                                                vertex1,
                                                a_settings.m_collisionRadius,
                                                t_collisionPoint,
                                                t_collisionNormal,
                                                t_collisionPointV01,
                                                t_p,
                                                t_n,
                                                t_c) > 0)
        {
            hit = true;
            t_collisionDistanceSq = cDistanceSq(a_segmentPointA, t_collisionPoint);
            if (t_collisionDistanceSq <= collisionDistanceSq)
            {
                collisionPoint = t_collisionPoint;
                collisionNormal = t_collisionNormal;
                collisionDistanceSq = t_collisionDistanceSq;
                collisionPointV01 = t_collisionPointV01;
                collisionPointV02 = 0.0;
            }
        }


        // check for collision between segment and triangle edge02 shell.
        // if the starting point (a_segmentPointA) is located inside
        // the cylinder, we ignore the collision to avoid remaining
        // stuck inside the triangle.
        if (cIntersectionSegmentToplessCylinder(a_segmentPointA,
                                                a_segmentPointB,
                                                vertex0,
                                                vertex2,
                                                a_settings.m_collisionRadius,
                                                t_collisionPoint,
                                                t_collisionNormal,
                                                t_collisionPointV02,
                                                t_p,
                                                t_n,
                                                t_c) > 0)
        {
            hit = true;
            t_collisionDistanceSq = cDistanceSq(a_segmentPointA, t_collisionPoint);
            if (t_collisionDistanceSq <= collisionDistanceSq)
            {
                collisionPoint = t_collisionPoint;
                collisionNormal = t_collisionNormal;
                collisionDistanceSq = t_collisionDistanceSq;
                collisionPointV01 = 0.0;
                collisionPointV02 = t_collisionPointV02;
            }
        }


        // check for collision between segment and triangle edge12 shell.
        // if the starting point (a_segmentPointA) is located inside
        // the cylinder, we ignore the collision to avoid remaining
        // stuck inside the triangle.
        if (cIntersectionSegmentToplessCylinder(a_segmentPointA,
                                                a_segmentPointB,
                                                vertex1,
                                                vertex2,
                                                a_settings.m_collisionRadius,
                                                t_collisionPoint,
                                                t_collisionNormal,
                                                t_collisionPointV12,
                                                t_p,
                                                t_n,
                                                t_c) > 0)
        {
            hit = true;
            t_collisionDistanceSq = cDistanceSq(a_segmentPointA, t_collisionPoint);
            if (t_collisionDistanceSq <= collisionDistanceSq)
            {
                collisionPoint = t_collisionPoint;
                collisionNormal = t_collisionNormal;
                collisionDistanceSq = t_collisionDistanceSq;
                collisionPointV01 = 1.0 - t_collisionPointV12;
                collisionPointV02 = t_collisionPointV12;
            }
        }
    }

    // report collision
    if (hit)
    {
        // before reporting the new collision, we need to check if
        // the collision settings require us to verify the side of the
        // triangle which has been hit.
        bool hit_confirmed = false;

        if (checkFrontSide && checkBackSide)
        {
            // settings specify that a collision can occur on both sides
            // of the triangle, so the new collision is reported.
            hit_confirmed = true;
        }
        else
        {
            // we need check on which side of the triangle the collision occurred
            // and see if it needs to be reported.
            cVector3d segmentAB;
            a_segmentPointB.subr(a_segmentPointA, segmentAB);

            cVector3d v01, v02, triangleNormal;
            vertex2.subr(vertex0, v02);
            vertex1.subr(vertex0, v01);
            v01.crossr(v02, triangleNormal);

            double value = cCosAngle(segmentAB, triangleNormal);
            if (value <= 0.0)
            {
                if (checkFrontSide)
                    hit_confirmed = true;
            }
            else
            {
                if (checkBackSide)
                    hit_confirmed = true;
            }
        }

        // here we finally report the new collision to the collision event handler.
        if (hit_confirmed)
        {
            // we verify if anew collision needs to be created or if we simply
            // need to update the nearest collision.
            if (a_settings.m_checkForNearestCollisionOnly)
            {
                // no new collision event is create. We just check if we need
                // to update the nearest collision
                if(collisionDistanceSq <= a_recorder.m_nearestCollision.m_squareDistance)
                {
                    // report basic collision data
                    a_recorder.m_nearestCollision.m_object = a_object;
                    a_recorder.m_nearestCollision.m_triangles = ((cMesh*)(a_object))->m_triangles;
                    a_recorder.m_nearestCollision.m_triangleIndex = a_triangleIndex;
                    a_recorder.m_nearestCollision.m_localPos = collisionPoint;
                    a_recorder.m_nearestCollision.m_localNormal = collisionNormal;
                    a_recorder.m_nearestCollision.m_squareDistance = collisionDistanceSq;
                    a_recorder.m_nearestCollision.m_adjustedSegmentAPoint = a_segmentPointA;
                    a_recorder.m_nearestCollision.m_trianglePosV01 = collisionPointV01;
                    a_recorder.m_nearestCollision.m_trianglePosV02 = collisionPointV02;

                    // report advanced collision data
                    if (!a_settings.m_returnMinimalCollisionData)
                    {
                        a_recorder.m_nearestCollision.m_globalPos = cAdd(a_object->getGlobalPos(),
                                cMul(a_object->getGlobalRot(),
                                        a_recorder.m_nearestCollision.m_localPos));
                        a_recorder.m_nearestCollision.m_globalNormal = cMul(a_object->getGlobalRot(),
                                a_recorder.m_nearestCollision.m_localNormal);
                    }
                }
            }
            else
            {
                cCollisionEvent newCollisionEvent;

                // report basic collision data
                newCollisionEvent.m_object = a_object;
                newCollisionEvent.m_triangles = ((cMesh*)(a_object))->m_triangles;
                newCollisionEvent.m_triangleIndex = a_triangleIndex;
                newCollisionEvent.m_localPos = collisionPoint;
                newCollisionEvent.m_localNormal = collisionNormal;
                newCollisionEvent.m_squareDistance = collisionDistanceSq;
                newCollisionEvent.m_adjustedSegmentAPoint = a_segmentPointA;
                newCollisionEvent.m_trianglePosV01 = collisionPointV01;
                newCollisionEvent.m_trianglePosV02 = collisionPointV02;

                // report advanced collision data
                if (!a_settings.m_returnMinimalCollisionData)
                {
                    newCollisionEvent.m_globalPos = cAdd(a_object->getGlobalPos(),
                                                         cMul(a_object->getGlobalRot(),
                                                         newCollisionEvent.m_localPos));
                    newCollisionEvent.m_globalNormal = cMul(a_object->getGlobalRot(),
                                                            newCollisionEvent.m_localNormal);
                }

                // add new collision even to collision list
                a_recorder.m_collisions.push_back(newCollisionEvent);

                // check if this new collision is a candidate for "nearest one"
                if(collisionDistanceSq <= a_recorder.m_nearestCollision.m_squareDistance)
                {
                    a_recorder.m_nearestCollision = newCollisionEvent;
                }
            }
        }

        // return result
        return (hit_confirmed);
    }
    else
    {
        return (false);
    }
}