|
|

楼主 |
发表于 2006-12-27 01:17:00
|
显示全部楼层
Re: Re: 请教一个入门问题:绘制的图形为什么会随着窗口
代码如下:
// D3DTest3.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "D3DTest3.h"
#include <d3d9.h>
#include <d3dx9.h>
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
HWND hWnd;
LPDIRECT3D9 m_pD3D;
LPDIRECT3DDEVICE9 m_pDevice;
LPDIRECT3DVERTEXBUFFER9 m_pVB; //顶点缓存区的的接口指针
int m_nRotateY; //实体的旋转角度(单位:度)
LPDIRECT3DINDEXBUFFER9 m_pIB1; //索引缓存区的接口指针
LPDIRECT3DINDEXBUFFER9 m_pIB2; //索引缓存区的接口指针
//定义FVF的顶点结构
struct CUSTOMVERTEX
{
float x, y, z; //顶点坐标
DWORD color; //顶点颜色
};
//定义FVF用到的数据项:坐标 颜色
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE)
void InitD3D(void);
void Render(void);
void Cleanup(void);
void InitGeometry(void);
void SetupMatrices(void);
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_D3DTEST3, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
m_nRotateY = 0;
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_D3DTEST3));
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
//释放接口
Cleanup();
return (int) msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage are only necessary if you want this code
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
// function that was added to Windows 95. It is important to call this function
// so that the application will get 'well formed' small icons associated
// with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_D3DTEST3));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_D3DTEST3);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
//初始化Direct3D
InitD3D();
//建模
InitGeometry();
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case ID_Y_START:
SetTimer(hWnd, 1, 40, NULL);
break;
case ID_Y_END:
KillTimer(hWnd, 1);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
Render();
EndPaint(hWnd, &ps);
break;
case WM_TIMER:
m_nRotateY+=1;
SendMessage(hWnd, WM_PAINT, NULL, NULL);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
void InitD3D(void)
{
//创建Direct3D对象,并获取接口IDirect3D9的指针,
//我们将通过该指针操作Direct3D对象。
m_pD3D = : irect3DCreate9(D3D_SDK_VERSION);
D3DPRESENT_PARAMETERS d3dpp;
::ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE; //创建窗口模式的Direct3D程序
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16; //生成16 bit的Z缓存
//调用方法IDirect3D9::CreateDevice创建设备对象,并获取
//接口IDirect3DDevice9的指针,我们将通过该指针操作设备对象
m_pD3D->CreateDevice(
D3DADAPTER_DEFAULT, //使用缺省的显卡
D3DDEVTYPE_HAL, //指定设备类型为HAL
hWnd, //Direct3D窗口的句柄
D3DCREATE_SOFTWARE_VERTEXPROCESSING,//软件顶点处理
&d3dpp, &m_pDevice);
//因为使用顶点颜色渲染,所以要禁用光照处理
m_pDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
//关闭“挑选”功能,允许渲染背面
// m_pDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
//启用Z缓存,允许消隐处理
m_pDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE );
}
void Render(void)
{
//用指定颜色清除后备缓存区
m_pDevice->Clear(
0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
D3DCOLOR_XRGB(0,0,255), //指定使用蓝色
1.0f, 0);
//Direct3D规定在渲染前必须调用方法IDirect3DDevice9::BeginScene,
//结束时要调用IDirect3DDevice9::EndScene。
m_pDevice->BeginScene();
//实际的渲染代码放在此处。因为本节只是为了演示如何初始化Direct3D,
//所以这里为空,生成的Direct3D窗口将是一个蓝色背景的空白窗口
SetupMatrices(); //设置变换矩阵
//绑定顶点缓存区至设备数据源
m_pDevice->SetStreamSource( 0, m_pVB, 0, sizeof(CUSTOMVERTEX) );
//设置自定义的FVF
m_pDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
//绑定索引缓存区
m_pDevice->SetIndices( m_pIB2 );
m_pDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE );
//从索引缓存区绘制图元,参数1为图元格式,参数4为顶点数,参数6为三角形数
m_pDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12 );
SetupMatrices(); //设置变换矩阵
//设置自定义的FVF
m_pDevice->SetFVF( D3DFVF_XYZ );
//绑定索引缓存区
m_pDevice->SetIndices( m_pIB1 );
m_pDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE );
//从索引缓存区绘制图元,参数1为图元格式,参数4为顶点数,参数6为三角形数
m_pDevice->DrawIndexedPrimitive( D3DPT_LINELIST, 0, 0, 8, 0, 12 );
m_pDevice->EndScene();
//交换当前/后备缓存区,刷新窗口
m_pDevice-> resent(NULL, NULL, NULL, NULL);
}
void Cleanup(void)
{
m_pIB1->Release();
m_pIB2->Release();
m_pVB->Release();
m_pDevice->Release();
m_pD3D->Release();
}
void InitGeometry(void)
{
CUSTOMVERTEX vertices[] = //FVF顶点数据
{
{ -1.0f, 1.0f, -1.0f, D3DCOLOR_XRGB(0,0,0) }, //点A,绿色
{ 1.0f, 1.0f, -1.0f, D3DCOLOR_XRGB(0,0,0) }, //点B,红色
{ 1.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(0,0,0) }, //点C,浅蓝
{ -1.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(0,0,0) }, //点D,粉红
{ -1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB(0,0,0) }, //点A,绿色
{ 1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB(0,0,0) }, //点B,红色
{ 1.0f, -1.0f, 1.0f, D3DCOLOR_XRGB(0,0,0) }, //点C,浅蓝
{ -1.0f, -1.0f, 1.0f, D3DCOLOR_XRGB(0,0,0) } //点D,粉红
};
WORD indicesline[] = { 0, 1, 0, 3, 0, 4,
2, 1, 2, 3, 2, 6,
5, 1, 5, 4, 5, 6,
7, 4, 7, 3, 7, 6
}; //索引序列
WORD indicesTri[] = { 0, 3, 1, 1, 3, 2,
1, 2, 5, 5, 2, 6,
0, 1, 4, 4, 1, 5,
3, 0, 4, 3, 4, 7,
2, 3, 6, 6, 3, 7,
4, 5, 7, 5, 6, 7
}; //索引序列
//创建顶点缓存区,并获取接口IDirect3DVertexBuffer9的指针
m_pDevice->CreateVertexBuffer(
sizeof(vertices), //缓存区尺寸
0, D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT, &m_pVB, NULL );
//把顶点数据填入顶点缓存区
void* pVertices;
m_pVB->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 );
memcpy( pVertices, vertices, sizeof(vertices) );
m_pVB->Unlock();
//创建索引缓存区,并获取接口LPDIRECT3DINDEXBUFFER9的指针
m_pDevice->CreateIndexBuffer(
sizeof(indicesline), //缓存区尺寸
0, D3DFMT_INDEX16, //使用16 bit的索引值
D3DPOOL_DEFAULT, &m_pIB1, NULL );
//把索引值填入索引缓存区
void *pIndices1;
m_pIB1->Lock( 0, sizeof(indicesline), (void**)&pIndices1, 0 );
memcpy( pIndices1, indicesline, sizeof(indicesline) );
m_pIB1->Unlock();
//创建索引缓存区,并获取接口LPDIRECT3DINDEXBUFFER9的指针
m_pDevice->CreateIndexBuffer(
sizeof(indicesTri), //缓存区尺寸
0, D3DFMT_INDEX16, //使用16 bit的索引值
D3DPOOL_DEFAULT, &m_pIB2, NULL );
//把索引值填入索引缓存区
void *pIndices2;
m_pIB2->Lock( 0, sizeof(indicesTri), (void**)&pIndices2, 0 );
memcpy( pIndices2, indicesTri, sizeof(indicesTri) );
m_pIB2->Unlock();
}
void SetupMatrices(void)
{
float angle = m_nRotateY * D3DX_PI / 180; //把旋转角换算成弧度
D3DXMATRIX matWorld;
//计算世界变换矩阵
::D3DXMatrixRotationY( &matWorld, angle );
//把世界变换矩阵设置到渲染环境
m_pDevice->SetTransform( D3DTS_WORLD, &matWorld );
D3DXVECTOR3 eye( 0.0f, 3.0f,-5.0f ); //观察点
D3DXVECTOR3 lookat( 0.0f, 0.0f, 0.0f ); //视线目标点
D3DXVECTOR3 up( 0.0f, 1.0f, 0.0f ); //上方向
D3DXMATRIX matView;
//计算视角变换矩阵
::D3DXMatrixLookAtLH( &matView, &eye, &lookat, &up );
//把视角变换矩阵设置到渲染环境
m_pDevice->SetTransform( D3DTS_VIEW, &matView );
D3DXMATRIXA16 matProj;
//计算透视投影变换矩阵
::D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f );
//把投影变换矩阵设置到渲染环境
m_pDevice->SetTransform( D3DTS_PROJECTION, &matProj );
}
|
|