首页 > 代码库 > 转: 在Ogre中使用Havok物理引擎(源码)

转: 在Ogre中使用Havok物理引擎(源码)

作者:CYM

众所周知Ogre则是评价很高的一款图形渲染引擎,Havok则是世界一流的物理引擎,今天花了点时间将两者结合在了一块,做了个Demo

由于国内对Havok的研究似乎很少,网上也找不到多少资料,所以先分享一下源码..

演示了很多棍子掉落在地上的场景

 




--------------------------------------------华丽分割线---------------------------------------------------------------

灰色部分为暂时无用代码

 

//-----------------------------------------------------------------------------

//类名: CCYMBasePhysical 物理类(独立类)

//描述: 用于处理物理的计算

//文件:CYMBasePhysical.h

//作者: CYM

//-----------------------------------------------------------------------------

 

#pragma once

#include <initguid.h>

#include <stdio.h>

#include <Windows.h>

//包涵Havok相关的头文件

// 数学库和基本库

#include <Common/Base/hkBase.h>

#include <Common/Base/System/hkBaseSystem.h>

#include <Common/Base/System/Error/hkDefaultError.h>

#include <Common/Base/Memory/System/Util/hkMemoryInitUtil.h>

#include <Common/Base/Monitor/hkMonitorStream.h>

#include <Common/Base/Memory/System/hkMemorySystem.h>

#include <Common/Base/Memory/Allocator/Malloc/hkMallocAllocator.h>

#include <Common/Base/Types/Geometry/hkStridedVertices.h>

 

// 序列化

#include <Common/Serialize/Util/hkSerializeUtil.h>

#include <Physics/Utilities/Serialize/hkpPhysicsData.h>

#include <Common/SceneData/Scene/hkxScene.h>

#include <Common/SceneData/Mesh/hkxMesh.h>

#include <Common/SceneData/Scene/hkxSceneUtils.h>

#include <Common/Serialize/Util/hkLoader.h>

#include <Common/Serialize/Util/hkRootLevelContainer.h>

#include <Common/Serialize/Util/hkBuiltinTypeRegistry.h>

 

// 形状

#include <Physics/Collide/Shape/Compound/Collection/CompressedMesh/hkpCompressedMeshShape.h>

#include <Physics/Collide/Shape/Compound/Collection/ExtendedMeshShape/hkpExtendedMeshShape.h>

#include <Physics/Collide/Shape/Compound/Collection/StorageExtendedMesh/hkpStorageExtendedMeshShape.h>

#include <Physics/Collide/Shape/Compound/Collection/List/hkpListShape.h>

#include <Physics/Collide/Shape/Convex/Box/hkpBoxShape.h>

#include <Physics/Collide/Shape/Convex/Sphere/hkpSphereShape.h>

#include <Physics/Collide/Shape/Compound/Tree/Mopp/hkpMoppBvTreeShape.h>

#include <Physics/Collide/Shape/Convex/ConvexTranslate/hkpConvexTranslateShape.h>

#include <Physics/Collide/Shape/HeightField/CompressedSampledHeightField/hkpCompressedSampledHeightFieldShape.h>

#include <Physics/Collide/Shape/HeightField/TriSampledHeightField/hkpTriSampledHeightFieldCollection.h>

#include <Physics/Collide/Shape/HeightField/TriSampledHeightField/hkpTriSampledHeightFieldBvTreeShape.h>

 

// 动力学库

#include <Physics/Collide/hkpCollide.h>

#include <Physics/Collide/Agent/ConvexAgent/SphereBox/hkpSphereBoxAgent.h>

//#include <Physics/Collide/Shape/Convex/Box/hkpBoxShape.h>

//#include <Physics/Collide/Shape/Convex/Sphere/hkpSphereShape.h>

#include <Physics/Collide/Shape/Convex/ConvexVertices/hkpConvexVerticesShape.h>

#include <Physics/Collide/Dispatch/hkpAgentRegisterUtil.h>

#include <Physics/Collide/Query/CastUtil/hkpWorldRayCastInput.h>

#include <Physics/Collide/Query/CastUtil/hkpWorldRayCastOutput.h>

#include <Physics/Dynamics/World/hkpWorld.h>

#include <Physics/Dynamics/Entity/hkpRigidBody.h>

#include <Physics/Utilities/Dynamics/Inertia/hkpInertiaTensorComputer.h>

#include <Common/Base/Thread/Job/ThreadPool/Cpu/hkCpuJobThreadPool.h>

#include <Common/Base/Thread/Job/ThreadPool/Spu/hkSpuJobThreadPool.h>

