DXUT扩展之摄像机

最近需要用DXUT写一个球形环境映射,需要用到摄像机,然而原来的三步曲没有涉及到摄像机,所以这里专门补充下摄像机的用法

 

/*------------------------------------------------------------
	chap15_camera_dx9.cpp -- learn how to use camera
			(c) Seamanj.2013/7/21
------------------------------------------------------------*/
//phase1 : add camera
//phase2 : add teapot
//phase3 : add sphere environment mapping shader
#include "DXUT.h"
#include "resource.h"

#define phase1 1
#define phase2 1
#if phase1 1
#include "DXUTcamera.h"
LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL;
CModelViewerCamera g_Camera;


#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE)

#endif
#if phase2 1
ID3DXMesh* pTeapotMesh = 0;
#endif
//--------------------------------------------------------------------------------------
// Rejects any D3D9 devices that aren't acceptable to the app by returning false
//--------------------------------------------------------------------------------------
bool CALLBACK IsD3D9DeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat,
                                      bool bWindowed, void* pUserContext )
{
    // Typically want to skip back buffer formats that don't support alpha blending
    IDirect3D9* pD3D = DXUTGetD3D9Object();
    if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
                                         AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING,
                                         D3DRTYPE_TEXTURE, BackBufferFormat ) ) )
        return false;

    return true;
}


//--------------------------------------------------------------------------------------
// Before a device is created, modify the device settings as needed
//--------------------------------------------------------------------------------------
bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void* pUserContext )
{
#if phase1 
	pDeviceSettings->d3d9.pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
#endif
	
    return true;
}


//--------------------------------------------------------------------------------------
// Create any D3D9 resources that will live through a device reset (D3DPOOL_MANAGED)
// and aren't tied to the back buffer size
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnD3D9CreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
                                     void* pUserContext )
{
#if phase1
// Setup the camera's view parameters    
D3DXVECTOR3 vecEye( 0.0f, 0.0f, -5.0f );  
	D3DXVECTOR3 vecAt ( 0.0f, 0.0f, -0.0f );  
	g_Camera.SetViewParams( &vecEye, &vecAt );  
	FLOAT fObjectRadius=1;  
	//摄像机缩放的3个参数
	g_Camera.SetRadius( fObjectRadius * 3.0f, fObjectRadius * 0.5f, fObjectRadius * 10.0f );
	g_Camera.SetEnablePositionMovement( true );
#endif
#if phase2
	D3DXCreateTeapot( pd3dDevice, &pTeapotMesh, 0);
#endif
    return S_OK;
}

#if phase1
struct CUSTOMVERTEX
{
	FLOAT x, y, z;
	DWORD color;
};
static HRESULT initVertexBuffer(IDirect3DDevice9* pd3dDevice)
{
	// Create and initialize vertex buffer
	CUSTOMVERTEX vertices[] =
	{
		{ -1.0f, 0.0f, 1.0f, 0xffff0000 },
		{ 1.0f, 0.0f, 1.0f, 0xff00ff00 },	
		{ 0.0f, 1.0f, 1.0f, 0xff0000ff }
	};
  if ( FAILED( pd3dDevice->CreateVertexBuffer( 3 * sizeof( CUSTOMVERTEX ), 0, D3DFVF_CUSTOMVERTEX,
		D3DPOOL_DEFAULT, &g_pVB, NULL ))) 
  {
    return E_FAIL;
  }

  void* pVertices;
  if (FAILED(g_pVB->Lock(0, 0, /* map entire buffer */
                                  &pVertices, 0))) {
    return E_FAIL;
  }
  memcpy(pVertices, vertices, sizeof(vertices));
  g_pVB->Unlock();
  return S_OK;
}
#endif
//--------------------------------------------------------------------------------------
// Create any D3D9 resources that won't live through a device reset (D3DPOOL_DEFAULT) 
// or that are tied to the back buffer size 
//--------------------------------------------------------------------------------------


HRESULT CALLBACK OnD3D9ResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
                                    void* pUserContext )
{
#if phase1
	pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );  
	//关闭光照处理, 默认情况下启用光照处理   
	pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );  
//Setup the camera's projection parameters   
	float fAspectRatio = pBackBufferSurfaceDesc->Width / ( FLOAT )pBackBufferSurfaceDesc->Height;  
	  
	g_Camera.SetProjParams( D3DX_PI / 2, fAspectRatio, 0.1f, 5000.0f );  
	g_Camera.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height );  
	g_Camera.SetButtonMasks( MOUSE_LEFT_BUTTON, MOUSE_WHEEL, MOUSE_RIGHT_BUTTON ); 
	
    return initVertexBuffer(pd3dDevice);
#endif
}


//--------------------------------------------------------------------------------------
// Handle updates to the scene.  This is called regardless of which D3D API is used
//--------------------------------------------------------------------------------------
void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void* pUserContext )
{
#if phase1
	g_Camera.FrameMove( fElapsedTime );
#endif
}


