HavokCharacter

À̹øÀå¿¡´Â hkpCharacterContext::HK_CHARACTER_RIGIDBODY ŸÀÔÀ¸·Î ¼ÂÆÃÇÏ¿© ij¸¯Å͸¦ Á¦¾î ÇÑ´Ù.

´ÙÀ½ÀÇ ¸Þ¼Òµå ¼ø¼­·Î ¾Ë¾Æ º»´Ù.

void HavokCharacter::Create( )
void HavokCharacter::Destroy()
void HavokCharacter::Update( )
void HavokCharacter::SetPosition( )

void HavokCharacter::Create( const hkVector4& position )

{

    ..................

    hkVector4 scaledPosition = position;

    scaledPosition.mul4( fHAVOK_SCALE );

 

    // Define the shapes for the controller

    hkVector4 va( 0.0f, 0.0f, 0.1f );

    hkVector4 vb( 0.0f, 0.0f, -0.1f );

    m_pStandShape = new hkpCapsuleShape( va, vb, 1.1f );       

 

    va.setZero4();

    m_pCrouchShape = new hkpCapsuleShape( va, vb, 0.6f );

 

    // Construct a character rigid body

    hkpCharacterRigidBodyCinfo characterRigidBodyCInfo;

    characterRigidBodyCInfo.m_mass = 100.0f;

    characterRigidBodyCInfo.m_shape = m_pStandShape;

 

    characterRigidBodyCInfo.m_maxForce = 1000.0f;

    characterRigidBodyCInfo.m_up = m_up;

    characterRigidBodyCInfo.m_position.set( position(0), position(1), position(2) );

    //characterRigidBodyCInfo.m_maxSlope = 65.0f * HK_REAL_DEG_TO_RAD;

    characterRigidBodyCInfo.m_maxSlope = 90.0f * HK_REAL_DEG_TO_RAD;

    characterRigidBodyCInfo.m_friction = 0;

    characterRigidBodyCInfo.m_unweldingHeightOffsetFactor = 5;

    characterRigidBodyCInfo.m_maxLinearVelocity = 1000;

 

    m_pHavokRigidBody = new hkpCharacterRigidBody( characterRigidBodyCInfo );

 

    hkpCharacterRigidBodyListener* pListener = new hkpCharacterRigidBodyListener();

    m_pHavokRigidBody->setListener( pListener );

    pListener->removeReference();

 

    pWorld->lock();

    pWorld->markForWrite();

 

    pWorld->addEntity( m_pHavokRigidBody->getRigidBody() );

 

    hkpCharacterState* pState = NULL;

    hkpCharacterStateManager* pManager = new hkpCharacterStateManager();

 

    pState = new hkpCharacterStateOnGround();

    pManager->registerState( pState, HK_CHARACTER_ON_GROUND );

    pState->removeReference();

    ................................

    m_characterContext = new hkpCharacterContext( pManager, HK_CHARACTER_ON_GROUND );

    pManager->removeReference();

 

    m_characterContext->setCharacterType( hkpCharacterContext::HK_CHARACTER_RIGIDBODY );

    //m_characterContext->setFilterParameters(0.9f, 30, 400.0f);

 

    pWorld->unmarkForWrite();

    pWorld->unlock();

}

ij¸¯ÅÍÀÇ Ã浹ü¸¦ ÀϹÝÀûÀÎ ÇüÅ m_pStandShape¿Í Âޱ׸° m_pCrouchShape·Î µÎ °³¸¦ ¸¸µé¾î »ç¿ëÇÑ´Ù.

HavokActoró·³ hkpCharacterStateManager¿¡  ´ÙÀ½ÀÇ Ä³¸¯ÅÍ »óŸ¦ µî·ÏÇÑ´Ù.

hkpCharacterStateOnGround
hkpCharacterStateInAir
hkpCharacterStateJumping
hkpCharacterStateClimbing

hkpCharacterStateManager·Î hkpCharacterContext¸¦ ¼³Á¤ÇÑ´Ù.
ij¸¯ÅÍ Å¸ÀÔÀº hkpCharacterContext::HK_CHARACTER_RIGIDBODY·Î ¼³Á¤ÇÑ´Ù.

outputÀÇ ÃÖ´ë ¼Óµµ¸¦ ¼³Á¤ÇÏ´Â setFilterParameters( )´Â ÁÖ¼® ó¸® ÇÑ´Ù.

void  HavokCharacter::Destroy()

{

    if( !m_bActive )

        return;

 

    m_bActive = false;

 

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

    if( pWorld == NULL )

        return;

 

    m_pHavokRigidBody->removeReference();

    m_pStandShape->removeReference();

    m_pCrouchShape->removeReference();

    delete  m_characterContext;

    m_pHavokRigidBody = NULL;

}

Ãæµ¹ ¸Þ½¬¿Í m_characterContext, m_pHavokRigidBody¸¦ ÇØÁ¦ÇÑ´Ù.

void  HavokCharacter::Update( const  float  fTimestep )

