. . . . . . . . . . . . . . Blog Garden' C plus plus (My technology Impire!)

................................................................ It‘s a age of economic globalization and Infomation globalization........................................

[引] 键盘控制3D场景漫游

[引] 键盘控制3D场景漫游

//做了好久都不能整合鼠标做CS那样的运动引擎....看来暂时都只能用键盘控制了

//-----------------------------------------------------------------------------
// File: basic.cpp
//
//-----------------------------------------------------------------------------
#define STRICT
#include <Windows.h>
#include <commctrl.h>
#include <stdio.h>
#include <math.h>
#include <D3DX9.h>
#include "DXUtil.h"
#include "D3DEnumeration.h"
#include "D3DSettings.h"
#include "D3DApp.h"
#include "D3DFile.h"
#include "D3DFont.h"
#include "D3DUtil.h"
#include "resource.h"

//-----------------------------------------------------------------------------
// Name: class CMyD3DApplication
// Desc: Application class. The base class (CD3DApplication) provides the
//       generic functionality needed in all Direct3D samples. CMyD3DApplication
//       adds functionality specific to this sample program.
//-----------------------------------------------------------------------------
class CMyD3DApplication : public CD3DApplication
{
    LPD3DXMESH m_pMesh;     //Mesh对象的接口指针
 D3DMATERIAL9 *m_pMeshMaterials;  //用于保存模型中各个子集的材质
 LPDIRECT3DTEXTURE9 *m_pMeshTextures;//用于保存模型中各个子集的纹理
 DWORD m_dwNumSubsets;    //模型中子集的数目
 TCHAR               m_strMeshFilename[512];
    TCHAR               m_strInitialDir[512];

 //CD3DArcBall         m_ArcBall;              // Mouse rotation utility
    D3DXVECTOR3         m_vObjectCenter;        // Center of bounding sphere of object
    FLOAT               m_fObjectRadius;        // Radius of bounding sphere of object

 D3DXVECTOR3 VDot,VAtPoint,VUp;//全局观察变量
 BYTE  m_bKey[256];   // keyboard state buffer
 

protected:
    HRESULT OneTimeSceneInit();
    HRESULT InitDeviceObjects();
    HRESULT RestoreDeviceObjects();
    HRESULT InvalidateDeviceObjects();
    HRESULT DeleteDeviceObjects();
    HRESULT FinalCleanup();
    HRESULT Render();
    HRESULT FrameMove();
    HRESULT ConfirmDevice( D3DCAPS9* pCaps, DWORD dwBehavior,
  D3DFORMAT adapterFormat, D3DFORMAT backBufferFormat );
 LRESULT MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
public:
    CMyD3DApplication();
};


//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: Entry point to the program. Initializes everything, and goes into a
//       message-processing loop. Idle time is used to render the scene.
//-----------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
    CMyD3DApplication d3dApp;

    InitCommonControls();
    if( FAILED( d3dApp.Create( hInst ) ) )
        return 0;

    return d3dApp.Run();
}

//-----------------------------------------------------------------------------
// Name: CMyD3DApplication()
// Desc: Application constructor. Sets attributes for the app.
//-----------------------------------------------------------------------------
CMyD3DApplication::CMyD3DApplication()
{
 m_bStartFullscreen=TRUE;
    //m_dwCreationWidth  = 800;   // Width used to create window
    //m_dwCreationHeight  = 600;
  // Override base class members
    m_strWindowTitle    = _T("加载Mesh模型");
    m_d3dEnumeration.AppUsesDepthBuffer   = TRUE;
  DXUtil_GetDXSDKMediaPathCb( m_strInitialDir, sizeof(m_strInitialDir) );
    _tcscpy( m_strMeshFilename, _T("this.x") );
    //初始化
 ZeroMemory( m_bKey, 256 );
}

//-----------------------------------------------------------------------------
// Name: ConfirmDevice()
// Desc: Called during device initialization, this code checks the device
//       for some minimum set of capabilities
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::ConfirmDevice( D3DCAPS9* pCaps, DWORD dwBehavior,
                                          D3DFORMAT adapterFormat, D3DFORMAT backBufferFormat )
{
    return S_OK;
}

//-----------------------------------------------------------------------------
// Name: OneTimeSceneInit()
// Desc: Called during initial app startup, this function performs all the
//       permanent initialization.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::OneTimeSceneInit()
{
    return S_OK;
}


