作者:CYM
摸索了半天终于完成了这个简单的Havok程序,她使用directX渲染.转载请说明出处,尊他人重劳动成果.
和DirectX一样,在使用Havok物理引擎库之前要先要配置好环境,我用的是Visual Studio2010.
第一步:首先要修改工程配置的 公共语言运行时库 ,默认情况下VS的这个选项是 公共语言运行时库支持(旧语法),在这里我们要把它改为
无公共语言支持.如图
:
第二部:也是修改公共语言支持的选项,只是改的位置不同,这回要在C++常规属性上修改,如下图
第三部:接下来就是设置包涵文件和库文件路径了:在这里设置程序需要的包涵文件和库文件,如下图
第四部:s设置Havok的预处理器选项:选择工程属性->C++->预处理器->预处理器定义
将以下内容加进去
WIN32
NDEBUG
_WINDOWS
_WIN32
_DEBUG
HK_DEBUG
_CONSOLE
HK_CONFIG_SIMD=2
如图
第五步:z在工程属性->连接器->输入 中的 附加依赖选项 加入以下内容:
d3d9.lib
d3dx9.lib
hkBase.lib
hkCompat.lib
hkSceneData.lib
hkSerialize.lib
hkInternal.lib
hkGeometryUtilities.lib
hkVisualize.lib
hkcdInternal.lib
hkcdCollide.lib
hkpCollide.lib
hkpConstraintSolver.lib
hkpDynamics.lib
hkpInternal.lib
hkpUtilities.lib
hkpVehicle.lib
如图;
这样配好后程序就可以保证运行了:但是还会出现一个 库文件冲突的提示,很多时候这对程序并无大碍,但是也有几个别时候会使程序崩溃,要解决这个问题只要在 工程属性->连接器->输入 中的 忽略特定默认库选项中添加 libcmtd.lib 就可以了
-------------------------以下是代码部分,已经做了详细的注解,想了解更多关于Havok可以查看我以前写的教程----------------------------------
点击以下链接地址(源码)
http://hi.baidu.com/ae8506/blog/item/ed2147ca70ceaf04bf09e6f4.html
作者:CYM
关于Havok环境配置部分教程可以点击以下链接地址
http://hi.baidu.com/ae8506/blog/item/7529e9633bb3b8c6e6113aea.html?timeStamp=1315916689964
一个模拟炮弹轨迹打出去的小球,以下是代码
---------------------------------------------------华丽分割线------------------------------------------------
//包涵directX相关的头文件
#include
#include
#define WINDOW_CLASS "UGPDX"
#define WINDOW_NAME "Blank D3D Window"
//包涵Havok相关的头文件
// 数学库和基本库
#include
#include
#include
#include
#include
#include
#include
// 动力学库
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// Keycode
#include
#define HK_FEATURE_REFLECTION_PHYSICS
#define HK_CLASSES_FILE
#define HK_EXCLUDE_FEATURE_MemoryTracker
#define HK_EXCLUDE_FEATURE_SerializeDeprecatedPre700
#define HK_EXCLUDE_FEATURE_RegisterVersionPatches
#define HK_EXCLUDE_LIBRARY_hkGeometryUtilities
#include
#include
// 函数原型
bool InitializeD3D(HWND hWnd, bool fullscreen);
void RenderScene();
void Shutdown();
//关于Havok的函数原型
bool InitializeHavok(void);
void UpdateHavok(void);
void ShutdownHavok(void);
//错误信息打印函数
static void HK_CALL errorReport(const char* msg, void* userArgGivenToInit)
{
printf("%s", msg);
}
// D3D对象和D3D设备对象
LPDIRECT3D9 g_D3D = NULL;
LPDIRECT3DDEVICE9 g_D3DDevice = NULL;
//D3D全局灯光和材质
D3DLIGHT9g_d3dLight;
D3DMATERIAL9g_d3dMaterial;
//D3D网格对象
ID3DXMesh*g_d3dBall=NULL;//球体网格
ID3DXMesh*g_d3dGround=NULL;//陆地网格
//D3D图形变化矩阵
D3DXMATRIXg_d3dMatBall;//球体网格的变化矩阵
D3DXMATRIXg_d3dMatGround;//陆地网格的变化矩阵
//Havok相关的定义
hkMemoryRouter* g_hkMemoryRouter;//内存路由器
hkJobThreadPool* g_hkThreadPool=NULL;//线程池
hkJobQueue* g_hkJobQueue=NULL;//工作队列
hkpRigidBody* g_hkBall=NULL;//物理球体
hkpRigidBody* g_hkGround=NULL;//物理陆地
hkpWorld* g_hkPhysicsWorld=NULL;//物理世界
hkStopwatch g_hkStopWatch;
LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
break;
case WM_KEYUP:
if(wParam == VK_ESCAPE) PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE prevhInst, LPSTR cmdLine, int show)
{
// 注册应用程序窗口类
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
WINDOW_CLASS, NULL };
RegisterClassEx(&wc);
// 创建应用程序
HWND hWnd = CreateWindow(WINDOW_CLASS, WINDOW_NAME, WS_OVERLAPPEDWINDOW,
100, 100, 640, 480, GetDesktopWindow(), NULL,
wc.hInstance, NULL);
//初始化D3D
if(InitializeD3D(hWnd, false)&&InitializeHavok())
{
// 显示窗口
ShowWindow(hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd);
// 进入消息循环
MSG msg;
ZeroMemory(&msg, sizeof(msg));
while(msg.message != WM_QUIT)
{
if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
UpdateHavok();
RenderScene();
}
}
// 释放所有资源
ShutdownHavok();
Shutdown();
// 注销应程序窗口
UnregisterClass(WINDOW_CLASS, wc.hInstance);
return 0;
}
bool InitializeD3D(HWND hWnd, bool fullscreen)
{
D3DDISPLAYMODE displayMode;
// 创建D3D对象
g_D3D = Direct3DCreate9(D3D_SDK_VERSION);
if(g_D3D == NULL) return false;
// 获取桌面显示模式
if(FAILED(g_D3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &displayMode)))
return false;
// 填充用于创建D3D设备对象的结构体
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
if(fullscreen)
{
d3dpp.Windowed = FALSE;
d3dpp.BackBufferWidth = 640;
d3dpp.BackBufferHeight = 480;
}
else
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = displayMode.Format;
// 创建D3D设备对象
if(FAILED(g_D3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_D3DDevice)))
{
return false;
}
//初始化D3D灯光和材质
::ZeroMemory(&g_d3dLight, sizeof(D3DLIGHT9));
g_d3dLight.Type = D3DLIGHT_DIRECTIONAL;
g_d3dLight.Ambient = D3DXCOLOR(0.8f, 0.8f, 0.8f, 1.0f);
g_d3dLight.Diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
g_d3dLight.Specular = D3DXCOLOR(0.2f, 0.2f, 0.2f, 1.0f);
g_d3dLight.Direction = D3DXVECTOR3(1.0f, -1.0f, 0.0f);
g_D3DDevice->SetLight(0, &g_d3dLight);//设置灯光
g_D3DDevice->LightEnable(0, true);//激活灯光
//初始化全局材质
::ZeroMemory(&g_d3dMaterial,sizeof(D3DMATERIAL9));
g_d3dMaterial.Diffuse.r = 0.4f;
g_d3dMaterial.Diffuse.g =0.4f;
g_d3dMaterial.Diffuse.b = 0.4f;
g_d3dMaterial.Ambient.r = 0.6f;
g_d3dMaterial.Ambient.g = 0.6f;
g_d3dMaterial.Ambient.b = 0.7f;
g_d3dMaterial.Specular.r = 0.4f;
g_d3dMaterial.Specular.g = 0.4f;
g_d3dMaterial.Specular.b = 0.4f;
g_d3dMaterial.Power = 8.0f;
g_D3DDevice->SetMaterial(&g_d3dMaterial);
//设置摄像机和投影矩阵
D3DXMATRIX matView;
D3DXVECTOR3 pEye(45.0f, 25.0f, 60.0f);
D3DXVECTOR3 pAt(0.0f, 0.0f, 0.0f);
D3DXVECTOR3 pUp(0.0f, 1.0f, 0.0f);
D3DXMatrixLookAtLH(&matView, &pEye,&pAt,&pUp);
g_D3DDevice->SetTransform(D3DTS_VIEW, &matView);
//设置投影矩阵
D3DXMATRIX matProjection;
D3DXMatrixPerspectiveFovLH(&matProjection,
D3DXToRadian(75),
(FLOAT)640 / (FLOAT)480,
1.0f,
180.0f);
g_D3DDevice->SetTransform(D3DTS_PROJECTION, &matProjection);
//创建d3d网格图形
// 创建陆地
D3DXCreateBox(g_D3DDevice,40.0f,2.0f,80.0f, &g_d3dGround,0);
// 创建球体
D3DXCreateSphere(g_D3DDevice, 1.5f, 20, 20, &g_d3dBall, 0);
//设置渲染状态
g_D3DDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
g_D3DDevice->SetRenderState(D3DRS_AMBIENT,D3DCOLOR_COLORVALUE(0.3f, 0.3f, 0.3f, 1.0f));
return true;
}
//初始化Havok物理引擎
bool InitializeHavok(void)
{
//
// 初始化基本的系统和我们的内存系统
//
// 分配0.5MB的物理解决缓存
g_hkMemoryRouter = hkMemoryInitUtil::initDefault( hkMallocAllocator::m_defaultMallocAllocator, hkMemorySystem::FrameInfo( 500* 1024 ) );
hkBaseSystem::init(g_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;
g_hkThreadPool = new hkCpuJobThreadPool( threadPoolCinfo );
//创建工作队列
hkJobQueueCinfo info;
info.m_jobQueueHwSetup.m_numCpuThreads = totalNumThreadsUsed;
g_hkJobQueue= new hkJobQueue(info);
//为这个线程池激活
hkMonitorStream::getInstance().resize(200000);
//创建Havok物理世界
{
//用于创建物理世界的信息
hkpWorldCinfo worldInfo;
//设置多线程来模拟我们的物理世界
worldInfo.m_simulationType = hkpWorldCinfo::SIMULATION_TYPE_MULTITHREADED;
// 将掉落在物理世界规定大小以外的实体移除
worldInfo.m_broadPhaseBorderBehaviour = hkpWorldCinfo::BROADPHASE_BORDER_REMOVE_ENTITY;
//创建物理世界
g_hkPhysicsWorld = new hkpWorld(worldInfo);
//设置去活化
g_hkPhysicsWorld->m_wantDeactivation = false;
//向我们已尽创建好的物理世界中写入数据
g_hkPhysicsWorld->markForWrite();
//注册碰撞代理
hkpAgentRegisterUtil::registerAllAgents( g_hkPhysicsWorld->getCollisionDispatcher() );
//注册工作队列
g_hkPhysicsWorld->registerWithJobQueue(g_hkJobQueue );
//-----------------------
//创建物理世界中的刚体
//-----------------------
//创建陆地
hkVector4 vec4Ground( 20.0f, 2.0f, 40.0f );
hkpConvexShape* shape = new hkpBoxShape(vec4Ground, 0 );
//填充陆地物理信息
hkpRigidBodyCinfo ci;
ci.m_shape = shape;
ci.m_motionType = hkpMotion::MOTION_FIXED;
ci.m_position = hkVector4( 0.0f, -2.0f, 0.0f );
ci.m_qualityType = HK_COLLIDABLE_QUALITY_FIXED;
//创建刚体,并添加到物理世界
g_hkGround=new hkpRigidBody(ci);
g_hkPhysicsWorld->addEntity(g_hkGround);
g_hkGround->removeReference();//移除引用
shape->removeReference();//移除引用
//创建球体
const hkReal radius = 1.5f;//球的直径
const hkReal sphereMass = 30.0f;//球的重量
hkVector4 relPos( 0.0f,radius + 0.0f, 0.0f );
//填充球体的刚体信息
hkpRigidBodyCinfo info;
hkpMassProperties massProperties;
hkpInertiaTensorComputer::computeSphereVolumeMassProperties(radius, sphereMass, massProperties);
info.m_mass = massProperties.m_mass;
info.m_centerOfMass = massProperties.m_centerOfMass;
info.m_inertiaTensor = massProperties.m_inertiaTensor;
info.m_shape = new hkpSphereShape(radius);
info.m_position.setAdd4(hkVector4(0.0f,0.0f,0.0f,20.0f),relPos );
info.m_motionType = hkpMotion::MOTION_BOX_INERTIA;
info.m_qualityType = HK_COLLIDABLE_QUALITY_BULLET;
//创建刚体
g_hkBall=new hkpRigidBody(info);
//添加到物理世界
g_hkPhysicsWorld->addEntity(g_hkBall);
g_hkBall->removeReference();//移除引用
info.m_shape->removeReference();//移除引用
//设置球的方向和速度
hkVector4 vel( 0.0f,19.6f, 8.0f );
g_hkBall->setLinearVelocity(vel);
//结束向物理世界写入数据
g_hkPhysicsWorld->unmarkForWrite();
}
}
return true;
}
//更新物理世界
void UpdateHavok(void)
{
//使用多线程进行一次模拟
g_hkPhysicsWorld->stepMultithreaded(g_hkJobQueue, g_hkThreadPool,1.0f/30.0f);
hkMonitorStream::getInstance().reset();
g_hkThreadPool->clearTimerData();
}
//释放资源
void ShutdownHavok(void)
{
//移除物理世界
g_hkPhysicsWorld->markForWrite();
g_hkPhysicsWorld->removeReference();
//清除工作队列和线程池
delete g_hkJobQueue;
g_hkThreadPool->removeReference();
//退出Havok内存系统
hkBaseSystem::quit();
hkMemoryInitUtil::quit();
}
void RenderScene()
{
// 清空后台缓存.
g_D3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0);
// 开始渲染
g_D3DDevice->BeginScene();
//绘制陆地
D3DXMatrixTranslation(&g_d3dMatGround, 0.0f, -2.0f, 0.0f);
// 设置世界矩阵
g_D3DDevice->SetTransform(D3DTS_WORLD, &g_d3dMatGround);
g_d3dGround->DrawSubset(0);
//绘制球体
hkVector4 pos = g_hkBall->getPosition();
D3DXMatrixTranslation(&g_d3dMatBall, pos(0), pos(1), pos(2));
//D3DXMatrixTranslation(&g_d3dMatBall, 0.0f, 5.0f,0.0f);
g_D3DDevice->SetTransform(D3DTS_WORLD, &g_d3dMatBall);
g_d3dBall->DrawSubset(0);
// 结束渲染
g_D3DDevice->EndScene();
// 输出图像
g_D3DDevice->Present(NULL, NULL, NULL, NULL);
}
void Shutdown()
{
if(g_d3dBall!=NULL) g_d3dBall->Release();
if(g_d3dGround!=NULL) g_d3dGround->Release();
if(g_D3DDevice != NULL) g_D3DDevice->Release();
if(g_D3D != NULL) g_D3D->Release();
}