#include <Common/Base/Thread/JobQueue/hkJobQueue.h>

 

// Keycode

#include <Common/Base/keycode.cxx>

#define HK_FEATURE_REFLECTION_PHYSICS

#define HK_CLASSES_FILE <Common/Serialize/Classlist/hkClasses.h>

#define HK_EXCLUDE_FEATURE_MemoryTracker

#define HK_EXCLUDE_FEATURE_SerializeDeprecatedPre700

#define HK_EXCLUDE_FEATURE_RegisterVersionPatches 

#define HK_EXCLUDE_LIBRARY_hkGeometryUtilities

#include <Common/Base/Config/hkProductFeatures.cxx>

 

class CPhysical

{

public:

CPhysical(void);

~CPhysical(void);

 

//初始化Havok物理引擎相关和物理世界

bool InitPhyscal(hkpWorldCinfo* hkWorldInfo);

//增加一个刚体

//bool AddRigidBody(hkpRigidBodyCinfo* hkRigidInfo,hkpRigidBody* hkRigidBody);

//向物理世界增加一个实体

bool AddEntity(hkpRigidBody* hkRigidBody);

//根据网格建立形状

//hkpShape* BiuldShapeFromXMesh(ID3DXMesh* pMesh);

//根据HKT网格文件建立形状

//const hkpShape* BiuldShapeFromHKT( const char* filename );

//更新物理世界

void UpdatePhysical(hkReal hkDeltaTime);

 

//向物理世界写入数据

bool MarkForWrite(void);

bool UnMarkForWrite(void);

//从物理世界读取数据

bool MarkForRead(void);

bool UnMarkForRead(void);

 

//获得物理世界

hkpWorld* GetPhysicalworld(void);

 

protected:

hkArray<hkUint32> m_collisionFilterInfos;

//错误信息打印函数

//static void HK_CALL errorReport(const char* msg, void* userArgGivenToInit);

 

//Havok相关的定义

hkMemoryRouter* m_hkMemoryRouter;//内存路由器

hkJobThreadPool* m_hkThreadPool;//线程池

hkJobQueue* m_hkJobQueue;//工作队列

hkpWorld* m_hkPhysicsWorld;//物理世界

};

 

//-----------------------------------------------------------------------------

//类名: CCYMBasePhysical 物理类(独立类)

//描述: 用于处理物理的计算

//文件:CYMBasePhysical.cpp

//作者: CYM

//-----------------------------------------------------------------------------

#include "Physical.h"

 

CPhysical::CPhysical(void)

{

m_hkMemoryRouter=NULL;//内存路由器

m_hkThreadPool=NULL;//线程池

m_hkJobQueue=NULL;//工作队列

m_hkPhysicsWorld=NULL;//物理世界

}

 

 

CPhysical::~CPhysical(void)

{

//移除物理世界

m_hkPhysicsWorld->markForWrite();

m_hkPhysicsWorld->removeReference();

 

//清除工作队列和线程池

delete m_hkJobQueue;

m_hkThreadPool->removeReference();

 

//退出Havok内存系统

hkBaseSystem::quit();

    hkMemoryInitUtil::quit();

}

 

static void HK_CALL errorReport(const char* msg, void* userArgGivenToInit)

{

printf("%s", msg);

}

 

//初始化Havok物理引擎相关和物理世界

bool CPhysical::InitPhyscal(hkpWorldCinfo* hkWorldInfo)

{

//

// 初始化基本的系统和我们的内存系统

//

// 分配0.5MB的物理解决缓存

 

m_hkMemoryRouter = hkMemoryInitUtil::initDefault( hkMallocAllocator::m_defaultMallocAllocator, hkMemorySystem::FrameInfo( 500* 1024 ) );

hkBaseSystem::init(m_hkMemoryRouter,errorReport );

 

//

// 初始化多线程类, hkJobQueue, 和 hkJobThreadPool

//

int totalNumThreadsUsed;

hkHardwareInfo hwInfo;

hkGetHardwareInfo(hwInfo);

totalNumThreadsUsed = hwInfo.m_numThreads;

// We use one less than this for our thread pool, because we must also use this thread for our simulation

hkCpuJobThreadPoolCinfo threadPoolCinfo;

threadPoolCinfo.m_numThreads = totalNumThreadsUsed - 1;

//创建线程池

threadPoolCinfo.m_timerBufferPerThreadAllocation = 200000;

m_hkThreadPool = new hkCpuJobThreadPool( threadPoolCinfo );

//创建工作队列

hkJobQueueCinfo info;

info.m_jobQueueHwSetup.m_numCpuThreads = totalNumThreadsUsed;

m_hkJobQueue= new hkJobQueue(info);

//为这个线程池激活

hkMonitorStream::getInstance().resize(200000);

 

//

//创建物理世界

//

m_hkPhysicsWorld = new hkpWorld(*hkWorldInfo);

 

//向物理世界写入数据

m_hkPhysicsWorld->markForWrite();

//设置去活化

m_hkPhysicsWorld->m_wantDeactivation = true;

 

//注册碰撞代理

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

//注册工作队列

m_hkPhysicsWorld->registerWithJobQueue(m_hkJobQueue );

 

//终止向物理世界写入数据

m_hkPhysicsWorld->unmarkForWrite();

 

return true;

 

}

 

