zoukankan      html  css  js  c++  java
  • 转: 在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: "<<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;

    }

  • 相关阅读:
    .net序列化和反序列化(一)——自动序列化
    在Sql Server 2005使用公用表表达式CTE简化复杂的查询语句
    使用JQuery与iframe交互
    FCKeditor自定义工具栏和定义多个工具栏
    FCKeditor自定义非空验证
    PHP5.3.6的IIS配置
    Linux下缓存服务器的应用
    PHP采集程序中常用的函数
    关于PHP5.3.x和Zend Optimizer(Zend Guard Loader),以及shopex4.8.5安装的问题
    SQLserver数据库还原出现错误112(磁盘空间不足)的解决办法
  • 原文地址:https://www.cnblogs.com/skyofbitbit/p/4083080.html
Copyright © 2011-2022 走看看