Havok Start

하복을 아래 싸이트로 가서 다운 받는다.
http://software.intel.com/sites/havok/

하복 버전:
Havok_Physics_Animation_2010-2-0_PC_XS_win32_VS2005_keycode_perpetual_20101115.zip

추가 포함 디렉터리: ../hk2010_2_0_r1/Source

추가 라이브러리 디렉터리:
디버그용 - ../hk2010_2_0_r1/Lib/win32_net_8-0/debug_multithreaded_dll
릴리즈용 - ../hk2010_2_0_r1/Lib/win32_net_8-0/release_multithreaded_dll

< 1. 하복 초기화 >

    //하복 메모리 초기화

    hkMallocAllocator baseMalloc; 

    hkMemoryRouter* memoryRouter = hkMemoryInitUtil::initDefault( &baseMalloc, hkMemorySystem::FrameInfo(1024 * 1024) );

    hkBaseSystem::init(memoryRouter, HavokErrorReportFunction);

 

    hkpWorldCinfo info;

    info.m_simulationType = hkpWorldCinfo::SIMULATION_TYPE_CONTINUOUS;

    info.m_collisionTolerance = 0.001f;

    info.setBroadPhaseWorldSize( 10000.0f );

    info.setupSolverInfo( hkpWorldCinfo::SOLVER_TYPE_8ITERS_HARD );

    info.m_gravity = hkVector4(0.0f, -9.8f, 0.0f);

    hkpWorld *world = new hkpWorld(info);

 

    hkpAgentRegisterUtil::registerAllAgents( world->getCollisionDispatcher() );

하복 메모리를 초기화 하고 종료시에서는 quit을 호출해준다.

hkMemoryRouter* memoryRouter = hkMemoryInitUtil::initDefault( &baseMalloc, hkMemorySystem::FrameInfo(1024 * 1024) );

hkBaseSystem::init(memoryRouter, HavokErrorReportFunction);

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

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

hkBaseSystem::quit();

hkMemoryInitUtil::quit();

하복 시뮬레이션 타입을 정한다.
멀티쓰레드 물리 시뮬레이션을 한다면  SIMULATION_TYPE_MULTITHREADED을 사용한다.

info.m_simulationType = hkpWorldCinfo::SIMULATION_TYPE_CONTINUOUS;

충돌 오차를 지정한다.

info.m_collisionTolerance = 0.001f;

충돌 월드 사이즈를 지정한다.

info.setBroadPhaseWorldSize( 10000.0f );

이 옵션은 정확하게 뭐하는건지 모른다. 디폴트 값은 SOLVER_TYPE_4ITERS_MEDIUM이다.

info.setupSolverInfo( hkpWorldCinfo::SOLVER_TYPE_8ITERS_HARD );

중력 방향을 설정한다.

info.m_gravity = hkVector4(0.0f, -9.8f, 0.0f);

< 2. 충돌 바닥 만들기 >

    const  float  groundHalfH = 2.0f;

    const  hkVector4 halfExtents( 2000.0f, groundHalfH, 2000.0f );

    hkpBoxShape* groundShape = new  hkpBoxShape(halfExtents);

 

    hkpRigidBodyCinfo bodyInfo;

    bodyInfo.m_mass = 0.0f;

    bodyInfo.m_shape = groundShape;

    bodyInfo.m_motionType = hkpMotion::MOTION_FIXED;

    bodyInfo.m_position.set(0.0f, -groundHalfH, 0.0f);

 

    hkpRigidBody* groundBody = new  hkpRigidBody(bodyInfo);

    groundShape->removeReference();

 

    world->addEntity(groundBody);

    groundBody->removeReference();

반지름 x = 2000, y = 2, z = 2000 hkBoxShape를 생성한다.

hkpBoxShape* groundShape = new hkpBoxShape(halfExtents)

바닥은 움직이 않는 정적인 물체이므로 질량을 0으로 셋팅한다.
모션 타입을 MOTION_FIXED로 하면 움직이지 않는 게임의 배경과 같은 정적인 타입이다.

bodyInfo.m_mass = 0.0f

hkpRigidBody 생성후 groundShape 정보는 더 이상 필요하지 않으므로 삭제한다.

hkpRigidBody* groundBody = new hkpRigidBody(bodyInfo);

groundShape->removeReference();

하복 월드에 Rigid Body추가후 groundBody정보는 더 이상 필요하지 않으므로 삭제한다.

