2010-06-21 66 views
4

我正試圖在C++土地上找到我的方式,現在越來越困惑。玩具應用程序是一個非常基本的OpenGL引擎。 所以這裏是(我猜簡單)的問題: 我想處理不同頂點數據的網格,所以我有模板vs開關

struct Vertex 
{ 
    Vector3f position; 
} 

struct VertexN : public Vertex 
{ 
    Vector3f normal; 
} 

現在我需要一個Mesh類,它包含數據並繪製它。 我試過這樣的事情:

template<class T> 
class Mesh 
{ 
    public: 
     Mesh(); 
     ~Mesh(); 

     void load(const T * vertices, int num); 
     void draw(); 

    protected: 
     T * vertices_; 

};;

不同的頂點必須加載和繪製不同,這可以通過模板專門化來完成。

我的問題是,我喜歡有另一個持有Mesh對象實例的類,但模板類成員顯然是不允許的。

我能想到的另一種解決方案是在Mesh中保存指向基本結構頂點的指針,傳遞所使用的頂點類型的標識符,然後在load()和draw()中使用switch語句以允許不同的實現。

完成此操作的最佳方法是什麼?

任何幫助,非常感謝。

回答

7

您可以使用繼承和虛函數。例如:

class MeshBase 
{ 
public: 
    virtual ~MeshBase() { } 
    virtual void draw() = 0; 
}; 

template <typename T> 
class Mesh : public MeshBase 
{ 
public: 
    virtual void draw() { } 
    // ... 
}; 

通過這種方法,你可以存儲在一個容器指針的基類MeshBase

理想情況下,你可以使用指針容器,將管理的指針你,或者你可以使用智能指針的容器(例如,std::vector<std::shared_ptr<MeshBase> >,如果您的實現包括shared_ptr;如果沒有,it can be found in a number of places)。

我還建議將頂點存儲在Mesh類的容器中,而不是使用手動動態分配和內存管理。

+0

鑑於Vertex類的繼承,Mesh上的模板是否也可以被移除? – drfrogsplat 2010-06-21 15:09:44

+0

@drfrogsplat:只有當你想存儲指向單個頂點的指針時,這可能不是出於性能原因所期望的。我不會在所有頂點類中使用繼承:只是將每種類型的頂點實現爲獨立類或使用模板(例如,這是OpenSceneGraph所做的)。 – 2010-06-21 15:11:32

+2

如果您有權訪問boost(它是Boost.PointerContainer的一部分),請嘗試將'boost :: ptr_vector'設置爲'std :: vector '。在C++ 0x中,你可以使用'std :: vector '來避免boost的依賴。 – 2010-06-21 15:14:13

0

我建議你不要模擬你的網格類,但要使它能夠處理不同類型的頂點數據。這是一個常見的圖形問題,在DirectX中解決了將不同的「數據流」綁定在一起繪製幾何圖形的想法。換句話說,你的法線將是一個不同於你的位置數據的數據流。然後,網格對象變成一個包含多個數據流的容器,並且在編譯時不會被綁定到特定的頂點格式。我不知道OpenGL,但我想有一個類似的概念。

參見:http://msdn.microsoft.com/en-us/library/bb147299(VS.85).aspx

0

@bshields有一個點,就需要表示最有效的方式頂點數據,其中在OpenGL的情況下是頂點緩存對象(維也納組織):http://www.opengl.org/wiki/Vertex_Buffer_Object

鑑於準則暴露在上面的鏈接中 - 這與@James McNellis所說的關於不對頂點類型使用繼承的內容一致 - 以及加載和繪製都可能取決於頂點類型和輸入類型(或輸出)我建議你使用靜態多態性來應用策略模式,正如在其他問題的答案中所概括的那樣:template strategy pattern

+0

謝謝。 draw()已經使用了一個包裝到VBO。我也應該正確地調整數據......你鏈接的文章很有趣,但現在看起來對我來說有點矯枉過正。無論如何收藏。 – bbtrb 2010-06-21 15:55:40