游戏开发论坛

 找回密码
 立即注册
搜索
查看: 2266|回复: 3

摄像机类及演示

[复制链接]

9

主题

102

帖子

343

积分

中级会员

Rank: 3Rank: 3

积分
343
发表于 2007-2-24 19:08:00 | 显示全部楼层 |阅读模式
//Camera.h

void Vec3MulMat(D3DXVECTOR3*,D3DXVECTOR3*,D3DXMATRIXA16*);//向量乘以矩阵
void CreateViewMat(D3DXMATRIX*,D3DXVECTOR3*,D3DXVECTOR3*,D3DXVECTOR3*,D3DXVECTOR3*);//建立视矩阵
void MoveOnAxis(D3DXVECTOR3*,D3DXVECTOR3*,D3DXVECTOR3*,float);//沿着某个轴移动
void RotateWithAxis(D3DXVECTOR3*,D3DXVECTOR3*,D3DXVECTOR3*,float);//围绕某个轴旋转
class CCamera
{
public:
CCamera(float,float,float);
CCamera(D3DXVECTOR3*,D3DXVECTOR3*,D3DXVECTOR3*);
void MoveByWorld(float,float,float);//按照世界坐标移动
void Move(float,float,float);//(沿着摄像机的3轴)移动
void SetPos(float,float,float);//设置摄像机的位置
D3DXVECTOR3 GetPos();//取得位置
void Rotate(float,float,float);//(围绕摄像机的3轴)旋转
void RotateByWorld(float,float,float);//围绕世界坐标系的轴旋转
D3DXMATRIX GetViewMat();//取得视变换的矩阵
private:
D3DXVECTOR3 m_Pos;
D3DXVECTOR3 m_Look;
D3DXVECTOR3 m_Up;
D3DXVECTOR3 m_Right;
void CheckRightUpLook();//重新归一化,正交化Look,Up,重新计算出Right.
};

//Camera.cpp

#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")
#include <d3d9.h>
#include <d3dx9.h>
#include "Camera.h"

void Vec3MulMat(D3DXVECTOR3* ret,D3DXVECTOR3* v,D3DXMATRIX* m)
{
ret->x = v->x * m->_11 + v->y * m->_21 + v->z * m->_31;
ret->y = v->x * m->_12 + v->y * m->_22 + v->z * m->_32;
ret->z = v->x * m->_13 + v->y * m->_23 + v->z * m->_33;
}

void CreateViewMat(D3DXMATRIX* mat,D3DXVECTOR3* pos,D3DXVECTOR3* right,D3DXVECTOR3* up,D3DXVECTOR3* look)
{
mat->_11=right->x; mat->_12=up->x; mat->_13=look->x; mat->_14=0;
mat->_21=right->y; mat->_22=up->y; mat->_23=look->y; mat->_24=0;
mat->_31=right->z; mat->_32=up->z; mat->_33=look->z; mat->_34=0;
mat->_41=-D3DXVec3Dot(pos,right); mat->_42=-D3DXVec3Dot(pos,up); mat->_43=-D3DXVec3Dot(pos,look); mat->_44=1;
}

void CCamera::CheckRightUpLook()//还有另一种方法。。。
{
D3DXVec3Normalize(&m_Look,&m_Look);
m_Up=m_Up-m_Look*D3DXVec3Dot(&m_Up,&m_Look);
D3DXVec3Normalize(&m_Up,&m_Up);
D3DXVec3Cross(&m_Right,&m_Up,&m_Look);
}

void MoveOnAxis(D3DXVECTOR3* dest,D3DXVECTOR3* axis,D3DXVECTOR3* pos,float deltaS)
{
D3DXVECTOR3 tmp;
D3DXVec3Normalize(&tmp,axis);
*dest=tmp*deltaS+*pos;
}

void RotateWithAxis(D3DXVECTOR3* ret,D3DXVECTOR3* vec,D3DXVECTOR3* axis,float sita)
{
D3DXMATRIX mat;
D3DXMatrixRotationAxis(&mat,axis,sita);
Vec3MulMat(ret,vec,&mat);
}

D3DXVECTOR3 CCamera::GetPos()
{
return m_Pos;
}

void CCamera::MoveByWorld(float dx,float dy,float dz)
{
m_Pos.x+=dx;m_Pos.y+=dy;m_Pos.z+=dz;
}

void CCamera::SetPos(float x,float y,float z)
{
m_Pos.x=x;m_Pos.y=y;m_Pos.z=z;
}

