surfaceVelocity ¹Ý¿µ

ij¸¯ÅÍ°¡ ¹è³ª ºñÇà±â °°ÀÌ ¿òÁ÷ÀÌ´Â ÁöÇü À§¿¡ ÀÖÀ» ¶§´Â ¿òÁ÷ÀÌ´Â ÁöÇüÀÇ ¼Óµµ¸¦ ij¸¯ÅÍ¿¡ ¹Ý¿µÇØ¾ß ÇÑ´Ù.

ÇϺ¹ µ¥¸ðÀÇ MovingSupportRbDemo.cpp getGround( )¸¦ ÂüÁ¶ ÇÏ¿´´Ù.

1. Ç¥¸éÀÇ ¼Óµµ ±¸Çϱâ
ij¸¯ÅÍ°¡ ¿ùµåÀÇ Áö¸é°ú Ãæµ¹ ÇÏ°í ÀÖÀ» ¶§, Áï hkpSurfaceInfo::UNSUPPORTED°¡ ¾Æ´Ò¶§ ¿ùµå¿¡ Á¢ÇÑ Ç¥¸éÀÇ ¼Óµµ¸¦ ±¸ÇÑ´Ù. ¼Óµµ´Â surfaceInfo.m_surfaceVelocity·Î ¾ò¾î ¿Ã¼ö ÀÖ´Ù.

    //¿òÁ÷ÀÌ´Â ¿ùµåÀÇ ¼Óµµ¸¦ ij¸¯ÅÍ¿¡ ¹Ý¿µÇÑ´Ù.

    hkpSurfaceInfo surfaceInfo;

    {

        hkArray<hkpCharacterRigidBody::SupportInfo> supportInfo;

 

        hkStepInfo stepInfo;

        stepInfo.m_deltaTime = fTimestep;

        stepInfo.m_invDeltaTime = 1.0f / fTimestep;

        stepInfo.m_endTime = TIME_STEP;

        surfaceInfo.m_supportedState = m_pHavokRigidBody->getSupportInfo( stepInfo, supportInfo );

        if ( surfaceInfo.m_supportedState != hkpSurfaceInfo::UNSUPPORTED )

            GetGround( m_pHavokRigidBody, supportInfo, surfaceInfo );

    }

hkpCharacterInput¸¦ inputÀ¸·Î »ç¿ëÇÏ´Â °æ¿ì¿¡´Â hkArray<hkpCharacterRigidBody::SupportInfo>´ë½Å input.m_surfaceInfo¸¦ GetGround( ) ¼¼ ¹ø° ÀÎÀÚ¿¡ Àü´ÞÇÑ´Ù.

2. ¼Óµµ ´õÇϱâ

º» ¿¹Á¦¿¡¼­´Â hkpCharacterInput·Î  hkpCharacterContext::update( )¸¦ ÅëÇؼ­ hkpCharacterOutput ±¸ÇÏ°í ÀÖÁö ¾Ê±â ¶§¹®¿¡ hkpCharacterOutput °ª¿¡ Á÷Á¢ ´õÇØÁØ´Ù.

    //¿òÁ÷ÀÌ´Â ¿ùµåÀÇ ¼Óµµ¸¦ ´õÇÑ´Ù.

    output.m_velocity.add4( surfaceInfo.m_surfaceVelocity );

hkpCharacterInputÀ» ÀÌ¿ëÇϸé hkpCharacterOutput °ª¿¡ ´õÇÏ´Â °úÁ¤Àº ÇÊ¿ä ¾ø´Ù.

ĸ½¶ÇüÀÇ Ä³¸¯ÅÍ°¡ ¿òÁ÷ÀÌ´Â ¿ùµå¿¡ ¿Ã¶ó°¡¸é °°ÀÌ ¿òÁ÷ÀÏ °ÍÀÌ´Ù.

 

Âü°í) GetGround(  ) ¼Ò½º