/*//增加一个刚体

bool CPhysical::AddRigidBody(hkpRigidBodyCinfo* hkRigidInfo,hkpRigidBody* hkRigidBody)

{

//向物理世界写入数据

//m_hkPhysicsWorld->markForWrite();

//创建刚体

hkRigidBody=new hkpRigidBody(*hkRigidInfo);

m_hkPhysicsWorld->addEntity(hkRigidBody);

//hkRigidBody->removeReference();//移除引用

 

//停止向物理世界写入数据

//m_hkPhysicsWorld->unmarkForWrite();

 

return true;

}*/

 

//向物理世界增加一个实体

bool CPhysical::AddEntity(hkpRigidBody* hkRigidBody)

{

m_hkPhysicsWorld->addEntity(hkRigidBody);

 

return true;

}

 

/*//根据网格建立形状

hkpShape* CPhysical::BiuldShapeFromXMesh(ID3DXMesh* pMesh)

{

//获取网格的顶点缓存

LPDIRECT3DVERTEXBUFFER9 lpBuffer=NULL;

pMesh->GetVertexBuffer(&lpBuffer);

//获取网格的索引缓存

LPDIRECT3DINDEXBUFFER9 lpIndexBuffer=NULL;

pMesh->GetIndexBuffer(&lpIndexBuffer);

 

//havok用于构造凸面体形状的顶点数组

float* hkVertex=NULL;

hkVertex=new float[pMesh->GetNumVertices()*4];

//获取网格的顶点

CYMFVFVertex1* pVertex=NULL;

lpBuffer->Lock(0,0,(void**)&pVertex,0);

//循环获取网格的每个顶点

for(int i=0,j=0;i<pMesh->GetNumVertices();i++)

{

hkVertex[j]=pVertex[i]._x;

hkVertex[j+1]=pVertex[i]._y;

hkVertex[j+2]=pVertex[i]._z;

hkVertex[j+3]=0.0f;

j+=4;

}

lpBuffer->Unlock();

 

//获取网格的索引值

DWORD* hkIndex=NULL;

hkIndex=new DWORD[pMesh->GetNumFaces()*6];

//获取索引值

DWORD* pIndex=NULL;

lpIndexBuffer->Lock(0,0,(void**)&pIndex,0);

//循环获取索引值

for(int i=0;i<pMesh->GetNumFaces()*6;i++)

{

hkIndex[i]=pIndex[i];

}

lpIndexBuffer->Unlock();

 

//根据获取的顶点信息构造一个形状

hkpExtendedMeshShape* extendedMeshShape = new hkpExtendedMeshShape();

{

hkpExtendedMeshShape::TrianglesSubpart part;

part.m_numTriangleShapes= pMesh->GetNumFaces();

part.m_numVertices= pMesh->GetNumVertices();

part.m_vertexBase= hkVertex;

part.m_stridingType= hkpExtendedMeshShape::INDICES_INT16;

part.m_vertexStriding= sizeof(hkReal) * 4;

part.m_indexBase= hkIndex;

part.m_indexStriding= sizeof( hkUint16 ) * 6;

 

extendedMeshShape->addTrianglesSubpart(part);

}

 

//int numTriangles = extendedMeshShape->getNumChildShapes();

//numTriangles ++;

 

//return extendedMeshShape;

 

hkStridedVertices* hkStrided=new hkStridedVertices(&hkVertex[0],pMesh->GetNumVertices());

hkpConvexShape* shape=new hkpConvexVerticesShape(*hkStrided);

return extendedMeshShape;

}*/

 