void CCamera::RotateByWorld(float x,float y,float z)
{
D3DXMATRIX mat;
if(x)
{
D3DXMatrixRotationX(&mat,x);
Vec3MulMat(&m_Look,&m_Look,&mat);
Vec3MulMat(&m_Up,&m_Up,&mat);
}
if(y)
{
D3DXMatrixRotationY(&mat,y);
Vec3MulMat(&m_Look,&m_Look,&mat);
Vec3MulMat(&m_Up,&m_Up,&mat);
}
if(z)
{
D3DXMatrixRotationZ(&mat,z);
Vec3MulMat(&m_Look,&m_Look,&mat);
Vec3MulMat(&m_Up,&m_Up,&mat);
}
}

void CCamera::Rotate(float x,float y,float z)
{
if(x)
{
RotateWithAxis(&m_Look,&m_Look,&m_Right,x);
RotateWithAxis(&m_Up,&m_Up,&m_Right,x);
}
if(y)
{
RotateWithAxis(&m_Look,&m_Look,&m_Up,y);
RotateWithAxis(&m_Up,&m_Up,&m_Up,y);
}
if(z)
{
RotateWithAxis(&m_Look,&m_Look,&m_Look,z);
RotateWithAxis(&m_Up,&m_Up,&m_Look,z);
}
CheckRightUpLook();
}

void CCamera::Move(float dx,float dy,float dz)
{
if(dx)MoveOnAxis(&m_Pos,&m_Right,&m_Pos,dx);
if(dy)MoveOnAxis(&m_Pos,&m_Up,&m_Pos,dy);
if(dz)MoveOnAxis(&m_Pos,&m_Look,&m_Pos,dz);
}

D3DXMATRIX CCamera::GetViewMat()
{
D3DXMATRIX ret;
CreateViewMat(&ret,&m_Pos,&m_Right,&m_Up,&m_Look);
return ret;
}

CCamera::CCamera(float x,float y,float z)
{
m_Pos.x=x;
m_Pos.y=y;
m_Pos.z=z;
m_Up.x=0.0f;
m_Up.y=1.0f;
m_Up.z=0.0f;
m_Look.x=0.0f;
m_Look.y=0.0f;
m_Look.z=1.0f;
m_Right.x=1.0f;
m_Right.y=0.0f;
m_Right.z=0.0f;
}

CCamera::CCamera(D3DXVECTOR3* pos,D3DXVECTOR3* look,D3DXVECTOR3* up)
{
m_Pos=*pos;
m_Up=*up;
m_Look=*look;
CheckRightUpLook();
}

9

主题

102

帖子

343

积分

中级会员

Rank: 3Rank: 3

积分
343
 楼主| 发表于 2007-2-24 19:09:00 | 显示全部楼层

Re:摄像机类及演示

下面是一个使用CCamera的例子。
鼠标的控制和CS一样。a,s,d,w这个不用解释了把。r,f是向上,下
注意的是,j,l,是向左右旋转,但和鼠标不一样,
j,l,是围绕摄像机自己的Y轴(Up向量)旋转,而鼠标向左,右,总是围绕(0,1,0)向量旋转。
i,k,和鼠标的上下一样。都是围绕摄像机自己的X轴(Right向量)旋转。
u,o,像开飞机一样,左右翻滚。都是围绕摄像机自己的Z轴(Look向量)旋转。

//app.cpp

#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")
#pragma comment(lib,"winmm.lib")
#include <d3d9.h>
#include <d3dx9.h>
#include "Mouse.h"
#include "camera.h"

const float PI=3.14159265358f;
void Cleanup();
void Initd3d(HWND hwnd);
void OnKeyDown(WORD KeyCode);
LRESULT WINAPI WinProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam);
void Render();
void FrameMove();
int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR CmdLine,int nShowCmd);
CCamera* g_pCamera;
CMouse* g_pMouse;
long g_mouseX,g_mouseY;

HWND g_hwnd=0;
//D3DXMATRIXA16 g_matTrans;
LPDIRECT3D9 g_pd3d=0;
LPDIRECT3DDEVICE9 g_pdev=0;
LPDIRECT3DDEVICE9 g_pdev2=0;
LPDIRECT3DVERTEXBUFFER9 g_pvb=0;
LPDIRECT3DINDEXBUFFER9 g_pib=0;
LPDIRECT3DVERTEXBUFFER9 g_pvb2=0;
LPDIRECT3DINDEXBUFFER9 g_pib2=0;
typedef struct
{
FLOAT x,y,z;
DWORD color;
}CUSTOMVERTEX;