//-----------------------------------------------------------------------------
// Name: InitDeviceObjects()
// Desc: Initialize scene objects.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::InitDeviceObjects()
{
 LPD3DXBUFFER pD3DXMtrlBuffer;

 TCHAR      strMeshPath[512];
  // Load the mesh from the specified file
    DXUtil_FindMediaFileCb( strMeshPath, sizeof(strMeshPath), m_strMeshFilename );
 //从.x文件创建Mesh对象
 ::D3DXLoadMeshFromX(
  strMeshPath, D3DXMESH_SYSTEMMEM, m_pd3dDevice,
  NULL, &pD3DXMtrlBuffer, NULL,
  &m_dwNumSubsets, //返回模型中子集的数目
  &m_pMesh );   //返回Mesh对象的接口指针

 m_pMeshMaterials = new D3DMATERIAL9[m_dwNumSubsets];
 m_pMeshTextures = new LPDIRECT3DTEXTURE9[m_dwNumSubsets];
    ZeroMemory(m_pMeshMaterials , sizeof(D3DMATERIAL9) * m_dwNumSubsets);
 ZeroMemory(m_pMeshTextures , sizeof(LPDIRECT3DTEXTURE9) * m_dwNumSubsets);
 //从接口指针pD3DXMtrlBuffer获得各个子集的材质和纹理图片的文件名
 D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
 for( DWORD i=0; i < m_dwNumSubsets; i++ )
 {
  //复制子集的材质
  m_pMeshMaterials[i] = d3dxMaterials[i].MatD3D;
  //Direct3D在调入Mesh模型时,没有设置材质的环境光颜色,
  //这里把它设置成和漫反射一样的颜色。
  m_pMeshMaterials[i].Ambient = m_pMeshMaterials[i].Diffuse;

  TCHAR strTexturePath[512] = _T("");
        DXUtil_FindMediaFileCb( strTexturePath, sizeof(strTexturePath), d3dxMaterials[i].pTextureFilename );
  //调入纹理图片
  ::D3DXCreateTextureFromFile(
   m_pd3dDevice,
   strTexturePath, //纹理图片的文件名
   &m_pMeshTextures[i] );
 }

 pD3DXMtrlBuffer->Release(); //释放接口
    return S_OK;
}

//-----------------------------------------------------------------------------
// Name: RestoreDeviceObjects()
// Desc: Initialize scene objects.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::RestoreDeviceObjects()
{
   m_pd3dDevice->SetRenderState( D3DRS_AMBIENT,
   D3DCOLOR_COLORVALUE(0.7,0.7,0.7,0.7 ));

    // Set the arcball parameters
    m_ArcBall.SetWindow( m_d3dsdBackBuffer.Width, m_d3dsdBackBuffer.Height,
                         0.85f );
    m_ArcBall.SetRadius( m_fObjectRadius );

    // Set the projection matrix
 D3DXMATRIXA16 matProj;
 ::D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 10000.0f );
 m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );

 D3DXMATRIX matView;
 D3DXMatrixLookAtLH( &matView,&VDot, &VAtPoint, &VUp );
 m_pd3dDevice->SetTransform( D3DTS_VIEW,  &matView );
    return S_OK;
}

//-----------------------------------------------------------------------------
// Name: InvalidateDeviceObjects()
// Desc:
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::InvalidateDeviceObjects()
{

    return S_OK;
}

//-----------------------------------------------------------------------------
// Name: DeleteDeviceObjects()
// Desc: Called when the app is exiting, or the device is being changed,
//       this function deletes any device dependent objects.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::DeleteDeviceObjects()
{
 for (DWORD i = 0; i < m_dwNumSubsets; i++)
  m_pMeshTextures[i]->Release();  //释放纹理对象
 delete [] m_pMeshMaterials;
 delete [] m_pMeshTextures;
 m_pMesh->Release();   //释放Mesh对象
    return S_OK;
}

