本篇是创建游戏内核(10)【OO改良版】的续篇,关于该内核的细节说明请参阅创建游戏内核(11)。
接口:
DWORD get_vertices_size(LPDIRECT3DVERTEXBUFFER9 vertex_buffer);
DWORD get_num_bytes_per_vertex(LPDIRECT3DVERTEXBUFFER9 vertex_buffer);
DWORD get_vertex_fvf(LPDIRECT3DVERTEXBUFFER9 vertex_buffer);
DWORD get_num_vertices(LPDIRECT3DVERTEXBUFFER9 vertex_buffer);
//================================================================================
// Defines for class VERTEX_BUFFER.
//================================================================================
class VERTEX_BUFFER
{
public:
VERTEX_BUFFER();
~VERTEX_BUFFER();
IDirect3DVertexBuffer9* get_vertex_buffer();
DWORD get_vertices_size();
DWORD get_num_bytes_per_vertex();
DWORD get_vertex_fvf();
DWORD get_num_vertices();
BOOL create(DWORD num_vertices, DWORD num_bytes_per_vertex, DWORD fvf);
void free();
BOOL is_loaded();
BOOL fill_in(DWORD first_vertex, DWORD num_vertices, void* vertex_list);
BOOL render(DWORD first_vertex, DWORD num_primitives, DWORD type);
BOOL lock(DWORD first_vertex = 0, DWORD num_vertices = 0);
BOOL unlock();
void* get_ptr();
private:
IDirect3DVertexBuffer9* m_vertex_buffer; // pointer to Direct3D vertex buffer object
char* m_ptr; // pointer to vertex data buffer
};
typedef VERTEX_BUFFER* VERTEX_BUFFER_PTR;
实现:
//---------------------------------------------------------------------------
// Return the total size of vertices.
//---------------------------------------------------------------------------
DWORD get_vertices_size(LPDIRECT3DVERTEXBUFFER9 vertex_buffer)
{
D3DVERTEXBUFFER_DESC _buffer_desc;
vertex_buffer->GetDesc(&_buffer_desc);
return _buffer_desc.Size;
}
//---------------------------------------------------------------------------
// Return the size of a vertex for a flexible vertex format (FVF)
//---------------------------------------------------------------------------
DWORD get_num_bytes_per_vertex(LPDIRECT3DVERTEXBUFFER9 vertex_buffer)
{
D3DVERTEXBUFFER_DESC _buffer_desc;
vertex_buffer->GetDesc(&_buffer_desc);
return D3DXGetFVFVertexSize(_buffer_desc.FVF);
}
//---------------------------------------------------------------------------
// Return vertex flexible format.
//---------------------------------------------------------------------------
DWORD get_vertex_fvf(LPDIRECT3DVERTEXBUFFER9 vertex_buffer)
{
D3DVERTEXBUFFER_DESC _buffer_desc;
vertex_buffer->GetDesc(&_buffer_desc);
return _buffer_desc.FVF;
}
//---------------------------------------------------------------------------
// Return the number of vertices.
//---------------------------------------------------------------------------
DWORD get_num_vertices(LPDIRECT3DVERTEXBUFFER9 vertex_buffer)
{
D3DVERTEXBUFFER_DESC _buffer_desc;
vertex_buffer->GetDesc(&_buffer_desc);
return _buffer_desc.Size / D3DXGetFVFVertexSize(_buffer_desc.FVF);
}
//---------------------------------------------------------------------------
// Constructor, initialize data member.
//---------------------------------------------------------------------------
VERTEX_BUFFER::VERTEX_BUFFER()
{
memset(this, 0, sizeof(*this));
}
//---------------------------------------------------------------------------
// Destructor, free vertex buffer resource.
//---------------------------------------------------------------------------
VERTEX_BUFFER::~VERTEX_BUFFER()
{
free();
}
//---------------------------------------------------------------------------
// Get pointer to vetex buffer.
//---------------------------------------------------------------------------
IDirect3DVertexBuffer9* VERTEX_BUFFER::get_vertex_buffer()
{
return m_vertex_buffer;
}
//---------------------------------------------------------------------------
// Return the total size of vertices.
//---------------------------------------------------------------------------
DWORD VERTEX_BUFFER::get_vertices_size()
{
return ::get_vertices_size(m_vertex_buffer);
}
//---------------------------------------------------------------------------
// Gets the size of a vertex for a flexible vertex format (FVF)
//---------------------------------------------------------------------------
DWORD VERTEX_BUFFER::get_num_bytes_per_vertex()
{
return ::get_num_bytes_per_vertex(m_vertex_buffer);
}
//---------------------------------------------------------------------------
// Get flexible vertex format.
//---------------------------------------------------------------------------
DWORD VERTEX_BUFFER::get_vertex_fvf()
{
return ::get_vertex_fvf(m_vertex_buffer);
}
//---------------------------------------------------------------------------
// Get number of vertex.
//---------------------------------------------------------------------------
DWORD VERTEX_BUFFER::get_num_vertices()
{
return ::get_num_vertices(m_vertex_buffer);
}
//---------------------------------------------------------------------------
// create vertex buffer.
//---------------------------------------------------------------------------
BOOL VERTEX_BUFFER::create(DWORD num_vertices, DWORD num_bytes_per_vertex, DWORD fvf)
{
// free vertex buffer resource first
free();
// Check condition
if(g_d3d_device == NULL)
return FALSE;
if(num_vertices == 0 || num_bytes_per_vertex == 0 || fvf == 0)
return FALSE;
// create vertex buffer now
if(FAILED(g_d3d_device->CreateVertexBuffer(
num_vertices * num_bytes_per_vertex, 0, fvf, D3DPOOL_MANAGED, &m_vertex_buffer, NULL)))
return FALSE;
return TRUE;
}
//---------------------------------------------------------------------------
// free vertex buffer resource, reset data member.
//---------------------------------------------------------------------------
void VERTEX_BUFFER::free()
{
release_com(m_vertex_buffer);
}
//---------------------------------------------------------------------------
// copy vertex data from VertexList to vertex buffer.
//---------------------------------------------------------------------------
BOOL VERTEX_BUFFER::fill_in(DWORD first_vertex, DWORD num_vertices, void* vertex_list)
{
// check condition
if(vertex_list == NULL || m_vertex_buffer == NULL)
return FALSE;
// lock the vertex buffer
if(! lock(first_vertex, num_vertices))
return FALSE;
// copy vertices to vertex buffer
memcpy(m_ptr, vertex_list, num_vertices * get_num_bytes_per_vertex());
// unlock vertex buffer
return unlock();
}
//---------------------------------------------------------------------------
// render vertex buffer into display.
//---------------------------------------------------------------------------
BOOL VERTEX_BUFFER::render(unsigned long first_vertex, unsigned long num_primitives, DWORD type)
{
if(g_d3d_device == NULL || m_vertex_buffer == NULL)
return FALSE;
// binds a vertex buffer to a device data stream
g_d3d_device->SetStreamSource(0, m_vertex_buffer, 0, get_num_bytes_per_vertex());
// sets the current vertex stream declaration
g_d3d_device->SetFVF(get_vertex_fvf());
// Renders a sequence of nonindexed, geometric primitives of the specified type from the current set
// of data input streams.
g_d3d_device->DrawPrimitive((D3DPRIMITIVETYPE) type, first_vertex, num_primitives);
return TRUE;
}
//---------------------------------------------------------------------------
// lock vertex buffer from specified position with specified length.
//---------------------------------------------------------------------------
BOOL VERTEX_BUFFER::lock(DWORD first_vertex, DWORD num_vertices)
{
if(m_vertex_buffer == NULL)
return FALSE;
DWORD _num_bytes_per_vertex = get_num_bytes_per_vertex();
// locks a range of vertex data and obtains a pointer to the vertex buffer memory
if(FAILED(m_vertex_buffer->Lock(first_vertex * _num_bytes_per_vertex, num_vertices * _num_bytes_per_vertex,
(void**)&m_ptr, 0)))
return FALSE;
return TRUE;
}
//---------------------------------------------------------------------------
// unlock vertex buffer.
//---------------------------------------------------------------------------
BOOL VERTEX_BUFFER::unlock()
{
if(m_vertex_buffer == NULL)
return FALSE;
if(FAILED(m_vertex_buffer->Unlock()))
return FALSE;
return TRUE;
}
//---------------------------------------------------------------------------
// Check whether vertex buffer has created successfully.
//---------------------------------------------------------------------------
BOOL VERTEX_BUFFER::is_loaded()
{
return m_vertex_buffer ? TRUE : FALSE;
}
//---------------------------------------------------------------------------
// Ger pointer to vertex data.
//---------------------------------------------------------------------------
void* VERTEX_BUFFER::get_ptr()
{
return (void*)m_ptr;
}
测试代码:
/***********************************************************************************
PURPOSE:
Test D3D vertex buffer.
***********************************************************************************/
#include "core_common.h"
#include "core_framework.h"
#include "core_graphics.h"
// The 2D vertex format and descriptor
typedef struct
{
float x, y, z; // 2D coordinates
float rhw; // rhw
D3DCOLOR diffuse; // diffuse color component
} VERTEX;
#define VERTEX_FVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)
//===========================================================================
// Defines class APP which public inherits from class FRAMEWORK.
//===========================================================================
class APP : public FRAMEWORK
{
public:
BOOL init()
{
// initialize vertex data
VERTEX _verts[] = {
{ 100.0f, 100.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(0,64,128,255) },
{ 300.0f, 100.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(0,64,128,255) },
{ 100.0f, 300.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(0,64,128,255) },
{ 300.0f, 300.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(0,64,128,255) },
{ 50.0f, 150.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(128,0,0,128) },
{ 350.0f, 150.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(128,0,0,128) },
{ 50.0f, 350.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(128,0,0,128) },
{ 350.0f, 350.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(128,0,0,128) }
};
// Create Direct3D and Direct3DDevice object
if(! create_display(g_hwnd, get_client_width(g_hwnd), get_client_height(g_hwnd), 16, TRUE, FALSE))
return FALSE;
DWORD num_vertices = sizeof(_verts) / sizeof(VERTEX);
m_vertex_buffer.create(num_vertices, sizeof(VERTEX), VERTEX_FVF);
m_vertex_buffer.fill_in(0, num_vertices, _verts);
return TRUE;
}
BOOL frame()
{
clear_display_buffer(D3DCOLOR_RGBA(0, 0, 0, 255));
if(SUCCEEDED(g_d3d_device->BeginScene()))
{
enalbe_alpha_blending(FALSE, 0, 0);
m_vertex_buffer.render(0, 2, D3DPT_TRIANGLESTRIP);
enalbe_alpha_blending(TRUE, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
m_vertex_buffer.render(4, 2, D3DPT_TRIANGLESTRIP);
g_d3d_device->EndScene();
}
present_display();
return TRUE;
}
BOOL shutdown()
{
release_com(g_d3d_device);
release_com(g_d3d);
return TRUE;
}
private:
VERTEX_BUFFER m_vertex_buffer;
};
int PASCAL WinMain(HINSTANCE inst, HINSTANCE, LPSTR cmd_line, int cmd_show)
{
APP app;
if(! build_window(inst, "MainClass", "MainWindow", WS_OVERLAPPEDWINDOW, 0, 0, 640, 480))
return -1;
app.run();
return 0;
}