#define D3DFVF_CUSTOMVERTEX  (D3DFVF_XYZ|D3DFVF_DIFFUSE)
#define TURE -1;

#define TRY(x) if(FAILED(x))MessageBox(0,"failed!","",0)

void Initd3d(HWND hwnd)
{
if(!(g_pd3d=Direct3DCreate9(D3D_SDK_VERSION))) MessageBox(0,"err","",0);
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp,sizeof(d3dpp));
d3dpp.Windowed=TURE;
d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat=D3DFMT_UNKNOWN;
TRY(g_pd3d->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hwnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dpp,&g_pdev));
////
g_pCamera=new CCamera(0,0,-50.0f);
}

void InitDraw()
{
TRY(g_pdev->CreateVertexBuffer(8*sizeof(CUSTOMVERTEX),D3DUSAGE_WRITEONLY,D3DFVF_CUSTOMVERTEX,
   D3DPOOL_MANAGED,&g_pvb,0));

TRY(g_pdev->CreateIndexBuffer(36*sizeof(WORD),D3DUSAGE_WRITEONLY,D3DFMT_INDEX16,
  D3DPOOL_MANAGED,&g_pib,0));

const float len=10.0f;
CUSTOMVERTEX source_vertices[]={
{-len,-len,-len,D3DCOLOR_XRGB(255,0,0)},
{-len, len,-len,D3DCOLOR_XRGB(0,255,0)},
{ len, len,-len,D3DCOLOR_XRGB(0,0,255)},
{ len,-len,-len,D3DCOLOR_XRGB(255,255,0)},
{-len,-len, len,D3DCOLOR_XRGB(255,0,255)},
{-len, len, len,D3DCOLOR_XRGB(0,255,255)},
{ len, len, len,D3DCOLOR_XRGB(0,0,0)},
{ len,-len, len,D3DCOLOR_XRGB(255,255,255)},
};
CUSTOMVERTEX* pVertices;
TRY(g_pvb->Lock(0,8*sizeof(CUSTOMVERTEX),(void**)&pVertices,0));
memcpy(pVertices,source_vertices,8*sizeof(CUSTOMVERTEX));
g_pvb->Unlock();
/////////////ib///////////////
WORD* indices=0;
WORD tmpindices[]={0,1,2,0,2,3,4,6,5,4,7,6,4,5,1,4,1,0,3,2,6,3,6,7,1,5,6,1,6,2,4,0,3,4,3,7};

g_pib->Lock(0,0,(void**)&indices,0);
memcpy(indices,tmpindices,36*sizeof(WORD));
g_pib->Unlock();
//////////////////////////
g_pdev->SetRenderState(D3DRS_LIGHTING,FALSE);
}

void Cleanup()
{
delete g_pMouse;
delete g_pCamera;
if(g_pvb)g_pvb->Release();
if(g_pdev)g_pdev->Release();
if(g_pd3d)g_pd3d->Release();
}

void FrameMove()
{

g_pdev->SetTransform(D3DTS_VIEW,&g_pCamera->GetViewMat());

D3DXMATRIX matProj;
D3DXMatrixPerspectiveFovLH(&matProj,D3DX_PI*0.5f,(float)800/(float)600,1.0f,1000.0f);
g_pdev->SetTransform(D3DTS_PROJECTION,&matProj);

/////

D3DXMATRIXA16 mat;
D3DXMatrixIdentity(&mat);
D3DXMatrixRotationY(&mat,timeGetTime()/300.0f);

g_pdev->SetTransform(D3DTS_WORLD,&mat);

}
void Render()
{

g_pdev->Clear(0,0,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,255),1.0f,0);
g_pdev->BeginScene();
{
g_pdev->SetStreamSource(0,g_pvb,0,sizeof(CUSTOMVERTEX));
g_pdev->SetFVF(D3DFVF_CUSTOMVERTEX);
g_pdev->SetIndices(g_pib);
g_pdev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,8,0,12);
}
g_pdev->EndScene();
/////////////////////
g_pdev-&gtresent(0,0,0,0);
}

