Пример #1
0
/** Rotates and turns the wheels appropriately, and adjust for suspension
 *  updates the speed-weighted objects' animations. 
 *
 *  \param dt time since last frame
 *  \param distance How far the wheels have rotated since last time.
 *  \param steer The actual steer settings.
 *  \param suspension Suspension height for all four wheels.
 *  \param speed The speed of the kart in meters/sec, used for the
 *         speed-weighted objects' animations
 *  \param current_lean_angle How much the kart is leaning (positive meaning
 *         left side down)
 *  \param gt_replay_index The index to get replay data, used by ghost kart
 */
void KartModel::update(float dt, float distance, float steer, float speed,
                       float current_lean_angle, int gt_replay_index)
{
    core::vector3df wheel_steer(0, steer*30.0f, 0);

    for(unsigned int i=0; i<4; i++)
    {
        if (!m_kart || !m_wheel_node[i]) continue;
#ifdef DEBUG
        if (UserConfigParams::m_physics_debug &&
            !m_kart->isGhostKart())
        {
            const btWheelInfo &wi = m_kart->getVehicle()->getWheelInfo(i);
            // Make wheels that are not touching the ground invisible
            m_wheel_node[i]->setVisible(wi.m_raycastInfo.m_isInContact);
        }
#endif
        core::vector3df pos =  m_wheel_graphics_position[i].toIrrVector();

        float suspension_length = 0.0f;
        GhostKart* gk = dynamic_cast<GhostKart*>(m_kart);
        // Prevent using m_default_physics_suspension uninitialized
        if (gk && gt_replay_index == -1) break;

        if (gk)
        {
            suspension_length = gk->getSuspensionLength(gt_replay_index, i);
        }
        else
        {
            suspension_length = m_kart->getVehicle()->getWheelInfo(i).
                                m_raycastInfo.m_suspensionLength;
        }

        // Check documentation of Kart::updateGraphics for the following line
        pos.Y +=   m_default_physics_suspension[i]
                 - suspension_length
                 - m_kart_lowest_point;

        // Adjust the wheel position for lean: the lean can cause the 'leaned
        // to' side to be partly in the ground - which looks ok (like the tyres
        // being compressed), but the other side will be in the air. To avoid
        // this, increase the position of the wheels on the side that are
        // higher in the ground so that the wheel still touch the ground.
        if(current_lean_angle > 0 && (i&1) == 1)   // i&1 == 0: left side
        {
            pos.Y -= 2*current_lean_angle;
        }
        else if (current_lean_angle < 0 && (i&1) == 0)   // i&1 == 1: right side
        {
            pos.Y += 2*current_lean_angle;
        }
        m_wheel_node[i]->setPosition(pos);

        // Now calculate the new rotation: (old + change) mod 360
        float new_rotation = m_wheel_node[i]->getRotation().X
                           + distance / m_wheel_graphics_radius[i] * RAD_TO_DEGREE;
        new_rotation = fmodf(new_rotation, 360);
        core::vector3df wheel_rotation(new_rotation, 0, 0);
        // Only apply steer to first 2 wheels.
        if (i < 2)
            wheel_rotation += wheel_steer;
        m_wheel_node[i]->setRotation(wheel_rotation);
    } // for (i < 4)

    // If animations are disabled, stop here
    if (m_animated_node == NULL) return;

    if (m_play_non_loop && m_animated_node->getLoopMode() == true)
    {
        m_play_non_loop = false;
        this->setAnimation(AF_DEFAULT);
    }

    // Update the speed-weighted objects' animations
    if (m_kart != NULL)
    {
        for (size_t i = 0; i < m_speed_weighted_objects.size(); i++)
        {
            SpeedWeightedObject&    obj = m_speed_weighted_objects[i];

#define GET_VALUE(obj, value_name)   \
    obj.m_properties.value_name > SPEED_WEIGHTED_OBJECT_PROPERTY_UNDEFINED ? obj.m_properties.value_name : \
    m_kart->getKartProperties()->getSpeedWeightedObjectProperties().value_name

            // Animation strength
            float strength = 1.0f;
            const float strength_factor = GET_VALUE(obj, m_strength_factor);
            if (strength_factor >= 0.0f)
            {
                strength = speed * strength_factor;
                btClamp<float>(strength, 0.0f, 1.0f);
            }

            // Animation speed
            const float speed_factor = GET_VALUE(obj, m_speed_factor);
            if (speed_factor >= 0.0f)
            {
                float anim_speed = speed * speed_factor;
                obj.m_node->setAnimationSpeed(anim_speed);
            }

            // Texture animation
            core::vector2df tex_speed;
            tex_speed.X = GET_VALUE(obj, m_texture_speed.X);
            tex_speed.Y = GET_VALUE(obj, m_texture_speed.Y);
            if (tex_speed != core::vector2df(0.0f, 0.0f))
            {
                obj.m_texture_cur_offset += speed * tex_speed * dt;
                if (obj.m_texture_cur_offset.X > 1.0f) obj.m_texture_cur_offset.X = fmod(obj.m_texture_cur_offset.X, 1.0f);
                if (obj.m_texture_cur_offset.Y > 1.0f) obj.m_texture_cur_offset.Y = fmod(obj.m_texture_cur_offset.Y, 1.0f);

                for (unsigned int i = 0; i < obj.m_node->getMaterialCount(); i++)
                {
                    video::SMaterial &irrMaterial = obj.m_node->getMaterial(i);
                    for (unsigned int j = 0; j < video::MATERIAL_MAX_TEXTURES; j++)
                    {
                        video::ITexture* t = irrMaterial.getTexture(j);
                        if (!t) continue;
                        core::matrix4 *m = &irrMaterial.getTextureMatrix(j);
                        m->setTextureTranslate(obj.m_texture_cur_offset.X, obj.m_texture_cur_offset.Y);
                    }   // for j<MATERIAL_MAX_TEXTURES
                }   // for i<getMaterialCount
            }
#undef GET_VALUE
        }
    }

    // Check if the end animation is being played, if so, don't
    // play steering animation.
    if(m_current_animation!=AF_DEFAULT) return;

    if(m_animation_frame[AF_LEFT]<0) return;   // no animations defined

    // Update animation if necessary
    // -----------------------------
    float frame;
    if(steer>0.0f)      frame = m_animation_frame[AF_STRAIGHT]
                              - ( ( m_animation_frame[AF_STRAIGHT]
                                        -m_animation_frame[AF_RIGHT]  )*steer);
    else if(steer<0.0f) frame = m_animation_frame[AF_STRAIGHT]
                              + ( (m_animation_frame[AF_STRAIGHT]
                                        -m_animation_frame[AF_LEFT]   )*steer);
    else                frame = (float)m_animation_frame[AF_STRAIGHT];

    m_animated_node->setCurrentFrame(frame);
}   // update
Пример #2
0
/** Rotates and turns the wheels appropriately, and adjust for suspension
    + updates the speed-weighted objects' animations.
 *  \param dt time since last frame
 *  \param rotation_dt How far the wheels have rotated since last time.
 *  \param steer The actual steer settings.
 *  \param suspension Suspension height for all four wheels.
 *  \param speed The speed of the kart in meters/sec, used for the 
 *         speed-weighted objects' animations
 */
