HavokDemo에서 캐릭터 제어

하복에서 캐릭터를 제어 하는 hkpCharacterRigidBody와 hkpCharacterProxy 2가지 방법이 있다.

이들 방법의 장단점을 알아보고 자세한 사용법에 대해서 설명한다.

< hkpCharacterRigidBody >

캐릭터를 제어하기 위한 새로운 방법이다. 시뮬레이션시 더 높은 퍼포먼스와 손실없는 시뮬레이션 퀄리티를 제공한다.

장점:

1. hkRidgidBody와 같이 월드를 시뮬레이션 할때, 물리적으로 움직인다. 멀티쓰레드에도 효과적이다.그래서, hkhkpCharacterRigidBody는 hkpCharacterProxy 보다 더 좋은 퍼포먼스를 제공한다.( 개인적으로 테스트 할때, 10배 이상의 프레임 차이가 있었다. )

2. hkhkpCharacterRigidBody는 월드 시뮬레이션을 할때, 동시에 충돌 시뮬레이션을 하면, 정확하게 충돌을 제어한다.

3. 캐릭터 충돌은 표준  hkpContactListener 인터페이스를 콜백한다.   hkRidgidBody나  월드처럼 적용된다.

 

단점:

1. hkhkpCharacterRigidBody는 물리 시뮬레이션 업데이트 주기에 맞춰서 업데이트가 필요하다. 하지만 실제 게임에서는 로직, 네트웍, Ai, 애니메이션과 동기화 되서 업데이트가 필요하다. 필요 할 때 업데이트 되는 것이 아니라 루프에서 주기적으로 업데이트 되기 때문에 로직과 동기화 시키는 것이 힘들다.

< hkpCharacterProxy >

장점:

1. 모든 플랫폼에서 오랫동안 사용되어온 시스템이다.

2. 주기적인 월드 업데이트와는 상관없이 로직, 플레이어의 입력, AI에 따라 직접 위치나 속도를 얻을수 있다.

 

단점:

1. 멀티쓰레드를 이용하기 힘들며,  hkpCharacterRigidBody보다 퍼포먼스가 느리다.

 

참고로 지구의 중력은 9.8kg이다.  hkpWorldCinfo에 값을 대입할 때 -9.5Kg이다.

hkpCharacterRigidBody의 최대 속도 제한을 풀기 위해서는 아래 세가지를 셋팅한다.

1) 지형상태에서 속도 설정
hkpCharacterState *state = new hkpCharacterStateOnGround();
static_cast<hkpCharacterStateOnGround*>(state)->setSpeed(30);

2) hkpCharacterRigidBodyCinfo의 m_maxLinearVelocity 값 설정
characterRigidBodyCInfo.m_maxLinearVelocity = 1000

3) characterContext의 속도 설정
m_characterContext->setFilterParameters( 0.9f, 1000, 1000.0f );

hkpCharacterRigidBody와 hkpCharacterProxy에서 땅에 닿았는지 확인하는 방법은 다음과 같다.
hkpCharacterProxy에서 충돌했는지 확인하는 방법은 원하는 벡터값을 값을 줄수 있기 때문에 게임로직에서 더 편리할 것 같다. 이건 나도 테스트 하지 않았다.

< hkpCharacterRigidBody에서 땅에 닿았는지 확인하는 방법 >

bool  HavokCharacter::IsSupported()

{

    hkReal timestep = 1.f / 60.f;

    // Check support

    hkpSurfaceInfo ground;

 

    hkStepInfo stepInfo;

    stepInfo.m_deltaTime = timestep;

    stepInfo.m_invDeltaTime = 1.f / timestep;

 

    hkpCharacterRigidBody* pCharRigidBody = m_pHavokRigidBody;

    //pCharRigidBody->getRigidBody()->markForRead();

    pCharRigidBody->checkSupport(stepInfo, ground);

    //pCharRigidBody->getRigidBody()->unmarkForRead();

 

    bool bRes = ( ground.m_supportedState != hkpSurfaceInfo::UNSUPPORTED );

    return bRes;

}

hkpCharacterRigidBody::checkSupport( )의 두 번째 인자 hkpSurfaceInfo로 이전 단계의 상태를 얻어온다.
hkpSurfaceInfo::m_supportedState는 3가지 상태를 알려준다.

UNSUPPORTED 공중에 있는 상태 
SLIDING 슬라이딩 상태
SUPPORTED 땅에 있는 상태

hkpSurfaceInfo는 이외에도 지표면의 노멀값, 지표면의 평균속도 ( m_surfaceNormal , m_surfaceVelocity )의 정보도 알수 있다.

< hkpCharacterProxy에서 땅에 닿았는지 확인하는 방법 >

bool  HavokActor::IsSupported()

{

    hkpSurfaceInfo ground;

    const  hkVector4 down(0.0f, 0.0f, -1.0f);

 

    m_characterProxy->checkSupport( down, ground );

    bool  bRes = ( ground.m_supportedState != hkpSurfaceInfo::UNSUPPORTED );

    return  bRes;

}

< 캐릭터를 제어 하는 방법 >

앞장에서 잘못한 것은 setLinearAccelerationToMassModifier( )는 m_characterContext->update( xInput, output ) 이후에 실행한다.

월드 좌표계가 Z-UP일때 forward는 m_forward.set( 0.0f, -1.0f, 0.0f )와 같이 셋팅한다.
foward의 y 값을 -1로 셋팅해야 모니터의 안쪽으로 y값이 증가하며, 오른쪽으로 갈수록 x값이 증가한다.

    float down = 0;

    if( IsSupported() == false )

        down = -5;

    output.m_velocity = hkVector4( fDX, fDZ, down );

    m_pHavokRigidBody->setLinearVelocity( output.m_velocity, fTimestep );

IsSupported( )는 현재 위치가 땅에 있는지 체크하는 것이다. IsSupported( )가 true이면 현재 위치에 바닥에 있고, false이면 공중에 있는 상태이므로 Z축 속도를 -5로 셋팅한다.

< hkpCharacterRigidBody에서 최대 속도 설정 >

hkpCharacterRigidBody::setLinearVelocity( )에서 속도를 올려도 원하는 속도가 나오지 않는다면 다음의 2가지를 체크하라.( m_maxLinearVelocity, setFilterParameters( ) )

    hkpCharacterRigidBodyCinfo characterRigidBodyCInfo;

    characterRigidBodyCInfo.m_maxLinearVelocity = 1000;

 

    hkpCharacterContext*    m_characterContext;

    m_characterContext->setFilterParameters(0.9f, 400, 400.0f);

프로젝트 :  HavokTest.zip

리소스 : MyTest.zip