Xem mẫu

Beginning DirectX9

Dịch bởi TransTeam diễn đàn Gamedev.VN

CHƯƠNG 7

CHIA NHỎ VÀ LÀM MỊN
CÁC ĐỐI TƯỢNG

B

ạn đã học được cách làm thế nào để tạo các object 3D bằng code và biểu diễn nó
lên màn hình. Có lẽ bạn đang nghĩ rằng đây là một quá trình thật nhàm chán và
chưa có cách nào để có thể tạo tất cả các object bằng code. Bạn nghĩ rất đúng.
Hiện nay 3D đã nhập cuôc. Nó có thể mô tả mọi thứ trong game của bạn rất giống với
thực thể. Những mô hìnhcó thể thể hiện vật thể và đặc điểm xung quanh bạn và cũng có
thể là chính chính nó. Với những đặc điểm này bạn có thể đưa những mô hình này vào
game, bạn có thể biểu diễn nó với đối tượng Mesh và dịch chuyển hoặc điều khiển chúng.
Đây là các phần mà bạn sẽ học trong chương này:
ƒ Direct3D điều khiển mesh như thế nào ?
ƒ Cần những gì để hợp lý hóa một model 3D?
ƒ Định dạng file X là gì?
ƒ Làm thế nào để tạo và lưu giữ mesh?
ƒ Làm thế nào để load một model 3D vào game?

Xây dựng một thế giới 3D
Mô hình 3D giúp chúng bạn thể hiện thế giới ảo mà bạn muốn tạo. Những mô hình này
được bổ xung bởi gamer và đối thủ của gamer trong môi trường này. Những mô hình này
được lấy từ đâu? Nếu bạn có một package thiết kế 3D giống như Max hoặc Maya, bạn đã
có những công cụ cần thiết để tạo mọi thứ cho game của bạn khi cần. Nếu những chương
trình trên bạn không có thì bạn có thể dùng những package khác như MilkShape 3D, nó
cũng có thể làm việc tốt.
Sau khi đã tạo các model, bạn đưa chúng vào một trong những định dạng file 3D hiện có.
Nhưng bạn cần biết làm thế nào để load một file định dạng 3D vào game của mình. Mục
đích của cuốn sách này là giúp bạn làm việc với những định dạng file mà Microsoft đã
tạo ra.
Chú ý:
Bạn có thể tìm MilkShape 3D tại trang http://www.swissquake.ch/chumbalumsoft/index.html.

96

Beginning DirectX9

Dịch bởi TransTeam diễn đàn Gamedev.VN

Mesh là gì?
Code của bạn điều khiển những mô hình 3D được load vào trong game cũng được xem
như là một Mesh. Một Mesh là một code container mà chứa mọi thứ liên quan đến đối
tượng 3D. Nó bào gồm các vectơ, tọa độ texture và các dữ liệu khác. Bằng cách sử dụng
dữ liệu có trong mesh object bạn có thể biểu diễn các mô hình 3D lên màn hình .
Chú ý:
Thư viện tổng hợp D3DX chứa tất cả mọi thứ mà bạn cần để sử dụng mesh trong Direct3D

Direct3D định nghĩa một Mesh như thế nào?
Hầu hết các mesh trong Direct3D đều dựa trên ID3DXBaseMesh interface. Interface này
cung cấp kho dự trữ dành cho các model của bạn, giúp các methods có hiệu lực để tăng
tốc độ truy cập tới dữ liệu trong mesh. Ví dụ method GetVertexBuffer luôn sẵn có trong
ID3DXBaseMesh interface để giúp bạn truy cập trực tiếp tới vectơ buffer của đối tượng
mesh.
Dưới đây là một số kiểu Mesh khác nhau:
ƒ ID3DXMesh – Đây là dạng mesh interface chuẩn mà bạn sẽ sử dụng.
ƒ ID3DXPMesh – Interface này cho phép bạn sử dụng mesh tiến hành.
ƒ ID3DXSPMesh – interface này điều khiển sự đơn giản hóa các mesh object.
ƒ ID3DXPatchMesh - Interface này cung cấp Patch mesh theo chức năng.
Mỗi một kiểu mesh có thể lưu giữ tất cả các vectơ của một model trong vectơ buffer và
cung cấp cho bạn thông tin vể model, ví dụ như số phần tử hoặc là số vectơ.

Tạo Mesh
Bước đầu tiên khi sử dụng các mesh trong game đó là sự khởi tạo mesh object. Mesh
object là kho dự trữ, cất giữ tất cả các thông tin cần thiết dùn để mô tả model của bạn
trong Direct3D. Sau khi bạn đã tạo ra mesh, bạn dễ dàng copy tất cả thông tin mà model
của bạn cần.
Hai hàm trong Direct3D dùng để tạo mesh: D3DXCreaetMesh và D3DXCreateMeshFVF.
Vì mỗi hàm này tạo mesh bằng các cách khác nhau, chúng ta sẽ làm rõ cả hai hàm dưới đây.