//ÇϺ¹ µ¥¸ðÀÇ MovingSupportRbDemo.cpp getGround( ) Âü°í

void HavokCharacter::GetGround( hkpCharacterRigidBody* characterRigidBody, const hkArray<hkpCharacterRigidBody::SupportInfo>& supportInfo, hkpSurfaceInfo& ground ) const

{

    float fTimestep = 1.0f / 60.0f;

    // Produce an average version of the ground

 

    ground.m_surfaceVelocity.setZero4();

    ground.m_surfaceNormal.setZero4();

    ground.m_surfaceDistanceExcess = 0.0f;

    ground.m_surfaceIsDynamic = false;

 

    const int numSupportInfo = supportInfo.getSize();

    for ( int i = 0; i < numSupportInfo; ++i )

    {

        const hkpCharacterRigidBody::SupportInfo& support = supportInfo[i];

        ground.m_surfaceNormal.add4( support.m_point.getNormal() );

        ground.m_surfaceDistanceExcess += support.m_point.getDistance();

        const hkpMotion::MotionType motionType = support.m_rigidBody->getMotionType();

        if ( motionType == hkpMotion::MOTION_KEYFRAMED )

        {

            hkVector4 pointVelocity;

            support.m_rigidBody->getPointVelocity( support.m_point.getPosition(), pointVelocity );

            ground.m_surfaceVelocity.add4( pointVelocity );

        }

        /*

        else if ( motionType != hkpMotion::MOTION_FIXED )

        {

            ground.m_surfaceIsDynamic = true;

            if ( m_bodyType.getWithDefault ( support.m_rigidBody, false ) == hkBool32( true ) )

            {

                hkVector4 pointVelocity;

                support.m_rigidBody->getPointVelocity( support.m_point.getPosition(), pointVelocity );

                ground.m_surfaceVelocity.add4( pointVelocity );

            }

        }

        */

    }

 

    ground.m_surfaceNormal.normalize3();

    const hkReal portion = 1.f / numSupportInfo;

 

    ground.m_surfaceVelocity.mul4( portion );

    ground.m_surfaceDistanceExcess = ( ground.m_surfaceDistanceExcess * portion );

 

    if ( ground.m_surfaceIsDynamic )

    {

        // We need to apply the character's weight onto dynamic bodies. We do this by

        // setting a positive surfaceDistanceExcess which the controller should try

        // to reduce by applying gravity.

        ground.m_surfaceDistanceExcess = 0.01f;

    }

    else

    {

        // For fixed and keyframed bodies, we subtract m_hardSupportDistance from the excess

        // to ensure an extra gap below the character. This improves the smoothness of the

        // character's motion over the ground.

        ground.m_surfaceDistanceExcess -= characterRigidBody->m_hardSupportDistance;

    }

 

    // For dynamic supporting bodies which do keep velocity, we apply gravity representing the

    // force required to keep the character in position.

    hkVector4 impulse;

    {

        hkpWorld* pWorld = HavokManager::Instance()->GetWorld();

        impulse.setMul4( characterRigidBody->m_character->getMass() * fTimestep, pWorld->getGravity() );

        // We want the component of the impulse tangential to the surface.

        const hkSimdReal normal = impulse.dot3( ground.m_surfaceNormal );

        impulse.setAddMul4( impulse, ground.m_surfaceNormal, -normal );

        // Divide the amount of impulse by the number of supporting surfaces

        impulse.mul4( 1.0f / numSupportInfo );

    }

 

    /*

    for ( int i = 0; i < numSupportInfo; ++i )

    {

        const hkpCharacterRigidBody::SupportInfo& support = supportInfo[i];

 

        if ( m_bodyType.getWithDefault( support.m_rigidBody, false ) == hkBool32( true ) )

        {

            // Apply the impulse at the contact point.

            support.m_rigidBody->applyPointImpulse( impulse, support.m_point.getPosition() );

        }

    }

    */

}

  ÇÁ·ÎÁ§Æ® : havok_surfaceVelocity.zip