转: 在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;
}
转: 在Ogre中使用Havok物理引擎(源码)的更多相关文章
- ROS_Kinetic_07 ROS中机器人三维物理引擎高保真仿真利器gazebo 7.0
ROS_Kinetic_07 ROS中机器人三维物理引擎高保真仿真利器gazebo 7.0 ROS kinetic中的gazebo版本是7.0,有很多新的特性. 首先,启动gazebo: ~$ gaz ...
- Fabric2.2中的Raft共识模块源码分析
引言 Hyperledger Fabric是当前比较流行的一种联盟链系统,它隶属于Linux基金会在2015年创建的超级账本项目且是这个项目最重要的一个子项目.目前,与Hyperledger的另外几个 ...
- eclipse中tomcat调试正确关联源码
1.build path中jar包关联本地源码 2.tomcat中添加source关联工程lib下的jar包 以上两步即可. 可解决tomcat直接关联本地源码debug时无法计算表达式的情况. 错误 ...
- 动态语言切换(续)-designer中的retranslateUi(带源码)
本站所有文章由本站和原作者保留一切权力,仅在保留本版权信息.原文链接.原文作者的情况下允许转载,转载请勿删改原文内容, 并不得用于商业用途. 谢谢合作.原文链接:动态语言切换(续)-designer中 ...
- RocketMQ中Broker的HA策略源码分析
Broker的HA策略分为两部分①同步元数据②同步消息数据 同步元数据 在Slave启动时,会启动一个定时任务用来从master同步元数据 if (role == BrokerRole.SLAVE) ...
- Chrome V8 引擎源码剖析
Chrome V8 引擎源码剖析 V8 https://github.com/v8/v8 array & sort https://github.com/v8/v8/search?l=Java ...
- cocos2d-x中的Box2D物理引擎
在Cocos2d-x中集成了2个物理引擎,一个是Chipmunk,一个是Box2D.前者是用C语言编写的,文档和例子相对较少:Box2D是用C++写的,并且有比较完善的文档和资料.所以在需要使用物理引 ...
- Egret中使用P2物理引擎
游戏中的对象按照物理规律移动,体现重力.引力.反作用力.加速度等物体特性,实现自由落体.摇摆运动.抛物线运动,以及物理碰撞现象的模拟.用于模拟物理碰撞.物理运动的引擎称为物理引擎. 来自瑞典斯德哥尔摩 ...
- Handlebars模板引擎中的each嵌套及源码浅读
若显示效果不佳,可移步到愚安的小窝 Handlebars模板引擎作为时下最流行的模板引擎之一,已然在开发中为我们提供了无数便利.作为一款无语义的模板引擎,Handlebars只提供极少的helper函 ...
随机推荐
- bat 批处理切换到当前脚本所在文件夹
bat 批处理切换到当前脚本所在文件夹 切换到当前脚本所在的文件夹 ? 1 cd %~dp0 另外附上一些bat基本内容 —————————————————————————————— 批处理常用 ...
- 【Javascript设计模式1】-单例模式
<parctical common lisp>的作者曾说,如果你需要一种模式,那一定是哪里出了问题.他所说的问题是指因为语言的天生缺陷,不得不去寻求和总结一种通用的解决方案. 不管是弱类型 ...
- 八一八android开发规范(一种建议)
开发规范重不重要了,不言而喻.这里就给大家说一故事把——据<圣经·旧约·创世记>第11章记载,是当时人类联合起来兴建,希望能通往天堂的高塔.为了阻止人类的计划,上帝让人类说不同的语言,使人 ...
- Anciroid的IPC机制-Binder原理
Binder驱动的原理和实现 通过上一节的介绍,大家应该对Binder有了基本的认识了.任何上层应用程序接口和用户操作都需要底层硬件设备驱动的支持,并为其提供各种操作接口.本节首先从Binder的驱动 ...
- python中read() readline()以及readlines()用法
[转自:http://www.ibm.com/developerworks/cn/linux/sdk/python/python-5/index.html#N1004E] 我们谈到“文本处理”时,我们 ...
- Eclipse使用hibernate插件
首先安装好hibernate插件,进入安装界面,输入下载地址http://download.jboss.org/jbosside/updates/stable,点击下载javaee web 以下的hi ...
- 编程实战——电影管理器之XML存储电影信息数据
但凡管理器之类的软件,存储数据是必不可少的.存储数据的话,有几种选择.一是用数据库,把数据存储到数据库里:一是用文本文件,把数据存储到文本文件里:一种是利用XML文件,把数据对象转换为XML后,存储到 ...
- ivr
/************************************************************* 北京高阳圣思园信息技术有限公司IVR业务: 流程说明:公司介绍子流程 发布 ...
- Mybatis源码分析之Cache二级缓存原理 (五)
一:Cache类的介绍 讲解缓存之前我们需要先了解一下Cache接口以及实现MyBatis定义了一个org.apache.ibatis.cache.Cache接口作为其Cache提供者的SPI(Ser ...
- Github 基本操作
.配置Git 首先在本地创建ssh key:$ ssh-keygen -t rsa -C "your_email@youremail.com" 后面的your_email@your ...