{

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

    if( pWorld == NULL )

        return;

 

    if( m_pHavokRigidBody == NULL )

        return;

 

    const  bool  bJump = m_bCameraControl && ( !m_bOldJump && GetKey( VK_SPACE ) );

    const  bool  bCrouch = m_bCameraControl && GetKey( 'C' );

    m_bOldJump = m_bCameraControl && GetKey( VK_SPACE );

 

    pWorld->lock();

    pWorld->markForWrite();

 

 

    hkVector4 p = m_pHavokRigidBody->getPosition();

 

    // TODO - the input code belongs in a player class or something

    hkpCharacterInput    xInput;

    hkpCharacterOutput    output;

 

    float  fDX = 0.0f;

    float  fDZ = 0.0f;

    float  fStepWidth = CHARACTER_SCALE_RATIO * 0.5f;

 

    if( m_bCameraControl )

    {

        if( GetKey( VK_UP ) )

        {

            fDZ -= fStepWidth;

        }

 

        if( GetKey( VK_DOWN ) )

        {

            fDZ += fStepWidth;

        }

 

        if( GetKey( VK_LEFT ) )

        {

            fDX -= fStepWidth;

        }

 

        if( GetKey( VK_RIGHT ) )

        {

            fDX += fStepWidth;

        }

    }

    else

    {

        fDX = m_xMovement.x;

        fDZ = m_xMovement.y;

    }

 

    xInput.m_inputLR = fDX;

    xInput.m_inputUD = fDZ;

 

    xInput.m_wantJump = bJump;

    xInput.m_atLadder = false;

 

    xInput.m_up = m_up;

 

    xInput.m_forward = m_forward;

    xInput.m_forward.normalize3();

 

    hkQuaternion orient;

    orient.setAxisAngle( m_up, 0 );

    xInput.m_forward.setRotatedDir( orient, xInput.m_forward );

 

    hkStepInfo stepInfo;

    stepInfo.m_deltaTime = fTimestep;

    stepInfo.m_invDeltaTime = 1.0f / fTimestep;

    //stepInfo.m_endTime = HavokManager::Instance()->GetStopwatch()->getElapsedSeconds();

    xInput.m_stepInfo = stepInfo;

 

    hkVector4 characterGravity = m_up;

    float gravity = -16 * CHARACTER_SCALE_RATIO;

    characterGravity.mul4( hkVector4(  gravity, gravity, gravity ) );  

    xInput.m_characterGravity = characterGravity;

 

    hkpRigidBody* const  pRigidBody = m_pHavokRigidBody->getRigidBody();

 

    xInput.m_velocity = pRigidBody->getLinearVelocity();

    xInput.m_position = pRigidBody->getPosition();

 

    m_pHavokRigidBody->checkSupport( stepInfo, xInput.m_surfaceInfo );

 

    const  hkpCollidable* const  pCollidable = pRigidBody->getCollidable();

    if( pRigidBody == NULL )

    {

        assert( 0 && "A character's Havok collidable pointer has been nulled. We are going to assume they aren't crouching." );

    }

 

    const  bool  bIsCrouched = pCollidable ? ( pRigidBody->getCollidable()->getShape() == m_pCrouchShape ) : false;

 

    if ( bIsCrouched && !bCrouch )

        pRigidBody->setShape( m_pStandShape );

 

    if ( !bIsCrouched && bCrouch )

        pRigidBody->setShape( m_pCrouchShape );

 

    // Calculate and set current acceleration for mass factor modifier

    {

        // calculate and set acceleration for mass factor modifier

        hkVector4 currentVel;

        currentVel = pRigidBody->getLinearVelocity();

 

        hkVector4 currentAcc;

        currentAcc.setSub4(output.m_velocity, currentVel);

        currentAcc.mul4( 1/fTimestep );

 

        m_pHavokRigidBody->setLinearAccelerationToMassModifier(currentAcc);

    }

 

 

    // Apply the character state machine

    m_characterContext->update( xInput, output );

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

 

    pWorld->unmarkForWrite();

    pWorld->unlock();

}

¹°¸® ½Ã¹Ä·¹À̼ÇÀ» ÇÏ´Â °÷ÀÌ´Ù.

Å°º¸µå ÀԷ°ªÀ¸·Î input °ªÀ» ä¿ö¼­ outputÀ¸·Î º¯È¯ÇÑ´Ù.
m_characterContext->update( xInput, output )

¼Óµµ¸¦ ¼³Á¤ÇÑ´Ù.

m_pHavokRigidBody->setLinearVelocity( output.m_velocity, fTimestep )

 

ÇÁ·Ï½Ã ÇüÀÎ hkpCharacterContext::HK_CHARACTER_PROXY°ú´Â ´Þ¸® intergrate( ) ¸í·ÉÀÌ ÇÊ¿ä ¾ø´Ù.

 

void  HavokCharacter::SetPosition( float  x, float  y, float  z )

{

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

    pWorld->lock();

    pWorld->markForWrite();

 

    hkVector4 pos( x, y, z );

 

    hkpRigidBody* pRigidBody = m_pHavokRigidBody->getRigidBody();

    pRigidBody->setPosition( pos );

 

    pWorld->unmarkForWrite();

    pWorld->unlock();

}

ij¸¯ÅÍ À§Ä¡¸¦ ¼³Á¤ÇÑ´Ù.

 

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