西昌.何雨锋
#include "stdafx.h"
#include <windows.h>
#include <windowsx.h>
#include ".\TV.h"
#include ".\havok.h"
CTVEngine *engine1;
CTVInputEngine *input1; //输入引擎
CTVScene *scene1; //场景
CTVGlobals *global1; //全球变量
CTVAtmosphere *atmos1;
CTVLandscape *land1;
CTVTextureFactory *fac1;
CTVMesh *sphere1;
CTVCameraFactory *camfac1;
CTVCamera *cam1;
hkReal lastTime,nextTime;
double xrot=0; //
double yrot=0;
double zrot=0;
double xpos=0; //主角位置
double ypos=0;
double zpos=0;
double lookx=0; //主角视点
double looky=0;
double lookz=0;
double xangle=0;
double yangle=0;
double arcc=0;
double timeleft;
float me_walk = 0.0; //前后移动变量
float me_strafe = 0.0; //左右移动变量
float me_updown=0.0;
void init_TV(HWND Handle);
void render();
void input();
void unload();
hkpWorld* physicsWorld=NULL;
hkJobQueue* jobQueue=NULL;
hkJobThreadPool* threadPool=NULL;
hkpPhysicsContext* context=NULL;
hkArray<hkProcessContext*> contexts;
hkVisualDebugger* vdb;
void setupPhysics();
void Init_Havok();
void Run_Havok();
void createBrickWall(int height, int length, const hkVector4& position, hkReal gapWidth, hkpConvexShape* box, hkVector4Parameter halfExtents );
hkpRigidBody* g_ball;
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
void init(HWND Handle)
{
init_TV(Handle);
}
//Entry point.
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
//Firstly lets create a window.
HWND hWnd;
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = (LPCWSTR) "WindowClass1";
RegisterClassEx(&wc);
int Cx = GetSystemMetrics(SM_CXSCREEN);
int Cy = GetSystemMetrics(SM_CYSCREEN);
hWnd = CreateWindowEx(NULL,(LPCWSTR) "WindowClass1",(LPCWSTR) "Blank Screen", WS_CAPTION, (Cx / 2) - (800 / 2), (Cy / 2) - (600 / 2), 800, 600, NULL, NULL, hInstance, NULL);
ShowWindow(hWnd, nCmdShow);
init(hWnd);
MSG msg;
Init_Havok();
unload();
/* while(TRUE)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if(msg.message == WM_QUIT) break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}*/
return msg.wParam;
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
} break;
}
return DefWindowProc (hWnd, message, wParam, lParam);
}
void render()
{
engine1->Clear(false);
atmos1->Atmosphere_Render();
land1->Render();
scene1->RenderAllMeshes();
//scene1->RenderAllActors();
//scene1->RenderAllMeshes();
engine1->RenderToScreen ();
}
void input()
{
if(input1->IsKeyPressed(cTV_KEY_ESCAPE)) //Check if ESCAPE has been pressed.
{
PostQuitMessage(0);
}
if(input1->IsKeyPressed(cTV_KEY_UP))
me_walk=0.2;
if(input1->IsKeyPressed(cTV_KEY_DOWN))
me_walk=-0.2;
if(input1->IsKeyPressed(cTV_KEY_LEFT))
me_strafe =0.2;
if(input1->IsKeyPressed(cTV_KEY_RIGHT))
me_strafe = -0.2;
if(input1->IsKeyPressed(cTV_KEY_W))
me_walk = 1;
if(input1->IsKeyPressed(cTV_KEY_S))
me_walk = -1;
if(input1->IsKeyPressed(cTV_KEY_A))
me_strafe =1;
if(input1->IsKeyPressed(cTV_KEY_D))
me_strafe = -1;
if(input1->IsKeyPressed(cTV_KEY_C))
me_updown=-1;
if(input1->IsKeyPressed(cTV_KEY_SPACE))
me_updown=1;
long mousex=0; long mousey=0;
int mouse_b1=0; int mouse_b2=0; int mouse_b3=0;
long mouse_old=0; long mouse_new=0;
mouse_old = mouse_new;
input1->GetMouseState((int *) &mousex,(int *) &mousey,(bool *)&mouse_b1,(bool *)&mouse_b2,(bool *)&mouse_b3,(bool *) &mouse_old);
xangle = xangle - ((float)mousey / 100.0f);
yangle = yangle - ((float)mousex / 100.0f);
if(xangle > 1.3f) xangle = 1.3f;
if(xangle < -1.3f) xangle = -1.3f;
if(me_walk > 0)
{
me_walk = me_walk - 0.05f;
if(me_walk < 0) me_walk = 0;
}
if(me_walk < 0)
{
me_walk = me_walk + 0.05f;
if(me_walk > 0) me_walk = 0;
}
if(me_strafe > 0)
{
me_strafe = me_strafe - 0.05f;
if(me_strafe < 0) me_strafe = 0;
}
if(me_strafe < 0)
{
me_strafe = me_strafe + 0.05f;
if(me_strafe > 0) me_strafe = 0;
}
timeleft=engine1->TimeElapsed();
//不知道hl中是否也这样写的呢?上下移动是否与鼠标无关?
xpos = xpos + (cosf(yangle) * me_walk * timeleft) + (cosf(yangle + 3.141596f / 2.0f) * me_strafe * timeleft);
zpos = zpos + (sinf(yangle) * me_walk * timeleft) + (sinf(yangle + 3.141596f / 2.0f) * me_strafe * timeleft);
ypos=ypos+me_updown;
me_updown=0;
lookx = xpos + cosf(yangle);
looky = ypos + tanf(xangle);
lookz = zpos + sinf(yangle);
cam1->SetCamera(xpos,ypos,zpos,lookx,looky,lookz);
}
void unload()
{
engine1->ReleaseAll();
delete(engine1);
}
void init_TV(HWND Handle)
{
engine1 = new CTVEngine;
engine1->SetDebugFile("debug.txt"); //We want TV to dump a debug file, this is very useful, Sylvain is good at catching common mistakes and informing you that you've made them in this files log.
engine1->Init3DWindowed(Handle, true); //We want to initialize on our windows handle and we have hardware transform and lighting.
//engine1->Init3DFullscreen(800, 600, 32, true, false, cTV_DEPTHBUFFER_BESTBUFFER, 1, Handle);
global1=new CTVGlobals;
input1=new CTVInputEngine;
input1->Initialize(true, true);
scene1=new CTVScene; //场景
global1=new CTVGlobals; //全球变量
atmos1=new CTVAtmosphere;
land1=new CTVLandscape;
fac1=new CTVTextureFactory;
sphere1=new CTVMesh;
camfac1=new CTVCameraFactory;
cam1=new CTVCamera;
fac1->LoadTexture("map\\skybox\\up.jpg","up",-1,-1,cTV_COLORKEY_NO);
fac1->LoadTexture("map\\skybox\\dn.jpg","down",-1,-1,cTV_COLORKEY_NO);
fac1->LoadTexture("map\\skybox\\lf.jpg","left",-1,-1,cTV_COLORKEY_NO);
fac1->LoadTexture("map\\skybox\\rt.jpg","right",-1,-1,cTV_COLORKEY_NO);
fac1->LoadTexture("map\\skybox\\ft.jpg","front",-1,-1,cTV_COLORKEY_NO);
fac1->LoadTexture("map\\skybox\\bk.jpg","back",-1,-1,cTV_COLORKEY_NO);
atmos1->SkyBox_SetTexture(global1->GetTex("front"),global1->GetTex("back"),global1->GetTex("left"),global1->GetTex("right"),global1->GetTex("up"),global1->GetTex("down"));
atmos1->SkyBox_Enable(true);
fac1->LoadTexture("map\\heightmap\\texture2.jpg","map_tex",-1,-1,cTV_COLORKEY_NO);
land1=scene1->CreateLandscape("land1");
land1->LoadTerrainData("map\\heightmap\\3.map");
//land1->GenerateTerrain("map\\heightmap\\height1.jpg",cTV_PRECISION_LOW,32,32,1000,1000,true);
//land1->SetScale(2,16,2);
land1->ExpandTexture(global1->GetTex("map_tex"),0,0,32,32,false);
camfac1->CreateCamera("cam1");
cam1=camfac1->GetCameraByName("cam1");
cam1->SetPosition(500,land1->GetHeight(500,500)+20,500);
cam1->SetLookAt(100,100,100);
cam1->SetViewFrustum(60,5000,1);
engine1->SetCamera(cam1);
}
void setupPhysics()
{
{
hkVector4 groundRadii( 70.0f, 2.0f, 140.0f );
hkpConvexShape* shape = new hkpBoxShape( groundRadii , 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;
physicsWorld->addEntity(new hkpRigidBody( ci ) )->removeReference();
shape->removeReference();
}
hkVector4 groundPos( 0.0f, 0.0f, 0.0f );
hkVector4 posy = groundPos;
int wallHeight = 8;
int wallWidth = 8;
int numWalls = 6;
hkVector4 boxSize( 1.0f, 0.5f, 0.5f);
hkpBoxShape* box = new hkpBoxShape( boxSize , 0 );
box->setRadius( 0.0f );
hkReal deltaZ = 25.0f;
posy(2) = -deltaZ * numWalls * 0.5f;
for ( int y = 0; y < numWalls; y ++ ) // first wall
{
createBrickWall(wallHeight, wallWidth, posy, 0.2f, box, boxSize );
posy(2) += deltaZ;
}
box->removeReference();
const hkReal radius = 1.5f;
const hkReal sphereMass = 150.0f;
hkVector4 relPos( 0.0f,radius + 0.0f, 50.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(posy, relPos );
info.m_motionType = hkpMotion::MOTION_BOX_INERTIA;
info.m_qualityType = HK_COLLIDABLE_QUALITY_BULLET;
hkpRigidBody* sphereRigidBody = new hkpRigidBody( info );
g_ball = sphereRigidBody;
physicsWorld->addEntity( sphereRigidBody );
sphereRigidBody->removeReference();
info.m_shape->removeReference();
hkVector4 vel( 0.0f,4.9f, -100.0f );
sphereRigidBody->setLinearVelocity( vel );
}
void Init_Havok()
{
PlatformInit();
hkMemoryRouter* memoryRouter = hkMemoryInitUtil::initDefault( hkMallocAllocator::m_defaultMallocAllocator, hkMemorySystem::FrameInfo( 500* 1024 ) );
hkBaseSystem::init( memoryRouter, errorReport );
{
//hkJobThreadPool* threadPool;
int totalNumThreadsUsed;
hkHardwareInfo hwInfo;
hkGetHardwareInfo(hwInfo);
totalNumThreadsUsed = hwInfo.m_numThreads;
hkCpuJobThreadPoolCinfo threadPoolCinfo;
threadPoolCinfo.m_numThreads = totalNumThreadsUsed - 1;
threadPoolCinfo.m_timerBufferPerThreadAllocation = 200000;
threadPool = new hkCpuJobThreadPool( threadPoolCinfo );
hkJobQueueCinfo info;
info.m_jobQueueHwSetup.m_numCpuThreads = totalNumThreadsUsed;
hkJobQueue* jobQueue = new hkJobQueue(info);
hkMonitorStream::getInstance().resize(200000);
//hkpWorld* world;
{
hkpWorldCinfo worldInfo;
worldInfo.m_simulationType = hkpWorldCinfo::SIMULATION_TYPE_MULTITHREADED;
worldInfo.m_broadPhaseBorderBehaviour = hkpWorldCinfo::BROADPHASE_BORDER_REMOVE_ENTITY;
physicsWorld = new hkpWorld(worldInfo);
physicsWorld->m_wantDeactivation = false;
physicsWorld->markForWrite();
hkpAgentRegisterUtil::registerAllAgents( physicsWorld->getCollisionDispatcher() );
physicsWorld->registerWithJobQueue( jobQueue );
setupPhysics();
}
//hkArray<hkProcessContext*> contexts;
//hkpPhysicsContext* context;
{
context = new hkpPhysicsContext();
hkpPhysicsContext::registerAllPhysicsProcesses();
context->addWorld(physicsWorld);
contexts.pushBack(context);
physicsWorld->unmarkForWrite();
}
hkVisualDebugger* vdb = new hkVisualDebugger(contexts);
vdb->serve();
hkStopwatch stopWatch;
stopWatch.start();
hkReal lastTime = stopWatch.getElapsedSeconds();
hkReal timestep = 1.f / 60.f;
int numSteps = int(60.f / timestep);
while(TRUE)
{
Run_Havok();
physicsWorld->stepMultithreaded( jobQueue, threadPool, 1.f / 60.f );
context->syncTimers( threadPool );
vdb->step();
hkMonitorStream::getInstance().reset();
threadPool->clearTimerData();
while (stopWatch.getElapsedSeconds() < lastTime + timestep);
lastTime += timestep;
render();
input();
}
{
physicsWorld->markForWrite();
physicsWorld->removeReference();
}
vdb->removeReference();
context->removeReference();
delete jobQueue;
threadPool->removeReference();
}
hkBaseSystem::quit();
hkMemoryInitUtil::quit();
PlatformQuit();
}
void Run_Havok()
{
}
void createBrickWall( int height, int length, const hkVector4& position, hkReal gapWidth, hkpConvexShape* box, hkVector4Parameter halfExtents )
{
hkVector4 posx = position;
{
hkpWorldRayCastInput ray;
ray.m_from = posx;
ray.m_to = posx;
ray.m_from(1) += 20.0f;
ray.m_to(1) -= 20.0f;
hkpWorldRayCastOutput result;
physicsWorld->castRay( ray, result );
posx.setInterpolate4( ray.m_from, ray.m_to, result.m_hitFraction );
}
posx(0) -= ( gapWidth + 2.0f * halfExtents(0) ) * length * 0.5f;
posx(1) -= halfExtents(1) + box->getRadius();
hkArray<hkpEntity*> entitiesToAdd;
for ( int x = 0; x < length; x ++ )
{
hkVector4 pos = posx;
for( int ii = 0; ii < height; ii++ )
{
pos(1) += (halfExtents(1) + box->getRadius())* 2.0f;
hkpRigidBodyCinfo boxInfo;
boxInfo.m_mass = 10.0f;
hkpMassProperties massProperties;
hkpInertiaTensorComputer::computeBoxVolumeMassProperties(halfExtents, boxInfo.m_mass, massProperties);
boxInfo.m_mass = massProperties.m_mass;
boxInfo.m_centerOfMass = massProperties.m_centerOfMass;
boxInfo.m_inertiaTensor = massProperties.m_inertiaTensor;
boxInfo.m_solverDeactivation = boxInfo.SOLVER_DEACTIVATION_MEDIUM;
boxInfo.m_shape = box;
boxInfo.m_restitution = 0.0f;
boxInfo.m_motionType = hkpMotion::MOTION_BOX_INERTIA;
{
boxInfo.m_position = pos;
hkpRigidBody* boxRigidBody = new hkpRigidBody(boxInfo);
physicsWorld->addEntity( boxRigidBody );
boxRigidBody->removeReference();
}
pos(1) += (halfExtents(1) + box->getRadius())* 2.0f;
pos(0) += halfExtents(0) * 0.6f;
{
boxInfo.m_position = pos;
hkpRigidBody* boxRigidBody = new hkpRigidBody(boxInfo);
entitiesToAdd.pushBack(boxRigidBody);
}
pos(0) -= halfExtents(0) * 0.6f;
}
posx(0) += halfExtents(0)* 2.0f + gapWidth;
}
physicsWorld->addEntityBatch( entitiesToAdd.begin(), entitiesToAdd.getSize());
for (int i=0; i < entitiesToAdd.getSize(); i++){ entitiesToAdd[i]->removeReference(); }
}
总结:
physicsWorld->stepMultithreaded( jobQueue, threadPool, 1.f / 60.f );语句非常奇怪,不能放到任何函数里执行,甚至不能放到WinMain的while循环里去执行,查看HVK的范例,全都是基于控制台而非windows平台编写的,而TV似乎又只能在win32程序中执行,坑爹啊.....