LRESULT WINAPI WinProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
{
switch(msg)
{
case WM_KEYDOWN:
OnKeyDown(wparam);
break;
case WM_MOUSEMOVE:
if(!g_pMouse)g_pMouse=new CMouse((float)g_mouseX,(float)g_mouseY,PI*0.001f,PI*0.001f);
float retx,rety;
g_pMouse->MovePos((float)g_mouseX,(float)g_mouseY,&retx,&rety);
g_pCamera->Rotate(rety,0,0);
g_pCamera->RotateByWorld(0,retx,0);
break;
case WM_DESTROY:
Cleanup();
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd,msg,wparam,lparam);
}

9

主题

102

帖子

343

积分

中级会员

Rank: 3Rank: 3

积分
343
 楼主| 发表于 2007-2-24 19:09:00 | 显示全部楼层

Re:摄像机类及演示

int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR CmdLine,int nShowCmd)
{
WNDCLASSEX wc={sizeof(WNDCLASSEX),CS_CLASSDC,WinProc,0L,0L,
GetModuleHandle(0),0,0,0,0,"instemast",0};
RegisterClassEx(&wc);
g_hwnd=CreateWindow("instemast","d3d",WS_OVERLAPPEDWINDOW,100,100,800,600,0,0,wc.hInstance,0);
Initd3d(g_hwnd);
InitDraw();
ShowWindow(g_hwnd,SW_SHOWDEFAULT);
UpdateWindow(g_hwnd);
///////////////////////////////////////
RECT rt;
GetWindowRect(g_hwnd,&rt);
SetCursorPos(g_mouseX=rt.left+400,g_mouseY=rt.top+300);
///////////////////////////////////////
MSG msg;
ZeroMemory(&msg,sizeof(msg));
while(msg.message!=WM_QUIT)
{
if(:eekMessage(&msg,0,0U,0U,PM_REMOVE))
{
g_mouseX=msg.pt.x;g_mouseY=msg.pt.y;
::TranslateMessage(&msg);
:ispatchMessage(&msg);
}else
{
FrameMove();
Render();
};
};
UnregisterClass("instemast",wc.hInstance);

return 0;
}

void OnKeyDown(WORD KeyCode)
{
D3DXMATRIXA16 mat;
// char tmp=(char)KeyCode;
float MoveSpeed=0.75f;
float RotateSpeed=PI*0.005f;
switch(KeyCode)
{
case 'W':
g_pCamera->Move(0,0,MoveSpeed);
break;
case 'S':
g_pCamera->Move(0,0,-MoveSpeed);
break;
case 'A':
g_pCamera->Move(-MoveSpeed,0,0);
break;
case 'D':
g_pCamera->Move(MoveSpeed,0,0);
break;
case 'R':
g_pCamera->Move(0,MoveSpeed,0);
break;
case 'F':
g_pCamera->Move(0,-MoveSpeed,0);
break;
////////////////
case 'L':
g_pCamera->Rotate(0,RotateSpeed,0);
break;
case 'J':
g_pCamera->Rotate(0,-RotateSpeed,0);
break;
case 'I':
g_pCamera->Rotate(-RotateSpeed,0,0);
break;
case 'K':
g_pCamera->Rotate(RotateSpeed,0,0);
break;
case 'U':
g_pCamera->Rotate(0,0,RotateSpeed);
break;
case 'O':
g_pCamera->Rotate(0,0,-RotateSpeed);
break;
};
}

9

主题

102

帖子

343

积分

中级会员

Rank: 3Rank: 3

积分
343
 楼主| 发表于 2007-2-24 19:10:00 | 显示全部楼层

Re:摄像机类及演示

对于鼠标,使用了一个小类,(由于不用di,不可以360度转动你的头~)
纪录下上次鼠标的位置,鼠标移动时,新鼠标位置减去旧的,然后乘以鼠标速度(灵敏度),
即可获得旋转角。
//Mouse.h
class CMouse
{
public:
float GetX(){ return m_X; }
float GetY(){ return m_Y; }
private:
float m_X;
float m_Y;
public:
void MovePos(float,float,float*,float*);
float m_SpeedX,m_SpeedY;
CMouse(float,float,float,float);
};

//Mouse.cpp
#include "Mouse.h"
void CMouse::MovePos(float newx,float newy,float* anglex,float* angley)
{
float dx=newx-m_X;
float dy=newy-m_Y;
*anglex=m_SpeedX*dx;
*angley=m_SpeedY*dy;
m_X=newx;
m_Y=newy;
}

CMouse::CMouse(float x,float y,float speedx,float speedy)
{
m_X=x;
m_Y=y;
m_SpeedX=speedx;
m_SpeedY=speedy;
}

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-26 11:56

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表