/*//根据HKT网格文件建立形状

const hkpShape* CPhysical::BiuldShapeFromHKT( const char* filename )

{

//载入文件

hkSerializeUtil::ErrorDetails loadError;

hkResource* loadedData=http://www.mamicode.com/NULL;

loadedData = http://www.mamicode.com/hkSerializeUtil::load( filename, &loadError );

 

//HK_ASSERT2(0xa6451543, loadedData != HK_NULL, "Could not load file. The error is:\n"<<loadError.defaultMessage.cString() );

::MessageBox(NULL,loadError.defaultMessage.cString(),"错误",NULL);

// Get the top level object in the file, which we know is a hkRootLevelContainer

hkRootLevelContainer* container = loadedData->getContents<hkRootLevelContainer>();

HK_ASSERT2(0xa6451543, container != HK_NULL, "Could not load root level obejct" );

 

// Get the physics data

hkpPhysicsData* physicsData = http://www.mamicode.com/static_cast( container->findObjectByType( hkpPhysicsDataClass.getName() ) );

HK_ASSERT2(0xa6451544, physicsData != HK_NULL, "Could not find physics data in root level object" );

 

HK_ASSERT2( 0x231a7ac2, physicsData->getPhysicsSystems().getSize() > 0, "There are no physics systems in the asset." );

hkpPhysicsSystem* system0 = physicsData->getPhysicsSystems()[0];

 

HK_ASSERT2( 0xb377381b, system0->getRigidBodies().getSize() > 0, "There are no rigid bodies in the first physics system." );

hkpRigidBody* system0body0 = system0->getRigidBodies()[0];

 

const hkpShape* shape = system0body0->getCollidableRw()->getShape();

HK_ASSERT2( 0xb377381c, shape, "There first rigid body in the first physics system has no shape." );

 

//m_externalData.pushBack( loadedData );

 

const hkpShape* ems = shape;

if ( ems->getType() == HK_SHAPE_MOPP )

{

ems = static_cast<const hkpMoppBvTreeShape*>( ems )->getChild();

}

 

HK_ASSERT( 0x4f78a915, ems->getType() == HK_SHAPE_EXTENDED_MESH );

 

// If there is a material table in the landscape, we overwrite it with the collision

// filter infos in this utility so it works with the demo.

if ( m_collisionFilterInfos.getSize() )

{

const hkpExtendedMeshShape* extendedMeshShape = static_cast<const hkpExtendedMeshShape*>( ems );

 

for ( int i = 0; i < extendedMeshShape->getNumTrianglesSubparts(); ++i )

{

const hkpExtendedMeshShape::Subpart& subPart = extendedMeshShape->getTrianglesSubpartAt( i );

if ( subPart.m_materialBase && subPart.m_materialStriding )

{

for ( int j = 0; j < subPart.m_numMaterials; ++j )

{

( const_cast<hkpMeshMaterial*>(hkAddByteOffsetConst( subPart.m_materialBase, j * subPart.m_materialStriding )))->m_filterInfo = m_collisionFilterInfos[ ( i + j ) % m_collisionFilterInfos.getSize() ];

}

}

}

for ( int i = 0; i < extendedMeshShape->getNumShapesSubparts(); ++i )

{

const hkpExtendedMeshShape::Subpart& subPart = extendedMeshShape->getShapesSubpartAt( i );

if ( subPart.m_materialBase && subPart.m_materialStriding )

{

for ( int j = 0; j < subPart.m_numMaterials; ++j )

{

( const_cast<hkpMeshMaterial*>(hkAddByteOffsetConst( subPart.m_materialBase, j * subPart.m_materialStriding )))->m_filterInfo = m_collisionFilterInfos[ i + j % m_collisionFilterInfos.getSize() ];

}

}

}

}

 

return shape;

}*/

 

//更新物理世界

void CPhysical::UpdatePhysical(hkReal hkDeltaTime)

{

//使用多线程进行一次模拟

m_hkPhysicsWorld->stepMultithreaded(m_hkJobQueue, m_hkThreadPool,hkDeltaTime);

hkMonitorStream::getInstance().reset();

m_hkThreadPool->clearTimerData();

}

 

//向物理世界写入数据

bool CPhysical::MarkForWrite(void)

{

m_hkPhysicsWorld->markForWrite();

 

return true;

}

 

bool CPhysical::UnMarkForWrite(void)

{

m_hkPhysicsWorld->unmarkForWrite();

 

return true;

}

 

//从物理世界读取数据

bool CPhysical::MarkForRead(void)

{

m_hkPhysicsWorld->markForRead();

 

return true;

}

 

bool CPhysical::UnMarkForRead(void)

{

m_hkPhysicsWorld->unmarkForRead();

 

return true;

}

 

//获取物理世界

hkpWorld* CPhysical::GetPhysicalworld(void)

{

return m_hkPhysicsWorld;

}

 

转: 在Ogre中使用Havok物理引擎(源码)