//-----------------------------------------------------------------------------
// Name: FrameMove()
// Desc: Called once per frame, the call is the entry point for animating
//       the scene.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::FrameMove()
{   
  // Setup world matrix
 float angle = 3 * D3DX_PI / 180;
 D3DXMATRIX matWorld;
 ::D3DXMatrixRotationY( &matWorld, angle );
 m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );


    // Set up view matrix
 
    float fRoll=0, fPitch =0, fYaw = 0.0f;
    float fOneStep=1.5;
    D3DXVECTOR3 vPos(0.0f, 0.0f, 0.0f);
    static D3DXMATRIX matView  = D3DXMATRIX(1.0f, 0.0f, 0.0f, 0.0f,
                 0.0f, 1.0f, 0.0f, 0.0f, 
                 0.0f, 0.0f, 1.0f, 0.0f, 
                 0.0f, 0.0f, 0.0f, 1.0f);
 // Process keyboard input
 if (m_bKey[VK_UP])   fPitch -= fOneStep*0.05; // Pitch Up
    if (m_bKey[VK_DOWN])  fPitch += fOneStep*0.05; // Pitch Down
    if (m_bKey[VK_LEFT])     fYaw -= fOneStep*0.05; // Turn Left
    if (m_bKey[VK_RIGHT])     fYaw += fOneStep*0.05; // Turn Right
    //if (m_bKey['C'])      fRoll += fOneStep; // Rotate Left
    //if (m_bKey['X'])      fRoll -= fOneStep; // Rotate Right
    if (m_bKey['W'])  vPos.z += fOneStep; // Move Forward
    if (m_bKey['S'])   vPos.z -= fOneStep; // Move Backward
    if (m_bKey['A'])  vPos.x -= fOneStep; // Slide Left
    if (m_bKey['D'])  vPos.x += fOneStep; // Slide Right
    if (m_bKey['Q'])     vPos.y += fOneStep; // Slide Down
    if (m_bKey['E'])     vPos.y -= fOneStep; // Slide Up

    // Update position and view matricies
    D3DXMATRIX matR, matTemp;
 D3DXQUATERNION qR;
 D3DXQuaternionRotationYawPitchRoll (&qR, fYaw, fPitch, fRoll); 
 D3DXMatrixRotationQuaternion (&matR, &qR);      
 D3DXMatrixMultiply (&matView, &matR, &matView);
 D3DXMatrixTranslation (&matTemp, vPos.x, vPos.y, vPos.z);
 D3DXMatrixMultiply (&matView, &matTemp, &matView);
 D3DXMatrixInverse (&matTemp, NULL, &matView);
 //D3DXMatrixMultiply(&matTemp,&matTemp,m_ArcBall.GetRotationMatrix());
 m_pd3dDevice->SetTransform(D3DTS_VIEW, &matTemp );
 
    return S_OK;
}

//-----------------------------------------------------------------------------
// Name: Render()
// Desc: Called once per frame, the call is the entry point for 3d
//       rendering. This function sets up render states, clears the
//       viewport, and renders the scene.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::Render()
{
 // Clear the backbuffer
   m_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
                         0x000000ff, 1.0f, 0x00000000 );
    // Begin the scene
    if( SUCCEEDED( m_pd3dDevice->BeginScene() ) )
    {
  //m_pd3dDevice->SetRenderState(D3DRS_NORMALIZENORMALS, TRUE);//解决发暗问题
  for( DWORD i=0; i < m_dwNumSubsets; i++ )
    {
  //设置子集的材质
  m_pd3dDevice->SetMaterial( &m_pMeshMaterials[i] );
  //设置子集的纹理,混合方式使用缺省值:纹理 × 材质的漫反射
  m_pd3dDevice->SetTexture( 0, m_pMeshTextures[i] );
  //绘制子集
  m_pMesh->DrawSubset( i );
  m_pd3dDevice->SetTexture( 0, NULL);
     }

      // End the scene.
      m_pd3dDevice->EndScene();
    }

    return S_OK;
}

//-----------------------------------------------------------------------------
// Name: FinalCleanup()
// Desc: Called before the app exits, this function gives the app the chance
//       to cleanup after itself.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::FinalCleanup()
{
    return S_OK;
}

//-----------------------------------------------------------------------------
// Name: MsgProc()
// Desc: Message proc function to handle key and menu input
//-----------------------------------------------------------------------------
LRESULT CMyD3DApplication::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam,
                                    LPARAM lParam )
{
    // Pass mouse messages to the ArcBall so it can build internal matrices
    //m_ArcBall.HandleMouseMessages( hWnd, uMsg, wParam, lParam );
 // Record key presses
    if( WM_KEYDOWN == uMsg )
    {
        m_bKey[wParam] = 1;
    }

    // Perform commands when keys are rleased
    if( WM_KEYUP == uMsg )
    {
        m_bKey[wParam] = 0;
 }
  // Pass remaining messages to default handler
    return CD3DApplication::MsgProc( hWnd, uMsg, wParam, lParam );
}

posted on 2006-10-04 03:38 Technical Consultant 阅读(961) 评论(3)  编辑 收藏 引用 所属分类: Game Develope & Game Engine

Feedback

# re: [引] 键盘控制3D场景漫游 2006-12-13 19:00 kelland

看到你的3D键盘控制真是太好了!我有鼠标控制 真好缺这个键盘控制呢
有机会的话可以聊聊 QQ4603988  回复  更多评论   

# re: [引] 键盘控制3D场景漫游 2006-12-13 19:20 kelland

晕~键盘没视角切换的啊!  回复  更多评论   

# re: [引] 键盘控制3D场景漫游 2006-12-13 19:24 kelland

#if !defined(AFX_CAMERA_H)
#define AFX_CAMERA_H