//--------------------------------------------------------------------------------------
// Render the scene using the D3D9 device
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D9FrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
{
    HRESULT hr;

    // Clear the render target and the zbuffer 
    V( pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB( 0, 45, 50, 170 ), 1.0f, 0 ) );




    // Render the scene
    if( SUCCEEDED( pd3dDevice->BeginScene() ) )
    {

#if phase2
		// Set world matrix   
	D3DXMATRIX world = *g_Camera.GetWorldMatrix() ;  
	//这里将Model矩阵设为摄机像的Model矩阵,那么以后画的东西都是摄相机为准了,东西都跟摄相机跑了,在世界坐标系中一起
	//移动,所以看起来,东西都没有动一样,所有为了将不同的物体放到不同的位置,需要对每个物体设置各自的Model矩阵,让它
	//们摆到合适的世界坐标系中.
	//注意ASDW移动的是摄像机,用左键转动摄像机时,转动的是摄像机的Model矩阵(在LookAt点处的Model矩阵),所以这里只有茶壶动,
	//而三角形不动,即摄像机在世界坐标系中的位置和朝向没有发生变化,只有以摄像机的Model矩阵为自己的Model矩阵的东西才会旋转,
	//注意摄像机的View矩阵(eye,up,lookat建立起来的矩阵)与摄像机的Model矩阵(LookAt处+记录Model旋转得到的矩阵)没有任何关系,
	//用右键转动摄像机时,转动的是摄像机的View矩阵,这个时候摄像机是围着LookAt点进行旋转的,当然旋转也是被记录了的.
	pd3dDevice->SetTransform(D3DTS_WORLD, &world) ;  
	pTeapotMesh->DrawSubset( 0 );
#endif
	#if phase1
	pd3dDevice->SetRenderState( D3DRS_AMBIENT, D3DCOLOR(0xffffffff) );
	// Set world matrix  
	D3DXMATRIX M;
	D3DXMatrixIdentity( &M ); // M = identity matrix
	pd3dDevice->SetTransform(D3DTS_WORLD, &M) ; 
	//这里将Model矩阵设为单位矩阵,说明以后画的东西是以世界坐标系为准的,不会随摄相机移动而跟着移动
	// Set view matrix   
	D3DXMATRIX view  = *g_Camera.GetViewMatrix() ;  
	pd3dDevice->SetTransform(D3DTS_VIEW, &view) ;  
	// Set projection matrix   
	D3DXMATRIX proj  = *g_Camera.GetProjMatrix() ;  
	pd3dDevice->SetTransform(D3DTS_PROJECTION, &proj) ;  


#endif
	#if phase1
	pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) );
	pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
	pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 );
#endif 
        V( pd3dDevice->EndScene() );
    }
}


//--------------------------------------------------------------------------------------
// Handle messages to the application 
//--------------------------------------------------------------------------------------
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
                          bool* pbNoFurtherProcessing, void* pUserContext )
{
#if phase1
	g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam );
#endif
    return 0;
}


//--------------------------------------------------------------------------------------
// Release D3D9 resources created in the OnD3D9ResetDevice callback 
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D9LostDevice( void* pUserContext )
{
#if phase1
	SAFE_RELEASE(g_pVB);
#endif
}


//--------------------------------------------------------------------------------------
// Release D3D9 resources created in the OnD3D9CreateDevice callback 
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D9DestroyDevice( void* pUserContext )
{
#if phase2
	SAFE_RELEASE(pTeapotMesh);
#endif
}


//--------------------------------------------------------------------------------------
// Initialize everything and go into a render loop
//--------------------------------------------------------------------------------------
INT WINAPI wWinMain( HINSTANCE, HINSTANCE, LPWSTR, int )
{
    // Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
    _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif

    // Set the callback functions
    DXUTSetCallbackD3D9DeviceAcceptable( IsD3D9DeviceAcceptable );
    DXUTSetCallbackD3D9DeviceCreated( OnD3D9CreateDevice );
    DXUTSetCallbackD3D9DeviceReset( OnD3D9ResetDevice );
    DXUTSetCallbackD3D9FrameRender( OnD3D9FrameRender );
    DXUTSetCallbackD3D9DeviceLost( OnD3D9LostDevice );
    DXUTSetCallbackD3D9DeviceDestroyed( OnD3D9DestroyDevice );
    DXUTSetCallbackDeviceChanging( ModifyDeviceSettings );
    DXUTSetCallbackMsgProc( MsgProc );
    DXUTSetCallbackFrameMove( OnFrameMove );

    // TODO: Perform any application-level initialization here

    // Initialize DXUT and create the desired Win32 window and Direct3D device for the application
    DXUTInit( true, true ); // Parse the command line and show msgboxes
    DXUTSetHotkeyHandling( true, true, true );  // handle the default hotkeys
    DXUTSetCursorSettings( true, true ); // Show the cursor and clip it when in full screen
    DXUTCreateWindow( L"chap15_camera_dx9" );
    DXUTCreateDevice( true, 640, 480 );

    // Start the render loop
    DXUTMainLoop();

    // TODO: Perform any application-level cleanup here

    return DXUTGetExitCode();
}


运行结果如下:

无论如何按wasd茶壶看起来都没有动,只有三角形像背景一样的在动!因为三角形的Model矩阵为单位矩阵,那么它就固定在世界坐标系中了,

而茶壶是以摄像机的Model矩阵为自己的矩阵,这样茶壶总是处理摄像机的LookAt位置,并且它的旋转是被记录的.左键的旋转记录为LookAt

处的旋转,从而改变了摄像机的Model矩阵,而右键的旋转记录为Eye绕LookAt点处的旋转,从而改变了摄像机的View矩阵

 

好了,球形环境映射的所有基础都打好了,明天可以开始动工了!


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值