D3DXCreateMesh
Giao diện ID3DXMesh là một giao diện đơn giản nhất trong mesh interface, dễ dàng tổ chức
và thực hiện một cách nhanh chóng. Trong phần này, bạn sẽ học cách làm thế nào để tạo
mesh trong ID3DXMesh interface bằng hàm D3DXCreateMesh.
D3DXCreateMesh(
DWORD NumFaces,
DWORD NumVertices,
DWORD Options,
CONST LPD3DVERTEXELEMENT9 *pDeclaration,
LPDIRECT3DDEVICE9 pDevice,
LPD3DXMESH *ppMesh
);

97

Beginning DirectX9

Dịch bởi TransTeam diễn đàn Gamedev.VN

Hàm D3DcreateMesh có 6 tham số:
ƒ NumFaces. Số phần tử mà mesh sẽ chứa.
ƒ NumVertices. Số vectơ mà mesh sẽ chứa.
ƒ Options. Giá trị từ bảng liệt kê D3DXMESH .
ƒ pDeclaration. Ma trận thuộc đối tượng D3DVERTEXELEMENT9. Những object
này mô tả FVF cho mesh.
ƒ pDevice. Một Direct3D device hợp lệ.
ƒ ppMesh. Con trỏ trỏ tới đối tượng ID3DMesh hợp lệ.
Đoạn code sau sẽ chỉ ra cách làm thế nào để tạo một đối tượng mesh mà chứa đầy đủ bộ
vectơ, dùng để tạo một khối lập phương.
HRESULT hr;
// biến giữ một mesh được tạo mới
LPD3DXMESH boxMesh;
// ma trận D3DVERTEXELEMENT9
D3DVERTEXELEMENT9 Declaration [MAX_FVF_DECL_SIZE];
// tạo khai báo cần thiết cho hàm D3DXCreateMesh
D3DXDeclaratorFromFVF (D3DFVF_CUSTOMVERTEX, Declaration);
hr= D3DXCreateMesh(12,
//số phần tử của mesh
8,
//số vectơ
D3DXMESH_MANAGED,
//sử dụng bộ nhớ cần thiết cho mesh
Declaration,
//ma trận kiểu đối tượng D3DVERTEXELEMENT9
pd3dDevice,
//the Direct3D device
&boxMesh);
//biến giữ mesh
//kiểm tra giá trị trả về để chắc chắn rằng bạn đã cómột đối tượng mesh hợp lệ.
if FAILD (hr)
Return false;

Như bạn đã thấy, đoạn code trên tạo ra một mesh chứa 12 phần tử và 8 vectơ và tất cả chúng
được đưa vào trong biến boxMesh. Biến thứ ba là D3DXMESH_MANAGED thông báo
Direct3D là cần sử dụng bộ nhớ cần thiết cho cả vectơ và index buffer để tạo mesh.
Bạn nên chú ý là hàm D3DXDeclaratorFromFVF phải được gọi trước hàm
D3DXCreateMesh.
D3DXDeclaratorFromFVF
tạo
đối
tượng
cần
thiết
D3DVERTEXELEMENT9 cho tham số thứ 4 bằng cách sử dụng Flexible Vertex Format
(định dạng véctơ linh hoạt) mà model của bạn sử dụng.
Khi bạn sử dụng hàm D3DXDeclaratorFromFVF, bạn không cần thiết phải tạo ngay các đối
tượng D3DVERTEXELEMENT9.

D3DXCreatMeshFVF
Hàm D3DXCreateMeshFVF không giống với D3DcreateMesh ở một điểm là nó dựa vào
sự kiến tạo mesh trên Định Dạng Véctơ Linh Hoạt (Flexible Vertex Format) thay vì dùng
Declarator. Mesh object này cũng giống với mesh object được tạo bởi hàm
D3DXCreateMesh ở trong phần trước.
Hàm D3DXCreatMeshFVF được định nghĩa như sau:
HRESULT D3DXCreateMeshFVF(
DWORD Numface,
DWORD NumVertices,
DWORD Options,
DWORD FVF,

98

Beginning DirectX9

Dịch bởi TransTeam diễn đàn Gamedev.VN

LPDIRECT3DDEVICE9 pDevice,
LPD3DXMESH *ppMesh
);

Hàm D3DXCreatMeshFVF cần 6 tham số:
ƒ Numface - số phần tử mà mesh sẽ có
ƒ NumVertices – số véctơ mà mà mesh sẽ có
ƒ Options – các giá trị từ bảng liệt kê D3DXMESH
ƒ FVF – Flexible Vertex Format của các véctơ.
ƒ pDevice – Direct3D device hợp lệ.
ƒ ppMesh – con trỏ trỏ tới đối tượng ID3DXMESH
Dưới đây là một chương trình mẫu gọi hàm D3DXCreateMeshFVF.
//biến giữ giá trị trả về
HRESULT hr;
//biến giữ mesh đựơc tạo mới
LPD3DXMESH boxMesh;
//tạo mesh bằng cách gọi gàm D3DXCreateMeshFVF
hr= D3DXCreateMeshFVF (12,
8,
D3DFVF_MANAGED,
D3DFVF_CUSTOMVERTEX,
pd3dDevice,
&boxMesh);
//kiểm tra giá trị trả về có hợp lệ không
if FAILED (hr)
return false;