world->addEntity(groundBody);

groundBody->removeReference();

< 3. 충돌 박스 만들기 >

    const float bx = 1.0f, by = 2.0f, bz = 1.0f;

    const int nx = 2, ny = 2, nz = 2;

    const int NUM_BODIES = nx * ny * nz;

    hkpRigidBody *bodies[NUM_BODIES];

    {

        const hkVector4 halfExtents(bx, by, bz);

        hkpShape* shape = new hkpBoxShape(halfExtents, 0.0f);

 

        hkpMassProperties massProperties;

        hkpInertiaTensorComputer::computeShapeVolumeMassProperties(shape, 5.0f, massProperties);

 

        hkpRigidBodyCinfo bodyInfo;

        bodyInfo.m_mass = massProperties.m_mass;

        bodyInfo.m_centerOfMass = massProperties.m_centerOfMass;

        bodyInfo.m_inertiaTensor = massProperties.m_inertiaTensor;

        bodyInfo.m_shape = shape;

        bodyInfo.m_motionType = hkpMotion::MOTION_BOX_INERTIA;

 

        int i = 0;

        for(int x = 0; x < nx; x++)

        for(int y = 0; y < ny; y++)

        for(int z = 0; z < nz; z++) {

            hkpRigidBody *body = new  hkpRigidBody(bodyInfo);

            body->setPosition(hkVector4(x * bx * 2, 100.0f + y * by * 2, z * bz * 2));

            bodies[i] = body;

            world->addEntity(body);

            body->removeReference();

            i++;

        }

        shape->removeReference();

    }

관성 텐서와 hkpShape의 주어진 총 질량의 중심을 계산한다. 모든 통과하는 자식 셰이프는 볼륨을 가지고 있어야 한다. 삼각형의 최소 두께는 0.01f이다.

        hkpInertiaTensorComputer::computeShapeVolumeMassProperties(shape, 5.0f, massProperties);

 

        hkpRigidBodyCinfo bodyInfo;

        bodyInfo.m_mass = massProperties.m_mass;

        bodyInfo.m_centerOfMass = massProperties.m_centerOfMass;

        bodyInfo.m_inertiaTensor = massProperties.m_inertiaTensor;

박스의 움직임이므로 MOTION_BOX_INERTIA로 설정한다.

bodyInfo.m_motionType = hkpMotion::MOTION_BOX_INERTIA

hkpRigidBody()을 생성후 setPosition()으로 이동한다.

hkpRigidBody *body = new hkpRigidBody(bodyInfo)

body->setPosition(hkVector4(x * bx * 2, 100.0f + y * by * 2, z * bz * 2))

< 4. 하복 루프 >

하복 시뮬레이션 간격을 60프레임으로 설정한다.

world->stepDeltaTime(1.0f/60.0f)

카메라는 첫 번째 박스를 따라서 움직입니다.
첫 번째 hkpRigidBody인 bodies[0]로부터 Transform으로 위치를 구해서 카메라 뷰를 설정한다.

hkVector4 pos = bodies[0]->getPosition();

{

    const hkTransform &trans = bodies[0]->getTransform();

    const hkVector4 &t = trans.getTranslation();

    D3DXMatrixLookAtLH(&view, &D3DXVECTOR3(0.0f, 50.0f, -25.0f),

        &D3DXVECTOR3(t(0), t(1), t(2)), &D3DXVECTOR3(0.0f, 1.0f, 0.0f));

    g_pD3DDev->SetTransform(D3DTS_VIEW, &view);

}

바닥이나 박스를 그릴때, 오른손 좌표계에서 왼손 좌표계로 행렬 변환을 한다.

                D3DXMATRIX transMat(

                    t(0,0), t(1,0), t(2,0), 0.0f,

                    t(0,1), t(1,1), t(2,1), 0.0f,

                    t(0,2), t(1,2), t(2,2), 0.0f,

                    t(0,3), t(1,3), t(2,3), 1.0f);

< 5. 하복 종료 >

    delete world;

    hkBaseSystem::quit();

    hkMemoryInitUtil::quit();

이상 참고 싸이트의 소스를 가져와서 새로운 하복버전에서 빌드 되도록 수정하고 소스를 분석 하였다.

프로젝트: havok_start.zip

참고 싸이트:
http://marupeke296.com/COL_HVK_No2_Integration.html