转: 在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=NULL;

loadedData = 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 = static_cast<hkpPhysicsData*>( 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;

}

时间: 2024-10-08 20:04:59

转: 在Ogre中使用Havok物理引擎(源码)的相关文章

如何学习大型项目的源码?虚幻引擎源码学习思路分享

每一个人做事都有自己的风格与习惯.当你发现身边一个人很优秀的时候,你去看一下他的24小时是怎么度过的,然后再对比一下你的24小时,答案就很明了了.同理,如果你觉得学习源码很困难,不妨请教一下那些比较牛的"过来人",看一下别人学习源码模块的流程.当然具体来说,影响一个事物的纬度,细节,前提条件都很多,别人的方法照搬过来可能是行不通的,比如说别人能一天雷打不动地学10个小时,这个放到有些人身上几乎不可能.那如何学习大型项目的源码?下面我把自己学习虚幻引擎源码(C++)的思路和过程给分享给大

Android中AsyncTask基本用法与源码分析(API 23)

原文链接 http://sparkyuan.github.io/2016/03/23/AsyncTask源码剖析(API 23)/ 转载请注明出处 Android的UI是线程不安全的,想在子线程中更新UI就必须使用Android的异步操作机制,直接在主线程中更新UI会导致程序崩溃. Android的异步操作主要有两种,AsyncTask和Handler.AsyncTask是一个轻量的异步类,简单.可控.本文主要结合API 23的源码讲解一下AsyncTask到底是什么. 基本用法 声明:Andr

【141029】VC游戏编写中的求解最短路径算法源码

VC游戏编写中的求解最短路径算法源码,本示例是自动寻径演示,篮点是起点,红点是终点,按确定键开始.源码爱好者注:编译后运行的时候请把EXE文件从Debug目录中拷贝到项目根目录中,若不然会出错. 编著.程序设计:唐明理 程序顺序: 初始化队列.待处理节点入队列, 依靠对目的地估价距离插入排序,将离目的地估计最近的方案出队列,释放栈顶节点,释放申请过的所有节点,估价函数,估价 x,y 到目的地的距离,估计值必须保证比实际值小, 尝试下一步移动到 x,y 可行否,如果曾经有更好的方案移动到 (x,y

caffe中HingeLossLayer层原理以及源码分析

输入: bottom[0]: NxKx1x1维,N为样本个数,K为类别数.是预测值. bottom[1]: Nx1x1x1维, N为样本个数,类别为K时,每个元素的取值范围为[0,1,2,-,K-1].是groundTruth. 输出: top[0]: 1x1x1x1维, 求得是hingeLoss. 关于HingeLoss: p: 范数,默认是L1范数,可以在配置中设置为L1或者L2范数. :指示函数,如果第n个样本的真实label为k,则为,否则为-1. tnk: bottom[0]中第n个样

Android 中View的绘制机制源码分析 三

到目前为止,measure过程已经讲解完了,今天开始我们就来学习layout过程,不过在学习layout过程之前,大家有没有发现我换了编辑器,哈哈,终于下定决心从Html编辑器切换为markdown编辑器,这里之所以使用"下定决心"这个词,是因为毕竟Html编辑器使用好几年了,很多习惯都已经养成了,要改变多年的习惯确实不易,相信这也是还有很多人坚持使用Html编辑器的原因.这也反应了一个现象,当人对某一事物非常熟悉时,一旦出现了新的事物想取代老的事物时,人们都有一种抵触的情绪,做技术的

美!视差滚动在图片滑块中的应用【附源码下载】

视差滚动(Parallax Scrolling)已经被广泛应用于网页设计中,这种技术能够让原本平面的网页界面产生动感的立体效果.下面分享的这个图片滑块效果是难得一见的结合视差滚动的例子,之前的文章给大家分享过,这里再推荐一下.美女很养眼吧 :) 温馨提示:为保证最佳的效果,请在 IE10+.Chrome.Firefox 和 Safari 等现代浏览器中浏览. 您可能感兴趣的相关文章 太赞了!超炫的页面切换动画效果[附源码下载] 创意无限!一组网页边栏过渡动画[附源码下载] 好东西!动感的页面加载

OpenSSL 中 RSA 加密解密实现源码分析

1.RSA 公钥和私钥的组成,以及加密和解密的公式: 2.模指数运算: 先做指数运算,再做模运算,如 5^3 mod 7 = 125 mod 7 = 6 3.RSA加密算法流程: 选择一对不同的.并且足够大的素数 p 和 q 计算 n = p * q 计算欧拉函数 f(n) = (p-1) * (q-1),p 和 q 需要保密 寻找与 f(n) 互质的数 e,并且 1 < e < f(n) 计算 d,使得 d * e ≡ 1 mod f(n) 公钥 KU = (e , n)   私钥 KR =

Android 中View的绘制机制源码分析 二

尊重原创:http://blog.csdn.net/yuanzeyao/article/details/46842891 本篇文章接着上篇文章的内容来继续讨论View的绘制机制,上篇文章中我们主要讲解了View的measure过程,今天我们就来学习ViewGroup的measure过程,由于ViewGroup只是一个抽象类,所以我们需要以一个具体的布局来分析measure过程,正如我上篇文章说的,我打算使用LinearLayout为例讲解measure过程,如果你还没有读过上篇文章,那么建议你先

Scala深入浅出实战经典《第83讲:Scala中List的实现内幕源码揭秘》笔记

终于从暑假回到正常的日子了~虽然开始学习<scala深入浅出实战经典>这门课程有些晚了,但是不管如何既然开始了,坚持下去才是重点.下面言归正传. 第83讲:Scala中List的实现内幕源码揭秘 Goal:List实现关键源码分析 Gains: 1)List中的诸多方法其实还是采用ListBuffer来实现的,而后ListBuffer利用toList返回不可变的List. 2)采用ListBuffer,效率较高:而toList方法返回List,也只是耗常量时间,并不会很大程度地影响性能. Q: