hkpMotion::MOTION_KEYFRAMED

모션 타입의 설정은 hkpRigidBodyCinfo::m_motionType으로 hkpRigidBody 초기화나 setMotionType( )으로 설정 할 수 있다.

엘리베이트 같은 것을 구현 하기 위해 사용 되는 hkpMotion::MOTION_KEYFRAMED에 대해서 알아보자.

특징:

  • 모션 타입 hkpMotion::MOTION_KEYFRAMED은 일반적인 rigid body처럼 시뮬레이션 하지 않는다.
  • rigid body의 속도는 새로운 위치를 계산하기 위해 사용한다.
  • 정적 rigid body에는 충돌 안하지만 동적 rigid body와는 충돌 테스트를 한다.
  • 매 프레임 속도를 바꾸는 경우에 적합하다.
  • 엘리베이트와 같은 구현에 적헙하다.

 

1. hkpMotion::MOTION_KEYFRAMED 모션 타입의 hkpRigidBody 생성

hkpRigidBody* AddKeyFrameBox( hkpWorld* pWorld , const  hkVector4* position, const  hkVector4*  width )

{

    const  hkVector4& w = *width;

    const  hkVector4 halfExtents( w(0)/2.0f, w(1)/2.0f, w(2)/2.0f );

    hkpShape* fixedSurfaceShape = new  hkpBoxShape( halfExtents );

 

    hkpRigidBodyCinfo rigidBodyInfo;

 

    rigidBodyInfo.m_mass = 0.0f;

    rigidBodyInfo.m_shape = fixedSurfaceShape;

    rigidBodyInfo.m_motionType = hkpMotion::MOTION_KEYFRAMED;

    rigidBodyInfo.m_position = *position;

    rigidBodyInfo.m_friction = 1.0f;

    //rigidBodyInfo.m_collisionFilterInfo = hkpGroupFilter::calcFilterInfo(hkpGroupFilter::calcFilterInfo(1));

 

    //create new rigid body with supplied info

    hkpRigidBody* pRigidBody = new  hkpRigidBody( rigidBodyInfo );

    pRigidBody->addProperty( UID_WALL_PROPERTY, 8 );

 

    //add rigid body to physics world

    pWorld->lock();

    pWorld->addEntity( pRigidBody );

 

    //decerase reference counter for rigid body and shape

    pRigidBody->removeReference();

    fixedSurfaceShape->removeReference();

 

    pWorld->unlock();

    return  pRigidBody;

}

2. 매프레임 속도 설정

void  MoveKeyFrameBox()

{

    static  float  height = 0;

    static   bool  bPlus = true;

    float    step = 0.25f;   

 

    hkVector4 newPos;

    newPos = g_keyFrameRigidBox->getPosition();

 

    if( height >= 10 )

        bPlus = false;

    if( height <= -5 )

        bPlus = true;

 

    if( bPlus )

        height += step;

    else

        height -= step;

 

    newPos(1) = height;

 

    hkVector4 pos = g_keyFrameRigidBox->getPosition();

 

    hkVector4 newVelocity = g_keyFrameRigidBox->getLinearVelocity();

    newVelocity(1) = ( newPos(1) - pos(1) ) * 60.0f;

    g_keyFrameRigidBox->setLinearVelocity( newVelocity );

}

게임에서 엘리베이트를 적용하는 경우, 프로그램 적으로 엘리베이트를 움직이는 경우도 있지만, 애니메이션 값에 의해서 움직일수도 있다.

애니메이션 된 데이터의 값을 가져와서 충돌 메쉬(kpMotion::MOTION_KEYFRAMED 모션 타입이 적용된 hkpRigidBody )를 움직일때, hkpRigidBody::setPosition( )으로 움직이게 되면,  순간 이동으로 인하여 시뮬레이션이 정상적으로 되지 않는다.
엘리베이트 위에 있는 캐릭터가 바닥으로 떨어질지도 모른다.

원하는 위치로 이동 시키기 위해서 hkpRigidBody::setLinearVelocity( )에 의해 움직여야 시뮬레이션이 정상적으로 된다.

속도 설정으로 원하는 곳으로 이동을 할려면 시뮬레이션시 업데이트 되는 델타 시간의 값과 일치 시켜야 한다. 현재 프로젝트 에서는 한 프레임당 업데이트 델타 시간을 0.016초로 고정 시켰다( 실제 업데이트 시간은 0.016초가 아님).
그래서 초속 속도를 구하기 위해 60을 곱한다.

newVelocity(1) = ( newPos(1) - pos(1) ) * 60.0f;

우리는 한 프레임당 0.25씩 움직이기를 원하였다.  비쥬얼 스튜디오로 출력된 값을 보자.

< 비쥬얼 스튜디오로 출력된 값 >

1 : 위치 0.00, 0.50, 0.00, 속도 : 0.00, 14.99, 0.00
2 : 위치 0.00, 0.75, 0.00, 속도 : 0.00, 15.00, 0.00
3 : 위치 0.00, 1.00, 0.00, 속도 : 0.00, 15.00, 0.00
4 : 위치 0.00, 1.25, 0.00, 속도 : 0.00, 15.00, 0.00
5 : 위치 0.00, 1.50, 0.00, 속도 : 0.00, 15.00, 0.00

실제 게임에서도 속도 값으로 애니메이션 된 데이터와 충돌 데이터를 일치 시키는 것이 잘 될지는 잘 모르겠다.          

프로젝트:   havok_keyframed_motion.zip