//Numfaces
// NumVertices
// Options
// FVF
// pDevice
// ppMesh

Một lần nữa bạn tạo mesh bằng cách sử dụng bộ nhớ quản lý cho véctơ, index buffer và
việc chỉ định giá trị D3DXMESH_MANAGED. Khi việc gọi hàm kết thúc, biến boxMessh
sẽ giữ đối tượng mesh hợp lệ.
Hàm D3DXCreateMeshFVF là hàm dễ sủ dụng nhất trong hai hàm tạo mesh.

Filling the Mesh.
Bạn đã tạo được mesh object, bạn cần bổ xung thêm dữ liệu để mô tả model mà bạn muốn
thể hiện. Ở đây, bạn có một kho rỗng với kích thước thích hợp để chứa dữ liệu cần thiết
cho việc tạo khối lập phương.
Để xác định một khối lập phương, trước tiên bạn cần lock véctơ buffer lại và bổ xung vào
nó 8 véctơ mà khối lập phương cần. Tiếp theo bạn cần lock index buffer và copy toàn bộ
index vào trong đó.
Hàm SetupMesh chỉ ra dưới đây sẽ giúp bạn từng bước hoàn thành mesh với các thông
tin cần thiết để tạo một khối lập phương.
/**************************************************************************************
* SetupMesh
* Set up the vertex buffer and index buffer of a mesh
**************************************************************************************/
HRESULT SetupMesh()
{
HRESULT hr;
//biến giữ giá trị trả về
///////////////////////////////////////////////////////////////////////////////
//các véctơ của vertex buffer
CUSTOMVERTEX g_Vertices[ ]={

99

Beginning DirectX9

Dịch bởi TransTeam diễn đàn Gamedev.VN
// X
Y
Z
{-1.0f, -1.0f, -1.0f, D3DCOLOR_ARGB(0,255,0,0)},
//0
{-1.0f, 1.0f, -1.0f, D3DCOLOR_ARGB(0,0,0,255)},
{ 1.0f, 1.0f, -1.0f, D3DCOLOR_ARGB(0,0,255,0)},
//2
{ 1.0f, -1.0f, -1.0f, D3DCOLOR_ARGB(0,0,0,255)},
//3
{-1.0f, -1.0f, 1.0f, D3DCOLOR_ARGB(0,0,255,0)},
//4
{ 1.0f, -1.0f, 1.0f, D3DCOLOR_ARGB(0,0,0,255)},
//5
{ 1.0f, 1.0f, 1.0f, D3DCOLOR_ARGB(0,0,255,0)},
//6
{-1.0f, 1.0f, 1.0f, D3DCOLOR_ARGB(0,0,0,255)}

//1

//7
};
//Copy các véctơ vào trong vertex buffer
VOID* pVertices;
// lock vertex buffer
hr = boxMesh->LockVertexBuffer(D3DLOCK_DISCARD, (void**)&pVertices);
//kiểm tra lại để chắc chắn là các vertex buffer đã lock
if FAILED (hr)
return hr;
/////////////////////////////////////////////////////////////////////////////////
//index buffer data
//index buffer xác định các phần tử của khối lập phương,
//hai phần tử ở mỗi mặt của cube
WORD IndexData[ ] = {
0,1,2,
//0
2,3,0,
//1
4,5,6,
//2
6,7,4,
//3
0,3,5,
//4
5,4,0.
//5
3,2,6,
//6
6,5,3,
//7
2,1,7,
//8
7,6,2,
//9
1,0,4,
//10
4,7,1,
//11
}
//copy các véctơ vào buffer
memcpy(pVertices, g_Vertices, sizeof(g_Vertices) );
//mở khóa véctơ buffer
boxMesh->UnlockVertexBuffer();
//chuẩn bị copy các index vào index buffer
VOID* IndexPtr;
//khóa index buffer
hr-boxMesh->LockIndexBufffer( 0, &IndexPtr);
//kiểm tra xem index buffer đã khóa chưa
if FAILED (hr)
return hr;
//copy các index vào buffer
memcpy(IndexPtr, IndexData, sizeof( IndexData)*sizeof(WORD));
//mở khóa buffer
boxMesh->UnlockIndexBuffer();
return S_OK;
}

Điều đầu tiên mà hàm SetupMesh làm đó là tạo ma trận g_Vertices. Ma trận này chứa
các véctơ và véctơ màu mà bạn cần để xác định một khối lập phương. Tiếp đó, vectơ
buffer bị locked như đã thấy ở ví dụ trên. Việc gọi hàm memcpy là để copy tất cả các
véctơ vào trong vertex buffer và sau đó thực hiện unlock buffer.

100

nguon tai.lieu . vn