Home > 圖像編程 > 實作Geometry Builder

實作Geometry Builder


因為還未決定坐標系統,今天先實作 Geometry Builder。


  • Geometry 類別是一個渲染的單位,儲存平台相關的渲染資訊,例如在 Direct3D9 版本裡包括了 Vertex Declaration、Vertex Buffer(s)、Index Buffer 和 Draw-call 的參數。但它並不包含 World Transform、Lighting 及 Material 等資訊。
  • GeometryBuilder 是用來生成 Geometry 的輔助類別。Geometry Builder 的介面是一個平台無關的,只有 Build() 函式的實現才跟平台相關, Build()是把建立的平台無間資訊轉化為平台有關的 Geometry 內容。
  • Device 類別有一個 DrawGeometry() 函式用來渲染 Geometry 物件。

Geometry Builder 的介面設計

為了使其容易使用,並且與平台無關,我盡量把 Geometry Builder 的介面設計得簡單,令它的功能比較單一,只可以生成 Geometry 而不可以修改。Geometry Builder 的用法是:

GeometryBuilder builder;

// Set format

// Add vertices
builder.VertexPosition(Vector3(0, 0, 0));
builder.VertexNormal(Vector3(0, 0, 1));
unsigned i0 = builder.AddVertex();

builder.VertexPosition(Vector3(1, 0, 0));
unsigned i1 = builder.AddVertex(); // using previous normal

builder.VertexPosition(Vector3(0, 1, 0));
unsigned i2 = builder.AddVertex(); // using previous normal

// Add triangle
builder.AddTriangle(i0, i1, i2);

// build
Geometry geometry;

// draw
  1. 使用 SetXXXEnable() 設置 Vertex 格式。(現時的設計只需在 Build() 之前呼這些函式,不影響 2~4)
  2. 使用 VertexXXX() 設定當前的 Vertex Attribue。
  3. 使用 AddVertex() 把當前的 Vertex Attributes 成為一個新的 Vertex,傳回它的 index。
  4. 使用 AddTriangle() 或 AddQuad() 加入三角形或四邊形 (目前使用 Triangle List Primitive,所以 AddQuad() 其實是加入兩個三角形)。
  5. 最後,使用 Build() 去把資料轉換為平台相關的 Geometry 物件。

Texture coordinate 的設置也是相似,但要加入Texture coordinate組的數量及大小,例如:

builder.SetTexcoordCount(2);   // use 2 texcoords per vertex
builder.SetTexcoordSize(0, 2);  // first texcoord is Vector2
builder.SetTexcoordSize(1, 3);  // second texcoord is Vector3

// ...
builder.VertexTexcoord(0, Vector2(0, 0));
builder.VertexTexcoord(1, Vector3(1, 1, 1));

Geometry Builder 的功用

  1. 簡單的介面去建立 Procedural Geometry。
  2. 介面與平台無關,加上函式參數簡單,可以輕易在 Script 裡使用。
  3. 將來可以用它來轉換 Mesh 格式,例如從 COLLADA 轉做平台相關的 Geometry。

經過這次小小的 refactor 後,ChamferBox.cpp 由原來的 221 行缩減至 144 行,並成為平台無關,更可以很容易加減 Vertex Attributes。

C# 的測試

以下是一個簡單的測試,用 C# 建立一個 Form,並在上面渲染一個 Chamfer Box (所有 transform 現時 hard-code 在 DrawGeometry() 裡):

using System;
using System.Windows.Forms;

using Mil.Graphics;
using Mil.Math;

namespace GraphicsCs
    public partial class Test1 : Form
        public Test1()

        public void Run()
            Device device = Device.Instance();

            device.Clear(new Color(0.0f, 0.0f, 0.5f, 0.0f));



        private void Test1_Load(object sender, EventArgs e)

            box1 = new ChamferBox(new Vector3(2, 2, 2), 0.5f, 10);
            geometry = box1.GetGeometry();

        private void Test1_FormClosed(object sender, FormClosedEventArgs e)

        private ChamferBox box1;
        private Geometry geometry;


Ricky 08-03-12 (三) 16:42

怎樣才可 draw 落特定的 C# Window?
Device 的 interface 應怎樣 design?

Milo 08-03-12 (三) 16:49

C# 的 Window (及其他 controls) 都有一個 Handle 的 Property,它的 type 是 IntPtr,其實就是 HWND。我現時是把它轉做 Int32傳過去C++,用它來建立Direct3D Device。如果客製化 SWIG,應該可以直接傳入 IntPtr,不過之前嘗試過但失敗了。

之後我其實要做到渲染到多個 window。

Ricky 08-08-06 (三) 13:56

How do you add other (generic) vertex attributes using the builder?

Milo 08-08-06 (三) 15:06

In this design of GeometryBuilder, the set of vertex attributes are fixed, such as { position, normal, tangent, binormal, color0, color1, texcoord0, …, texcoord7 }.

To support skinning/blending, need to add {blendweights, blendindices}.

But I think this is sufficient for most graphics hardware nowadays. A more flexible, generic buildder is possible, but may be overkill.

Ricky 08-08-06 (三) 16:34

Some more questions:
1) Are there any DCC tools will export normal, tangent and binormal? Or those 3 vectors should be all calculated during loading using the position and u, v alone?
2) Since TBN are all perpendicular with each others (is it correct?), which 2 vectors you will suggest to calculated first?
Thx a lot!

Milo 08-08-06 (三) 18:05

1) In ColladaMax, there is option to activate exporting of binormal/tangent. But there is no option to choose the mapping channel for computing these basis. You may compute them anytime by your own. Besides, you may need to handle mirror UV, and save the sign (mirror or not) in W component of tangent or binormal vector. I think ColladaMax does not have this.

2) I think there is no difference. I saw some vertex shaders compute the third basis from the other two by cross-product.

Comment Form
Remember personal info


Trackback URL for this entry
Listed below are links to weblogs that reference
實作Geometry Builder from Milo的遊戲開發

Home > 圖像編程 > 實作Geometry Builder


Return to page top