首先,我们封装正方体类的时候要考虑一个正方体呈现在我们面前需要一些什么东西然后开始动手
1)一个正方体有8个顶点(这是必备条件不考虑如何绘制的情况下8个顶点)
2)有了顶点我们需要保存这8个顶点以便后面使用(保存数据是需要顶点缓冲区)
3)要将正方体展现出来需要的变换
4)最后一部绘制正方形
这是我想的4个步骤,有了四个步骤之后要划分每个步骤之后明白每个步骤在类中称当什么角色:
1)首先8个顶点毫无疑问应该属于正方体的数据成员;而在DirectX中顶点需要定义顶点结构和灵活顶点格式。
2)后面3个步骤要对数据进行一些处理,处理数据成员便写成成员函数。
有了上面的分析就只用码代码了,代码如下:
一、将上面写的数据成员和成员函数插入类中 `
#pragma once
#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"winmm.lib")
#pragma comment(lib,"d3dx9.lib")
#include"Camera.h"
//顶点结构
struct CUSTOMVERTEX
{
FLOAT x, y, z;
DWORD color;
};
//灵活顶点格式
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)
class CCube
{
private:
LPDIRECT3D9 g_pD3D;
LPDIRECT3DDEVICE9 g_pd3dDevice;
//正方体顶点
CUSTOMVERTEX g_Vertices[18];
//顶点缓冲区
LPDIRECT3DVERTEXBUFFER9 g_pVB;
public:
//构造函数
CCube();
//析构函数
~CCube();
//保存顶点的成员函数
HRESULT InitGeometry();
//3大变换
VOID SetupMatrices();
//绘制图形
VOID Render();
};
之所以用18个顶点是因为用三角形带去绘制的时候10个点绘制4个面,上下两个面分别用4个顶点绘制所以一共18个点
还可以定义一个带参的构造函数来接收你要画的正方体坐标,这样你可以根据你的喜好来绘制正方体(建议以原点为正方体中心)
二、完善类中的成员函数
1)HRESULT InitGeometry();
HRESULT CCube::InitGeometry() {
//为了节省时间我直接将18个点放在这里 你们可以将它放在构造函数中
CUSTOMVERTEX g_Vertices[] =
{
{ -1.0f, -1.0f, -1.0f, 0xffff0000, },
{ -1.0f, 1.0f, -1.0f, 0xff0000ff, },
{ 1.0f, -1.0f, -1.0f, 0xffffffff, },
{ 1.0f, 1.0f, -1.0f, 0xffff0000, },
{ 1.0f, -1.0f, 1.0f, 0xff0000ff, },
{ 1.0f, 1.0f, 1.0f, 0xffffffff, },
{ -1.0f, -1.0f, 1.0f, 0xffff0000, },
{ -1.0f, 1.0f, 1.0f, 0xff0000ff, },
{ -1.0f, -1.0f, -1.0f, 0xffff0000, },
{ -1.0f, 1.0f, -1.0f, 0xff0000ff, },
{ -1.0f, 1.0f, -1.0f, 0xff0000ff, },
{ -1.0f, 1.0f, 1.0f, 0xff0000ff, },
{ 1.0f, 1.0f, -1.0f, 0xffff0000, },
{ 1.0f, 1.0f, 1.0f, 0xffffffff, },
{ -1.0f, -1.0f, -1.0f, 0xffff0000, },
{ -1.0f, -1.0f, 1.0f, 0xffff0000, },
{ 1.0f, -1.0f, -1.0f, 0xffffffff, },
{ 1.0f, -1.0f, 1.0f, 0xff0000ff, },
};
//将18个点保存在顶点缓存区
if (FAILED(g_pd3dDevice->CreateVertexBuffer(18 * sizeof(CUSTOMVERTEX),
0, D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT, &g_pVB, NULL)))
{
return E_FAIL;
}
VOID* pVertices;
//加锁
if (FAILED(g_pVB->Lock(0, sizeof(g_Vertices), (void**)&pVertices, 0)))
return E_FAIL;
//内存拷贝
memcpy(pVertices, g_Vertices, sizeof(g_Vertices));
//解锁
g_pVB->Unlock();
return S_OK;
}
2)VOID SetupMatrices();
VOID CCube::SetupMatrices()
{
//定义一个世界变换的矩阵
D3DXMATRIXA16 matWorld;
//平移变换
D3DXMatrixTranslation(&matWorld, 0, 0, 0);
//设置世界变换矩阵
g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
D3DXVECTOR3 vEyePt( 5.0f, 5.0f,-5.0f );//摄像机的位置
D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );//摄像机的朝向的点
D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );//摄像机的上方向
D3DXMATRIXA16 matView;
D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
//设置视图变换矩阵
g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
//定义一个投影变换矩阵
D3DXMATRIXA16 matProj;
D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f );
//设置投影变换
g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
}
这里我建议可以写两个函数一个是平移一个是旋转,这样你定义二个正方体是可以通过平移旋转将第一个移动开这样不会使得正方体重合
3) VOID Render();
VOID CCube::Render() {
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
{
//设置三大变换
SetupMatrices();
//设置资源流
g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );
//设置灵活顶点格式
g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
//绘制基本图元
//绘制周围四个正方形
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 8)
//绘制上面的图形
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 10, 2)
//绘制下面图形
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 14, 2)
g_pd3dDevice->EndScene();
}
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}
这样一个正方体的类就封装好了,这是我的思路有更好的欢迎投稿;