void KartModel::update(float dt, float rotation_dt, float steer,  float speed)
{
   core::vector3df wheel_steer(0, steer*30.0f, 0);

    for(unsigned int i=0; i<4; i++)
    {
        if(!m_wheel_node[i]) continue;
        const btWheelInfo &wi = m_kart->getVehicle()->getWheelInfo(i);
#ifdef DEBUG
        if(UserConfigParams::m_physics_debug && m_kart)
        {
            // Make wheels that are not touching the ground invisible
            m_wheel_node[i]->setVisible(wi.m_raycastInfo.m_isInContact);
        }
#endif
        float rel_suspension = wi.m_raycastInfo.m_suspensionLength
                             - m_default_physics_suspension[i];
        // If the suspension is too compressed
        if(rel_suspension< m_min_suspension[i])
            rel_suspension = m_min_suspension[i];
        else if(rel_suspension > m_max_suspension[i])
            rel_suspension = m_max_suspension[i];

        core::vector3df pos =  m_wheel_graphics_position[i].toIrrVector();
        pos.Y -= rel_suspension;

        m_wheel_node[i]->setPosition(pos);

        // Now calculate the new rotation: (old + change) mod 360
        float new_rotation = m_wheel_node[i]->getRotation().X
                             + rotation_dt * RAD_TO_DEGREE;
        new_rotation = fmodf(new_rotation, 360);
        core::vector3df wheel_rotation(new_rotation, 0, 0);
        // Only apply steer to first 2 wheels.
        if (i < 2)
            wheel_rotation += wheel_steer;
        m_wheel_node[i]->setRotation(wheel_rotation);
    } // for (i < 4)

    // If animations are disabled, stop here
    if (m_animated_node == NULL) return;

    // Update the speed-weighted objects' animations
    for(size_t i=0 ; i < m_speed_weighted_objects.size() ; i++)
    {
        SpeedWeightedObject&    obj = m_speed_weighted_objects[i];

#define GET_VALUE(obj, value_name)   \
    obj.m_properties.value_name > SPEED_WEIGHTED_OBJECT_PROPERTY_UNDEFINED ? obj.m_properties.value_name : \
    m_kart->getKartProperties()->getSpeedWeightedObjectProperties().value_name

        // Animation strength
        float strength = 1.0f;
        const float strength_factor =   GET_VALUE(obj, m_strength_factor);
        if(strength_factor >= 0.0f)
        {
            strength = speed * strength_factor;
            btClamp<float>(strength, 0.0f, 1.0f);
        }
        
        // Animation speed
        const float speed_factor =   GET_VALUE(obj, m_speed_factor);
        if(speed_factor >= 0.0f)
        {
            float anim_speed = speed * speed_factor;
            obj.m_node->setAnimationSpeed(anim_speed);
        }

        // Texture animation
        core::vector2df tex_speed;
        tex_speed.X = GET_VALUE(obj, m_texture_speed.X);
        tex_speed.Y = GET_VALUE(obj, m_texture_speed.Y);
        if(tex_speed != core::vector2df(0.0f, 0.0f))
        {
            obj.m_texture_cur_offset += speed * tex_speed * dt;
            if(obj.m_texture_cur_offset.X > 1.0f) obj.m_texture_cur_offset.X = fmod(obj.m_texture_cur_offset.X, 1.0f);
            if(obj.m_texture_cur_offset.Y > 1.0f) obj.m_texture_cur_offset.Y = fmod(obj.m_texture_cur_offset.Y, 1.0f);
            
            for(unsigned int i=0; i<obj.m_node->getMaterialCount(); i++)
            {
                video::SMaterial &irrMaterial=obj.m_node->getMaterial(i);
                for(unsigned int j=0; j<video::MATERIAL_MAX_TEXTURES; j++)
                {
                    video::ITexture* t=irrMaterial.getTexture(j);
                    if(!t) continue;
                    core::matrix4 *m = &irrMaterial.getTextureMatrix(j);
                    m->setTextureTranslate(obj.m_texture_cur_offset.X, obj.m_texture_cur_offset.Y);
                }   // for j<MATERIAL_MAX_TEXTURES
            }   // for i<getMaterialCount
        }
#undef GET_VALUE
    }

    // Check if the end animation is being played, if so, don't
    // play steering animation.
    if(m_current_animation!=AF_DEFAULT) return;

    if(m_animation_frame[AF_LEFT]<0) return;   // no animations defined

    // Update animation if necessary
    // -----------------------------
    float frame;
    if(steer>0.0f)      frame = m_animation_frame[AF_STRAIGHT]
                              - ( ( m_animation_frame[AF_STRAIGHT]
                                        -m_animation_frame[AF_RIGHT]  )*steer);
    else if(steer<0.0f) frame = m_animation_frame[AF_STRAIGHT]
                              + ( (m_animation_frame[AF_STRAIGHT]
                                        -m_animation_frame[AF_LEFT]   )*steer);
    else                frame = (float)m_animation_frame[AF_STRAIGHT];

    m_animated_node->setCurrentFrame(frame);
}   // update