예제 #1
0
void	btRaycastVehicle::updateWheelTransformsWS(btWheelInfo& wheel , bool interpolatedTransform)
{
    wheel.m_raycastInfo.m_isInContact = false;

    btTransform chassisTrans = getChassisWorldTransform();
    if (interpolatedTransform && (getRigidBody()->getMotionState()))
    {
        getRigidBody()->getMotionState()->getWorldTransform(chassisTrans);
    }

    wheel.m_raycastInfo.m_hardPointWS = chassisTrans( wheel.m_chassisConnectionPointCS );
    wheel.m_raycastInfo.m_wheelDirectionWS = chassisTrans.getBasis() *  wheel.m_wheelDirectionCS ;
    wheel.m_raycastInfo.m_wheelAxleWS = chassisTrans.getBasis() * wheel.m_wheelAxleCS;
}
예제 #2
0
void RaycastCar::updateVehicle( btScalar step )
{
    m_currentVehicleSpeedKmHour = btScalar(3.6f) * 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.0f))
        m_currentVehicleSpeedKmHour *= btScalar(-1.0f);

    for (int i = 0; i < getNumWheels(); i++)
    {
        updateWheelTransform(i, false);
        btScalar depth;
        depth = rayCast(m_wheelInfo[i]);
    }

    update_suspension(step);
    update_engine(step);
    update_forces(step);
    apply_impulses(step);
}
예제 #3
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

    }



}
예제 #4
0
파일: btKart.cpp 프로젝트: Flakebi/stk-code
// ----------------------------------------------------------------------------
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
예제 #5
0
파일: btKart.cpp 프로젝트: Flakebi/stk-code
btScalar btKart::rayCast(unsigned int index)
{
    btWheelInfo &wheel = m_wheelInfo[index];

    // Work around a bullet problem: when using a convex hull the raycast
    // would sometimes hit the chassis (which does not happen when using a
    // box shape). Therefore set the collision mask in the chassis body so
    // that it is not hit anymore.
    short int old_group=0;
    if(m_chassisBody->getBroadphaseHandle())
    {
        old_group = m_chassisBody->getBroadphaseHandle()
                                 ->m_collisionFilterGroup;
        m_chassisBody->getBroadphaseHandle()->m_collisionFilterGroup = 0;
    }

    updateWheelTransformsWS( wheel,false);

    btScalar max_susp_len = wheel.getSuspensionRestLength()
                          + wheel.m_maxSuspensionTravel;

    // Do a slightly longer raycast to see if the kart might soon hit the 
    // ground and some 'cushioning' is needed to avoid that the chassis
    // hits the ground.
    btScalar raylen = max_susp_len + 0.5f;

    btVector3 rayvector = wheel.m_raycastInfo.m_wheelDirectionWS * (raylen);
    const btVector3& source = wheel.m_raycastInfo.m_hardPointWS;
    wheel.m_raycastInfo.m_contactPointWS = source + rayvector;
    const btVector3& target = wheel.m_raycastInfo.m_contactPointWS;

    btVehicleRaycaster::btVehicleRaycasterResult rayResults;

    btAssert(m_vehicleRaycaster);

    void* object = m_vehicleRaycaster->castRay(source,target,rayResults);

    wheel.m_raycastInfo.m_groundObject = 0;

    btScalar depth =  raylen * rayResults.m_distFraction;
    if (object &&  depth < max_susp_len)
    {
        wheel.m_raycastInfo.m_contactNormalWS  = rayResults.m_hitNormalInWorld;
        wheel.m_raycastInfo.m_contactNormalWS.normalize();
        wheel.m_raycastInfo.m_isInContact = true;
        ///@todo for driving on dynamic/movable objects!;
        wheel.m_raycastInfo.m_triangle_index = rayResults.m_triangle_index;;
        wheel.m_raycastInfo.m_groundObject = &getFixedBody();

        wheel.m_raycastInfo.m_suspensionLength = depth;

        //clamp on max suspension travel
        btScalar minSuspensionLength = wheel.getSuspensionRestLength()
                                - wheel.m_maxSuspensionTravel;
        btScalar maxSuspensionLength = wheel.getSuspensionRestLength()
                                + wheel.m_maxSuspensionTravel;
        if (wheel.m_raycastInfo.m_suspensionLength < minSuspensionLength)
        {
            wheel.m_raycastInfo.m_suspensionLength = minSuspensionLength;
        }
        if (wheel.m_raycastInfo.m_suspensionLength > maxSuspensionLength)
        {
            wheel.m_raycastInfo.m_suspensionLength = maxSuspensionLength;
        }

        wheel.m_raycastInfo.m_contactPointWS = rayResults.m_hitPointInWorld;

        btScalar denominator = wheel.m_raycastInfo.m_contactNormalWS.dot(
                                      wheel.m_raycastInfo.m_wheelDirectionWS );

        btVector3 chassis_velocity_at_contactPoint;
        btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS
                         - getRigidBody()->getCenterOfMassPosition();

        chassis_velocity_at_contactPoint =
            getRigidBody()->getVelocityInLocalPoint(relpos);

        btScalar projVel = wheel.m_raycastInfo.m_contactNormalWS.dot(
                                            chassis_velocity_at_contactPoint );

        if ( denominator >= btScalar(-0.1))
        {
            wheel.m_suspensionRelativeVelocity = btScalar(0.0);
            wheel.m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1);
        }
        else
        {
            btScalar inv = btScalar(-1.) / denominator;
            wheel.m_suspensionRelativeVelocity = projVel * inv;
            wheel.m_clippedInvContactDotSuspension = inv;
        }

    } else
    {
        depth = btScalar(-1.0);
        //put wheel info as in rest position
        wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength();
        wheel.m_suspensionRelativeVelocity = btScalar(0.0);
        wheel.m_raycastInfo.m_contactNormalWS =
            - wheel.m_raycastInfo.m_wheelDirectionWS;
        wheel.m_clippedInvContactDotSuspension = btScalar(1.0);
    }

