Beispiel #1
0
void btRaycastVehicle::updateVehicle( btScalar step )
{
    {
        for (int i=0; i<getNumWheels(); i++)
        {
            updateWheelTransform(i,false);
        }
    }


    m_currentVehicleSpeedKmHour = btScalar(3.6) * getRigidBody()->getLinearVelocity().length();

    const btTransform& chassisTrans = getChassisWorldTransform();

    btVector3 forwardW (
        chassisTrans.getBasis()[0][m_indexForwardAxis],
        chassisTrans.getBasis()[1][m_indexForwardAxis],
        chassisTrans.getBasis()[2][m_indexForwardAxis]);

    if (forwardW.dot(getRigidBody()->getLinearVelocity()) < btScalar(0.))
    {
        m_currentVehicleSpeedKmHour *= btScalar(-1.);
    }

    //
    // simulate suspension
    //

    int i=0;
    for (i=0; i<m_wheelInfo.size(); i++)
    {
        btScalar depth;
        depth = rayCast( m_wheelInfo[i]);
    }

    updateSuspension(step);


    for (i=0; i<m_wheelInfo.size(); i++)
    {
        //apply suspension force
        btWheelInfo& wheel = m_wheelInfo[i];

        btScalar suspensionForce = wheel.m_wheelsSuspensionForce;

        if (suspensionForce > wheel.m_maxSuspensionForce)
        {
            suspensionForce = wheel.m_maxSuspensionForce;
        }
        btVector3 impulse = wheel.m_raycastInfo.m_contactNormalWS * suspensionForce * step;
        btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS - getRigidBody()->getCenterOfMassPosition();

        getRigidBody()->applyImpulse(impulse, relpos);

    }



    updateFriction( step);


    for (i=0; i<m_wheelInfo.size(); i++)
    {
        btWheelInfo& wheel = m_wheelInfo[i];
        btVector3 relpos = wheel.m_raycastInfo.m_hardPointWS - getRigidBody()->getCenterOfMassPosition();
        btVector3 vel = getRigidBody()->getVelocityInLocalPoint( relpos );

        if (wheel.m_raycastInfo.m_isInContact)
        {
            const btTransform&	chassisWorldTransform = getChassisWorldTransform();

            btVector3 fwd (
                chassisWorldTransform.getBasis()[0][m_indexForwardAxis],
                chassisWorldTransform.getBasis()[1][m_indexForwardAxis],
                chassisWorldTransform.getBasis()[2][m_indexForwardAxis]);

            btScalar proj = fwd.dot(wheel.m_raycastInfo.m_contactNormalWS);
            fwd -= wheel.m_raycastInfo.m_contactNormalWS * proj;

            btScalar proj2 = fwd.dot(vel);

            wheel.m_deltaRotation = (proj2 * step) / (wheel.m_wheelsRadius);
            wheel.m_rotation += wheel.m_deltaRotation;

        } else
        {
            wheel.m_rotation += wheel.m_deltaRotation;
        }

        wheel.m_deltaRotation *= btScalar(0.99);//damping of rotation when not in contact

    }



}
Beispiel #2
0
// ----------------------------------------------------------------------------
void btKart::updateVehicle( btScalar step )
{
    for (int i=0;i<getNumWheels();i++)
    {
        updateWheelTransform(i,false);
    }

    const btTransform& chassisTrans = getChassisWorldTransform();

    btVector3 forwardW(chassisTrans.getBasis()[0][m_indexForwardAxis],
                       chassisTrans.getBasis()[1][m_indexForwardAxis],
                       chassisTrans.getBasis()[2][m_indexForwardAxis]);

    // Simulate suspension
    // -------------------

    m_num_wheels_on_ground       = 0;
    m_visual_wheels_touch_ground = true;
    for (int i=0;i<m_wheelInfo.size();i++)
    {
        btScalar depth;
        depth = rayCast( i);
        if(m_wheelInfo[i].m_raycastInfo.m_isInContact)
            m_num_wheels_on_ground++;
    }

    // If the kart is flying, try to keep it parallel to the ground.
    if(m_num_wheels_on_ground==0)
    {
        btVector3 kart_up    = getChassisWorldTransform().getBasis().getColumn(1);
        btVector3 terrain_up(0,1,0);
        btVector3 axis = kart_up.cross(terrain_up);
        // Give a nicely balanced feeling for rebalancing the kart
        m_chassisBody->applyTorqueImpulse(axis * m_kart->getKartProperties()->getSmoothFlyingImpulse());
    }

    // Work around: make sure that either both wheels on one axis
    // are on ground, or none of them. This avoids the problem of
    // the kart suddenly getting additional angular velocity because
    // e.g. only one rear wheel is on the ground.
    for(int i=0; i<m_wheelInfo.size(); i+=2)
    {
        if( m_wheelInfo[i  ].m_raycastInfo.m_isInContact !=
            m_wheelInfo[i+1].m_raycastInfo.m_isInContact)
        {
            int wheel_air_index = i;
            int wheel_ground_index = i+1;

            if (m_wheelInfo[i].m_raycastInfo.m_isInContact)
            {
                wheel_air_index = i+1;
                wheel_ground_index = i;
            }

            btWheelInfo& wheel_air = m_wheelInfo[wheel_air_index];
            btWheelInfo& wheel_ground = m_wheelInfo[wheel_ground_index];

            wheel_air.m_raycastInfo = wheel_ground.m_raycastInfo;
        }
    }   // for i=0; i<m_wheelInfo.size(); i+=2

    updateSuspension(step);


    for (int i=0;i<m_wheelInfo.size();i++)
    {
        //apply suspension force
        btWheelInfo& wheel = m_wheelInfo[i];

        btScalar suspensionForce = wheel.m_wheelsSuspensionForce;

        if (suspensionForce > wheel.m_maxSuspensionForce)
        {
            suspensionForce = wheel.m_maxSuspensionForce;
        }
        btVector3 impulse = wheel.m_raycastInfo.m_contactNormalWS
                            * suspensionForce * step;
        btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS
                         - getRigidBody()->getCenterOfMassPosition();

        getRigidBody()->applyImpulse(impulse, relpos);

    }

    updateFriction( step);


    for (int i=0;i<m_wheelInfo.size();i++)
    {
        btWheelInfo& wheel = m_wheelInfo[i];
        btVector3 relpos   = wheel.m_raycastInfo.m_hardPointWS
                           - getRigidBody()->getCenterOfMassPosition();
        btVector3 vel      = getRigidBody()->getVelocityInLocalPoint(relpos);

        if (wheel.m_raycastInfo.m_isInContact)
        {
            const btTransform& chassisWorldTransform =
                                                 getChassisWorldTransform();

            btVector3 fwd (
                chassisWorldTransform.getBasis()[0][m_indexForwardAxis],
                chassisWorldTransform.getBasis()[1][m_indexForwardAxis],
                chassisWorldTransform.getBasis()[2][m_indexForwardAxis]);

            btScalar proj = fwd.dot(wheel.m_raycastInfo.m_contactNormalWS);
            fwd -= wheel.m_raycastInfo.m_contactNormalWS * proj;

            btScalar proj2 = fwd.dot(vel);

            wheel.m_deltaRotation = (proj2 * step) / (wheel.m_wheelsRadius);
            wheel.m_rotation += wheel.m_deltaRotation;

        } else
        {
            wheel.m_rotation += wheel.m_deltaRotation;
        }
        //damping of rotation when not in contact
        wheel.m_deltaRotation *= btScalar(0.99);

    }
    float f = -m_kart->getSpeed()
            * m_kart->getKartProperties()->getDownwardImpulseFactor();
    btVector3 downwards_impulse = m_chassisBody->getWorldTransform().getBasis()
                                * btVector3(0, f, 0);

    m_chassisBody->applyCentralImpulse(downwards_impulse);

    if(m_time_additional_impulse>0)
    {
        float dt = step > m_time_additional_impulse
                 ? m_time_additional_impulse
                 : step;
        m_chassisBody->applyCentralImpulse(m_additional_impulse*dt);
        m_time_additional_impulse -= dt;
    }

    if(m_time_additional_rotation>0)
    {
        btTransform &t = m_chassisBody->getWorldTransform();
        float dt = step > m_time_additional_rotation
                 ? m_time_additional_rotation
                 : step;
        btQuaternion add_rot(m_additional_rotation.getY()*dt,
                             m_additional_rotation.getX()*dt,
                             m_additional_rotation.getZ()*dt);
        t.setRotation(t.getRotation()*add_rot);
        m_chassisBody->setWorldTransform(t);
        // Also apply the rotation to the interpolated world transform.
        // This is important (at least if the rotation is only applied
        // in one frame) since STK will actually use the interpolated
        // transform, which would otherwise only be updated one frame
        // later, resulting in a one-frame incorrect rotation of the
        // kart, or a strongly 'visual jolt' of the kart
        btTransform &iwt=m_chassisBody->getInterpolationWorldTransform();
        iwt.setRotation(iwt.getRotation()*add_rot);
        m_time_additional_rotation -= dt;
    }
}   // updateVehicle
Beispiel #3
0
// ----------------------------------------------------------------------------
void btKart::updateVehicle( btScalar step )
{
    updateAllWheelPositions();

    const btTransform& chassisTrans = getChassisWorldTransform();

    btVector3 forwardW(chassisTrans.getBasis()[0][m_indexForwardAxis],
                       chassisTrans.getBasis()[1][m_indexForwardAxis],
                       chassisTrans.getBasis()[2][m_indexForwardAxis]);

    // Simulate suspension
    // -------------------

    m_num_wheels_on_ground       = 0;
    m_visual_wheels_touch_ground = true;
    for (int i=0;i<m_wheelInfo.size();i++)
    {
        rayCast( i);
        if(m_wheelInfo[i].m_raycastInfo.m_isInContact)
            m_num_wheels_on_ground++;
    }

    // Test if the kart is falling so fast 
    // that the chassis might hit the track
    // ------------------------------------
    bool needs_cushioning_test = false;
    for(int i=0; i<m_wheelInfo.size(); i++)
    {
        btWheelInfo &wheel = m_wheelInfo[i];
        if(!wheel.m_was_on_ground && wheel.m_raycastInfo.m_isInContact)
        {
            needs_cushioning_test = true;
            break;
        }
    }
    if(needs_cushioning_test)
    {
        const btVector3 &v = m_chassisBody->getLinearVelocity();
        btVector3 down(0, 1, 0);
        btVector3 v_down = (v * down) * down;
        // Estimate what kind of downward speed can be compensated by the
        // suspension. Atm the parameters are set that the suspension is
        // actually capped at max suspension force, so the maximum
        // speed that can be caught by the suspension without the chassis
        // hitting the ground can be based on that. Note that there are
        // 4 suspensions, all adding together.
        btScalar max_compensate_speed = m_wheelInfo[0].m_maxSuspensionForce 
                                      * m_chassisBody->getInvMass() 
                                      * step * 4;
        // If the downward speed is too fast to be caught by the suspension,
        // slow down the falling speed by applying an appropriately impulse:
        if(-v_down.getY() > max_compensate_speed)
        {
            btVector3 impulse = down * (-v_down.getY() - max_compensate_speed) 
                              / m_chassisBody->getInvMass()*0.5f;
            //float v_old = m_chassisBody->getLinearVelocity().getY();
            //float x = m_wheelInfo[0].m_raycastInfo.m_isInContact ?    m_wheelInfo[0].m_raycastInfo.m_contactPointWS.getY() : -100;
            m_chassisBody->applyCentralImpulse(impulse);
            //Log::verbose("physics", "Cushioning %f from %f m/s to %f m/s wheel %f kart %f", impulse.getY(),
            //  v_old, m_chassisBody->getLinearVelocity().getY(), x,
            //                m_chassisBody->getWorldTransform().getOrigin().getY()
            //               );
        }
    }
    for(int i=0; i<m_wheelInfo.size(); i++)
        m_wheelInfo[i].m_was_on_ground = m_wheelInfo[i].m_raycastInfo.m_isInContact;


    // If the kart is flying, try to keep it parallel to the ground.
    // -------------------------------------------------------------
    if(m_num_wheels_on_ground==0)
    {
        btVector3 kart_up    = getChassisWorldTransform().getBasis().getColumn(1);
        btVector3 terrain_up =
            m_kart->getMaterial() && m_kart->getMaterial()->hasGravity() ?
            m_kart->getNormal() : Vec3(0, 1, 0);
        // Length of axis depends on the angle - i.e. the further awat
        // the kart is from being upright, the larger the applied impulse
        // will be, resulting in fast changes when the kart is on its
        // side, but not overcompensating (and therefore shaking) when
        // the kart is not much away from being upright.
        btVector3 axis = kart_up.cross(terrain_up);

        // To avoid the kart going backwards/forwards (or rolling sideways),
        // set the pitch/roll to 0 before applying the 'straightening' impulse.
        // TODO: make this works if gravity is changed.
        btVector3 av = m_chassisBody->getAngularVelocity();
        av.setX(0);
        av.setZ(0);
        m_chassisBody->setAngularVelocity(av);
        // Give a nicely balanced feeling for rebalancing the kart
        m_chassisBody->applyTorqueImpulse(axis * m_kart->getKartProperties()->getStabilitySmoothFlyingImpulse());
    }
    
    // Work around: make sure that either both wheels on one axis
    // are on ground, or none of them. This avoids the problem of
    // the kart suddenly getting additional angular velocity because
    // e.g. only one rear wheel is on the ground and then the kart
    // rotates very abruptly.
    for(int i=0; i<m_wheelInfo.size(); i+=2)
    {
        if( m_wheelInfo[i  ].m_raycastInfo.m_isInContact !=
            m_wheelInfo[i+1].m_raycastInfo.m_isInContact)
        {
            int wheel_air_index = i;
            int wheel_ground_index = i+1;

            if (m_wheelInfo[i].m_raycastInfo.m_isInContact)
            {
                wheel_air_index = i+1;
                wheel_ground_index = i;
            }

            btWheelInfo& wheel_air = m_wheelInfo[wheel_air_index];
            btWheelInfo& wheel_ground = m_wheelInfo[wheel_ground_index];

            wheel_air.m_raycastInfo = wheel_ground.m_raycastInfo;
        }
    }   // for i=0; i<m_wheelInfo.size(); i+=2


    // Apply suspension forcen (i.e. upwards force)
    // --------------------------------------------
    updateSuspension(step);

    for (int i=0;i<m_wheelInfo.size();i++)
    {
        //apply suspension force
        btWheelInfo& wheel = m_wheelInfo[i];

        btScalar suspensionForce = wheel.m_wheelsSuspensionForce;

        if (suspensionForce > wheel.m_maxSuspensionForce)
        {
            suspensionForce = wheel.m_maxSuspensionForce;
        }
        btVector3 impulse = wheel.m_raycastInfo.m_contactNormalWS
                            * suspensionForce * step;
        btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS
                         - getRigidBody()->getCenterOfMassPosition();

        getRigidBody()->applyImpulse(impulse, relpos);

    }

    // Update friction (i.e. forward force)
    // ------------------------------------
    updateFriction( step);

    for (int i=0;i<m_wheelInfo.size();i++)
    {
        btWheelInfo& wheel = m_wheelInfo[i];
        //btVector3 relpos   = wheel.m_raycastInfo.m_hardPointWS
        //                   - getRigidBody()->getCenterOfMassPosition();
        //btVector3 vel      = getRigidBody()->getVelocityInLocalPoint(relpos);

        if (wheel.m_raycastInfo.m_isInContact)
        {
            const btTransform& chassisWorldTransform =
                                                 getChassisWorldTransform();

            btVector3 fwd (
                chassisWorldTransform.getBasis()[0][m_indexForwardAxis],
                chassisWorldTransform.getBasis()[1][m_indexForwardAxis],
                chassisWorldTransform.getBasis()[2][m_indexForwardAxis]);

            btScalar proj = fwd.dot(wheel.m_raycastInfo.m_contactNormalWS);
            fwd -= wheel.m_raycastInfo.m_contactNormalWS * proj;
        } 
    }

    // If configured, add a force to keep karts on the track
    // -----------------------------------------------------
    float dif = m_kart->getKartProperties()->getStabilityDownwardImpulseFactor();
    if(dif!=0 && m_num_wheels_on_ground==4)
    {
        float f = -fabsf(m_kart->getSpeed()) * dif;
        btVector3 downwards_impulse = m_chassisBody->getWorldTransform().getBasis()
                                    * btVector3(0, f, 0);
        m_chassisBody->applyCentralImpulse(downwards_impulse);
    }

    // Apply additional impulse set by supertuxkart
    // --------------------------------------------
    if(m_time_additional_impulse>0)
    {
        float dt = step > m_time_additional_impulse
                 ? m_time_additional_impulse
                 : step;
        m_chassisBody->applyCentralImpulse(m_additional_impulse*dt);
        m_time_additional_impulse -= dt;
    }

    // Apply additional rotation set by supertuxkart
    // ---------------------------------------------
    if(m_time_additional_rotation>0)
    {
        btTransform &t = m_chassisBody->getWorldTransform();
        float dt = step > m_time_additional_rotation
                 ? m_time_additional_rotation
                 : step;
        btQuaternion add_rot(m_additional_rotation.getY()*dt,
                             m_additional_rotation.getX()*dt,
                             m_additional_rotation.getZ()*dt);
        t.setRotation(t.getRotation()*add_rot);
        m_chassisBody->setWorldTransform(t);
        // Also apply the rotation to the interpolated world transform.
        // This is important (at least if the rotation is only applied
        // in one frame) since STK will actually use the interpolated
        // transform, which would otherwise only be updated one frame
        // later, resulting in a one-frame incorrect rotation of the
        // kart, or a strongly 'visual jolt' of the kart
        btTransform &iwt=m_chassisBody->getInterpolationWorldTransform();
        iwt.setRotation(iwt.getRotation()*add_rot);
        m_time_additional_rotation -= dt;
    }
}   // updateVehicle
Beispiel #4
0
void Vehicle::initialize(btDiscreteDynamicsWorld &dynamicsWorld_in)
{		
	
//	SceneObject *nullObj;
	if (!cmap_obj)
	{
		cmap_obj = new Mesh;
		cmap_obj->cloneStructure(*obj);
	}



#ifndef ARCH_PSP
#ifndef OPENGL_ES
#ifndef ARCH_DC
	cmap_obj->triangulate();
#endif
#endif
#endif
	
	
	cmap = new CollisionMap;
	cmap->addMesh(*cmap_obj);
	
	colShape = cmap->makeCollisionShape(mass);

//	if (wheelObj)
//	{
//		// front left
//		wheelRef[0].bind(*wheelObj);
//		wheel[0].bindChild(wheelRef[0]);
//		wheel[0].setPosition(XYZ(0.486f,0.141f,-0.9125f));
//		wheel[0].setMatrixLock(true);
//		
//		// front right
//		wheelRef[1].bind(*wheelObj);
//		wheelRef[1].setRotation(XYZ(0,180,0));
//		wheel[1].bindChild(wheelRef[1]);
//		wheel[1].setPosition(XYZ(-0.486f,0.141f,-0.9125f));
//		wheel[1].setMatrixLock(true);
//
//		// front left
//		wheelRef[2].bind(*wheelObj);
//		wheelRef[2].setRotation(XYZ(0,180,0));
//		wheel[2].bindChild(wheelRef[2]);
//		wheel[2].setPosition(XYZ(0.486f,0.141f,0.843f));
//		wheel[2].setMatrixLock(true);
//		
//		// front right
//		wheelRef[3].bind(*wheelObj);
//		wheel[3].bindChild(wheelRef[3]);
//		wheel[3].setPosition(XYZ(-0.486f,0.141f,0.843f));
//		wheel[3].setMatrixLock(true);
//	}

	btVector3 wheelAxleCSR,wheelAxleCSL;

	wheelDirectionCS0 = btVector3(0,-1,0);
	wheelAxleCS = btVector3(-1,0,0);
	
	RigidSceneObject::initialize(dynamicsWorld_in);

	btTransform tr;
	tr.setIdentity();

	setPivot(XYZ(0,0,0));

	btCompoundShape* compound = new btCompoundShape();

	btTransform localTrans;
	localTrans.setIdentity();

	localTrans.setOrigin(btVector3(0,0,0));

	compound->addChildShape(localTrans,colShape);

	tr.setOrigin(btVector3(0,0.f,0));

	setMass(mass);

	mRigidBody = &createRigidBody(*compound);
	
	// reset scene
	gVehicleSteering = 0.f;
	mRigidBody->setCenterOfMassTransform(btTransform::getIdentity());
	mRigidBody->setLinearVelocity(btVector3(0,0,0));
	mRigidBody->setAngularVelocity(btVector3(0,0,0));

	//	dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(m_carChassis->getBroadphaseHandle(),dynamicsWorld->getDispatcher());
		
	/// create vehicle
	m_vehicleRayCaster = new btDefaultVehicleRaycaster(dynamicsWorld);
	m_vehicle = new btRaycastVehicle(m_tuning,mRigidBody,m_vehicleRayCaster);
			
	///never deactivate the vehicle
	mRigidBody->setActivationState(DISABLE_DEACTIVATION);

	dynamicsWorld->addVehicle(m_vehicle);
	
	//choose coordinate system
	m_vehicle->setCoordinateSystem(rightIndex,upIndex,forwardIndex);

//	btVector3 connectionPointCS0(axelWidth/2.0f,connectionHeight,frontAxelZ);
	
	for (unsigned int i = 0; i < wheels.size(); i++)
	{
		btVector3 wpos = wheels[i]->getWheelPosition().cast();
		
//		printf("Wheel Radius: %f\n",wheels[i]->getWheelRadius());
//		printf("Wheel Width: %f\n",wheels[i]->getWheelWidth());
		
		m_vehicle->addWheel(wpos,wheelDirectionCS0,wheelAxleCS,wheels[i]->getSuspensionRest(),wheels[i]->getWheelRadius(),m_tuning,wheels[i]->getSteering());
	}

//	connectionPointCS0 = btVector3(axelWidth/2.0f,connectionHeight,rearAxelZ);
//	m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxleCS,suspensionRestLength,wheelRadius,m_tuning,isFrontWheel);
	
	updateSuspension();

	/// end car

	//worldspaceChildren = true;
}