#include "d3dx9.h"
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
//-------------------------------------------------------------------
//摄像机类,主要用于控制,更新2D,3D视图变换矩阵,投影变换矩阵
//实现计算鼠标指针射线(从摄像机开始穿过鼠标指针的一条3D空间的射线)
//-------------------------------------------------------------------
class CCamera
{
public:
CCamera(LPDIRECT3DDEVICE9 pDevice,
LPD3DXVECTOR3 pos);
virtual ~CCamera();
void YawPitchAt(float yaw,float pitch);
void YawPitchPos(float yaw,float pitch);
void Update3DMatrix();
void Update2DMatrix();
void AimTo(D3DVECTOR *pLookAt);
//获得观察点坐标
void GetLookAt(D3DVECTOR *pLookAt)
{
pLookAt->x= m_vPos.x+m_Distance*cosf(m_Pitch)*cosf(m_Yaw);
pLookAt->y= m_vPos.y+m_Distance*sinf(m_Pitch);
pLookAt->z= m_vPos.z+m_Distance*cosf(m_Pitch)*sinf(m_Yaw);

};

//获得摄像机坐标
D3DVECTOR* GetPos()
{
return &m_vPos;
}
//获得摄像机坐标
void GetPos(D3DVECTOR *vPos)
{ vPos->x=m_vPos.x;
vPos->y=m_vPos.y;
vPos->z=m_vPos.z;
};
//获得方向向量(单位向量)
void GetDirection(D3DVECTOR *vDir)
{
vDir->x=cosf(m_Pitch)*cosf(m_Yaw);
vDir->y=sinf(m_Pitch);
vDir->z=cosf(m_Pitch)*sinf(m_Yaw);
};
//-----------------------------------------------------------------
//根据鼠标坐标,计算射线
//实现计算鼠标指针射线(从摄像机开始穿过鼠标指针的一条3D空间的射线)
//-----------------------------------------------------------------
void GetCursorRayDir(POINT ptCursor,D3DVECTOR *vPickRayDir)
{
D3DXMATRIXA16 matProj;
D3DXMatrixPerspectiveFovLH(&matProj,D3DX_PI/4,4/3.0f,1.0f,6000.0f);
//计算屏幕空间的坐标(-1,-1)~(1,1)
D3DXVECTOR3 v;
v.x = ( (-1+2* ptCursor.x /float( m_scrWidth) ) /*- 1*/ ) / matProj._11;
v.y = ( ( 1-2* ptCursor.y /float( m_scrHeight)) /*- 1*/ ) / matProj._22;
v.z = 1.0f;

//获得视图变换矩阵的逆矩阵
D3DVECTOR vLookAt;
GetLookAt(&vLookAt);
D3DXMATRIXA16 matView, m;
D3DXMatrixLookAtLH(&matView,(D3DXVECTOR3*)&m_vPos,
(D3DXVECTOR3*)&vLookAt,&D3DXVECTOR3(0,1,0));

D3DXMatrixInverse( &m, NULL, &matView );

//把上述坐标转换成世界坐标
vPickRayDir->x = v.x*m._11 + v.y*m._21 + v.z*m._31;
vPickRayDir->y = v.x*m._12 + v.y*m._22 + v.z*m._32;
vPickRayDir->z = v.x*m._13 + v.y*m._23 + v.z*m._33;
};

//移动焦点坐标(实质上是移动摄像机)
void MoveAtTo(D3DXVECTOR3 *vLookAt)
{

m_vPos.x=vLookAt->x-m_Distance*cosf(m_Pitch)*cosf(m_Yaw);
m_vPos.y=vLookAt->y-m_Distance*sinf(m_Pitch);
m_vPos.z=vLookAt->z-m_Distance*cosf(m_Pitch)*sinf(m_Yaw);


}
//移动摄像机
void MovePosTo(D3DXVECTOR3 *pV)
{
m_vPos=*pV;
}

//返回屏幕高度,宽度
long GetScreenHeight() {return m_scrHeight ;};
long GetScreenWidth() {return m_scrWidth;};

//移动摄像机,在摄像机空间,也就是沿着摄像机朝向前后移动,和侧向左右移动
void Move(float dSide,float dForward);


protected:

float m_Yaw,m_Pitch;
float m_Distance;
long m_scrWidth;
long m_scrHeight;

D3DXVECTOR3 m_vPos;
LPDIRECT3DDEVICE9 m_pDevice;
public:
D3DXMATRIX matView;
D3DXMATRIX matProjection;
D3DXMATRIX matIdentity;
D3DXMATRIX matOrtho;
//摄像机从m_vPos观察,方向为:从m_vPos水平偏角为yaw,仰角为pitch
};

#endif // !defined(AFX_CAMERA_H)  回复  更多评论   



只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


My Links

Blog Stats

常用链接

留言簿(3)

随笔分类(47)

随笔档案(45)

文章分类(87)

文章档案(87)

相册

C++

Database

Game Develope & Game Engine

Java

News

Web

最新随笔

搜索

最新评论

阅读排行榜

评论排行榜