#define USE_VISUAL
#ifndef USE_VISUAL
    m_visual_contact_point[index] = rayResults.m_hitPointInWorld;
#else
    if(index==2 || index==3)
    {
        btTransform chassisTrans = getChassisWorldTransform();
        if (getRigidBody()->getMotionState())
        {
            getRigidBody()->getMotionState()->getWorldTransform(chassisTrans);
        }
        btQuaternion q(m_visual_rotation, 0, 0);
        btQuaternion rot_new = chassisTrans.getRotation() * q;
        chassisTrans.setRotation(rot_new);
        btVector3 pos = m_kart->getKartModel()->getWheelGraphicsPosition(index);
        pos.setZ(pos.getZ()*0.9f);
        btVector3 source = chassisTrans( pos );
        btVector3 target = source + rayvector;
        btVehicleRaycaster::btVehicleRaycasterResult rayResults;

        void* object = m_vehicleRaycaster->castRay(source,target,rayResults);
        m_visual_contact_point[index] = rayResults.m_hitPointInWorld;
        m_visual_contact_point[index-2] = source;
        m_visual_wheels_touch_ground &= (object!=NULL);
    }
#endif

    if(m_chassisBody->getBroadphaseHandle())
    {
        m_chassisBody->getBroadphaseHandle()->m_collisionFilterGroup
            = old_group;
    }


    return depth;

}   // rayCast
예제 #6
0
void RaycastCar::update_engine(btScalar step)
{
    const btTransform & chassis_t = getChassisWorldTransform();
    btVector3 fwd(chassis_t.getBasis()[0][m_indexForwardAxis],
                  chassis_t.getBasis()[1][m_indexForwardAxis],
                  chassis_t.getBasis()[2][m_indexForwardAxis]);

    WheelInfo & wheelInfo0 = m_wheelInfo[0];
    wheelInfo0.m_last_linear_velocity = wheelInfo0.m_linear_velocity;
    btVector3 relpos0      = wheelInfo0.m_raycastInfo.m_hardPointWS - getRigidBody()->getCenterOfMassPosition();
    btVector3 vel0         = getRigidBody()->getVelocityInLocalPoint(relpos0);
    btScalar  proj0        = fwd.dot(wheelInfo0.m_raycastInfo.m_contactNormalWS);
    btVector3 fwd_w0       = fwd - wheelInfo0.m_raycastInfo.m_contactNormalWS * proj0;
    btScalar  lin_vel0     = fwd_w0.dot(vel0);
    btScalar  w0_rpm       = fabs(rads2rpm(lin_vel0/wheelInfo0.m_wheelsRadius));
    btScalar  delta0       = (lin_vel0/wheelInfo0.m_wheelsRadius)*step;
    wheelInfo0.m_linear_velocity  = lin_vel0;
    wheelInfo0.m_angular_velocity = lin_vel0/wheelInfo0.m_wheelsRadius;

    WheelInfo & wheelInfo1 = m_wheelInfo[1];
    wheelInfo1.m_last_linear_velocity = wheelInfo1.m_linear_velocity;
    btVector3 relpos1      = wheelInfo1.m_raycastInfo.m_hardPointWS - getRigidBody()->getCenterOfMassPosition();
    btVector3 vel1         = getRigidBody()->getVelocityInLocalPoint(relpos1);
    btScalar  proj1        = fwd.dot(wheelInfo1.m_raycastInfo.m_contactNormalWS);
    btVector3 fwd_w1       = fwd - wheelInfo1.m_raycastInfo.m_contactNormalWS * proj1;
    btScalar  lin_vel1     = fwd_w1.dot(vel1);
    btScalar  w1_rpm       = fabs(rads2rpm(lin_vel1/wheelInfo1.m_wheelsRadius));
    btScalar  delta1       = (lin_vel1/wheelInfo1.m_wheelsRadius)*step;
    wheelInfo1.m_linear_velocity  = lin_vel1;
    wheelInfo1.m_angular_velocity = lin_vel1/wheelInfo1.m_wheelsRadius;

    WheelInfo & wheelInfo2 = m_wheelInfo[2];
    wheelInfo2.m_last_linear_velocity = wheelInfo2.m_linear_velocity;
    btVector3 relpos2      = wheelInfo2.m_raycastInfo.m_hardPointWS - getRigidBody()->getCenterOfMassPosition();
    btVector3 vel2         = getRigidBody()->getVelocityInLocalPoint(relpos2);
    btScalar  proj2        = fwd.dot(wheelInfo2.m_raycastInfo.m_contactNormalWS);
    btVector3 fwd_w2       = fwd - wheelInfo2.m_raycastInfo.m_contactNormalWS * proj2;
    btScalar  lin_vel2     = fwd_w2.dot(vel2);
//btScalar  w2_rpm       = fabs(rads2rpm(lin_vel2/wheelInfo2.m_wheelsRadius));
    btScalar  delta2       = (lin_vel2/wheelInfo2.m_wheelsRadius)*step;
    wheelInfo2.m_linear_velocity  = lin_vel2;
    wheelInfo2.m_angular_velocity = lin_vel2/wheelInfo2.m_wheelsRadius;

    WheelInfo & wheelInfo3 = m_wheelInfo[3];
    wheelInfo3.m_last_linear_velocity = wheelInfo3.m_linear_velocity;
    btVector3 relpos3      = wheelInfo3.m_raycastInfo.m_hardPointWS - getRigidBody()->getCenterOfMassPosition();
    btVector3 vel3         = getRigidBody()->getVelocityInLocalPoint(relpos3);
    btScalar  proj3        = fwd.dot(wheelInfo3.m_raycastInfo.m_contactNormalWS);
    btVector3 fwd_w3       = fwd - wheelInfo3.m_raycastInfo.m_contactNormalWS * proj3;
    btScalar  lin_vel3     = fwd_w3.dot(vel3);
//btScalar  w3_rpm       = fabs(rads2rpm(lin_vel3/wheelInfo3.m_wheelsRadius));
    btScalar  delta3       = (lin_vel3/wheelInfo3.m_wheelsRadius)*step;
    wheelInfo3.m_linear_velocity  = lin_vel3;
    wheelInfo3.m_angular_velocity = lin_vel3/wheelInfo3.m_wheelsRadius;

/////////////////////////////
//
// Update engine
//
//
    m_last_engine_rpm = m_engine_rpm;
    m_last_throttle   = m_throttle;

    btScalar to_engine_rpm = btScalar(0.0f);
    if (m_differential_type == 0)
    {
        to_engine_rpm = btMax(wheelInfo2.m_rpm,wheelInfo3.m_rpm);
    }

    if (m_gear == 1) // idle
    {
        m_engine_rpm = btScalar(m_rpm_data[m_graphs_size-1]*m_throttle);
    }
    else
    {
        m_engine_rpm = to_engine_rpm*m_gears_coefficients[m_gear]*m_final_drive*m_gears_eff;
    }

    if (m_engine_rpm > btScalar(m_rpm_data[m_graphs_size-1]*m_throttle))
    {
        m_engine_rpm = m_rpm_data[m_graphs_size-1]*m_throttle;
    }
    if (m_engine_rpm < btScalar(m_rpm_data[0])) {
        m_engine_rpm = btScalar(m_rpm_data[0]);
    }

    btScalar torque = lookup_value(m_engine_rpm, m_rpm_data,m_torque_data,m_graphs_size)*m_throttle;

#ifdef SHOW_MOTOR_INFO
    m_info_engine_torque = torque;
    m_info_engine_power = (torque*2.0f*SIMD_PI*m_engine_rpm)/60.0f;
#endif
    m_info_engine_rpm   = m_engine_rpm + (rand() % 10 + 1);

// drive force to apply to chassis at both rear wheel's
// contact points in local space
    btScalar Fdrive;
    if (m_gear == 0)
    {
        Fdrive = (m_gears_coefficients[m_gear]*m_gears_eff*torque)/wheelInfo2.m_wheelsRadius;
        Fdrive *=  0.5f; // per wheel
        Fdrive *= -1.0f;
    }
    //if (m_gear == 1)
    //{
    //Fdrive = btScalar(0.0f);
    //}
    else
    {
        Fdrive = (m_gears_coefficients[m_gear]*m_final_drive*m_gears_eff*torque)/wheelInfo2.m_wheelsRadius;
        Fdrive *=  0.5f; // per wheel
    }

    btScalar to_rear_wheel_rpm;

// acceleration (depends on m_inertia_coef) is essential to update engine RPM
    btScalar acceleration = (torque*m_gears_coefficients[m_gear]*m_final_drive*m_gears_eff)/m_inertia_coef;
    btScalar engine_rpm = m_engine_rpm + rads2rpm(acceleration)*step;

    if (m_gear == 0)
    {
        to_rear_wheel_rpm = engine_rpm/(m_gears_coefficients[m_gear]*m_gears_eff);
        to_rear_wheel_rpm *= 0.2f; //?
        wheelInfo2.m_engine_force = wheelInfo3.m_engine_force = Fdrive;
        wheelInfo2.m_rpm = wheelInfo3.m_rpm  = to_rear_wheel_rpm;
        if (to_rear_wheel_rpm
                >
                (m_rpm_data[m_graphs_size-1]*m_throttle)/(m_gears_coefficients[m_gear]*m_final_drive*m_gears_eff))
        {
            to_rear_wheel_rpm = (m_rpm_data[m_graphs_size-1]*m_throttle)/(m_gears_coefficients[m_gear]*m_final_drive*m_gears_eff);
        }
    }
    else if (m_gear == 1)
    {
        to_rear_wheel_rpm = 0.0f;
        wheelInfo2.m_engine_force = wheelInfo3.m_engine_force = btScalar(0.0f);
        wheelInfo2.m_rpm = wheelInfo3.m_rpm = to_rear_wheel_rpm = 0.0f;
    }
    else
    {
        to_rear_wheel_rpm = engine_rpm/(m_gears_coefficients[m_gear]*m_final_drive*m_gears_eff);
        wheelInfo2.m_engine_force = wheelInfo3.m_engine_force = Fdrive;
        wheelInfo2.m_rpm = wheelInfo3.m_rpm  = to_rear_wheel_rpm;
        if (to_rear_wheel_rpm > (m_rpm_data[m_graphs_size-1]*m_throttle)/(m_gears_coefficients[m_gear]*m_final_drive*m_gears_eff))
        {
            to_rear_wheel_rpm = (m_rpm_data[m_graphs_size-1]*m_throttle)/(m_gears_coefficients[m_gear]*m_final_drive*m_gears_eff);
        }
    }

    btScalar rear_wheel_delta = rpm2rads(to_rear_wheel_rpm)*step;
//
//
//
/////////////////////////////

/////////////////////////////
//
// Update wheel rotation
//

    if (wheelInfo0.m_brake > btScalar(0.0f)) delta0 = btScalar(0.0f);
    if (wheelInfo1.m_brake > btScalar(0.0f)) delta1 = btScalar(0.0f);
    if (wheelInfo2.m_brake > btScalar(0.0f))
    {
        delta2           = btScalar(0.0f);
        rear_wheel_delta = btScalar(0.0f);
    }
    if (wheelInfo3.m_brake > btScalar(0.0f))
    {
        delta3           = btScalar(0.0f);
        rear_wheel_delta = btScalar(0.0f);
    }

// 0
    if (wheelInfo0.m_raycastInfo.m_isInContact)
    {
        wheelInfo0.m_rotation += delta0;
        wheelInfo0.m_rpm = w0_rpm;
    }
    else
    {
        wheelInfo0.m_rotation *= 0.99f;
    }

// 1
    if (wheelInfo1.m_raycastInfo.m_isInContact)
    {
        wheelInfo1.m_rotation += delta1;
        wheelInfo1.m_rpm = w1_rpm;
    }
    else
    {
        wheelInfo1.m_rotation *= 0.99f;
    }

// 2
    if ( wheelInfo2.m_raycastInfo.m_isInContact
            &&
            ( fabs(rear_wheel_delta)
              <
              fabs(delta2) ) )
    {
        wheelInfo2.m_rotation += delta2;
    }
    else
    {
        if ((m_throttle > btScalar(0.0f)) && (m_gear != 1))
        {
            if (m_gear == 0)
            {
                wheelInfo2.m_rotation -= rear_wheel_delta;
            }
            else
            {
                wheelInfo2.m_rotation += rear_wheel_delta;
            }
        }
    }

// 3
    if ( wheelInfo3.m_raycastInfo.m_isInContact
            &&
            ( fabs(rear_wheel_delta)
              <
              fabs(delta3) ) )
    {
        wheelInfo3.m_rotation += delta3;
    }
    else
    {
        if ((m_throttle > btScalar(0.0f)) && (m_gear != 1))
        {
            if (m_gear == 0)
            {
                wheelInfo3.m_rotation -= rear_wheel_delta;
            }
            else
            {
                wheelInfo3.m_rotation += rear_wheel_delta;
            }
        }
    }
//
//
/////////////////////////////

}
예제 #7
0
파일: btKart.cpp 프로젝트: clasik/stk-code
// ----------------------------------------------------------------------------
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