2014-01-27 22 views
1

我需要实现一个按属性存储顶点的结构。例如,每个顶点都有一个属性,如“法线”或“位置”“颜色”等,并且可以通过它们的名称进行访问。存储顶点属性的数据结构

VertexStructure vstruct; 
AttribStream posStream = vstruct.CreateNewAttributeStream("Position",Vec3<double>); 
posStream.push_back(Vec3<double>(23.5,12.5,11.3)); 

AttribStream normalStream = vstruct.CreateNewAttributeStream("Normals",Vec3<double>); 
normalStream.push_back(Vec3<double>(0.03,0.02,0.18)); 

AttribStream indexStream = vstruct.CreateNewAttribStream("Indices",int); 
indexStream.push_back(23); 

std::cout << indexStream.size() << "," << normalStream.size() << posStream.size() << std::endl; 

现在我可以做的一个简单的方法是创建一个预定义数据类型的枚举,比如OpenGL如何实现它。像:

enum { 
DOUBLE = 0, 
FLOAT, 
INT, 
}; 

AttribStream posStream = vstruct.CreateNewAttributeStream("Position",DOUBLE,3); 
posStream.push_back_vec3d(23.5,12.5,11.3); 

但是,这是非常详细的,我要创造一切可能的数据类型的枚举,并有单独的函数对每个数据类型推回新的元素。

另一种可能的方法是使用抽象类。但即使这样也不能保证类型安全(除非使用RTTI)并且涉及到投射并且很难抽象。另外,没有办法创建通用'push_back',所以我需要为每种类型创建专门的函数。

class PX_STREAMBase 
{ 
public: 

    template <typename T> 
    PX_STREAMBase(T val) : value_type(typeid(T)), 
    value_size(sizeof(val)) 
    {}; 

    virtual size_t bytes() const = 0; 
    virtual size_t size() const = 0; 
    virtual const void* data() const = 0; 

    const std::type_info& value_type; 
    const std::size_t value_size; 

private: 


}; 

template<typename T, template <typename, typename> class Container = std::vector> class PX_STREAM; 
template<typename T, template <typename, typename> class Container> 
class PX_STREAM : public PX_STREAMBase { 
public: 
    PX_STREAM() : 
    PX_STREAMBase(T()) 
    {} 

    size_t bytes() const { 
     return vec.size() * value_size; 
    } 
    size_t size() const { 
     return vec.size(); 
    } 
    const void* data() const { 
     return vec.data(); 
    } 
private: 


    Container<T, std::allocator<T> > vec; 
}; 

最后,还有使用的字符数组结构作为described in this question 那么,什么是创建一个抽象的矢量,可以容纳任何类型的属性流结构的最佳方式?

+0

你要过度使用这个:'VEC2_DOUBLE'。首先,双精度顶点属性是GL4的一个特性;事实上,D3D11甚至不支持它们。你应该做的是将基本组件类型和组件数量作为两个独立的属性来存储。比如你在这个属性中有2个'GLdouble'组件。 Count = 2,Component = GLdouble。双精度对于渲染并不特别有用。 –

+0

数据不应该是OpenGL兼容的。我刚刚用它作为例子。但你是对的。 – rwb

+1

那么,你在你的问题中提到了*“像OpenGL那样”*。这实际上并不是GL如何做到的。虽然GL有'DOUBLE_VEC2'作为一个常量枚举,这是用来[描述一个GLSL变量的类型](http://www.opengl.org/sdk/docs/man4/xhtml/glGetActiveUniform.xml )。你永远不会告诉GL有关使用该枚举的顶点属性,它总是通过告诉GL底层数据类型和组件数量来完成的。如果你想像GL那样做,那么你会遵循这个模型。 –

回答

1

好的,所以这看起来像你正在尝试创建一个结构来存储3D模型的数据。顶点坐标和法线。老实说,我认为你只是想让它看起来很花哨。一个存储位置和法线的结构(实际上,如果你想在openGL中使用它们,这些应该是浮点数,因为大多数显卡对双精度浮点数有很强的支持),然后你的系统存储的任何其他数据因为它是模型。您使用此结构的向量,并将任何给定顶点的所有信息保存在一起。

如果你确实需要保持所有的数据分离,我还没有看到一个系统有这样的需求,但我的经验仍然比我想象的更有限,然后创建一个刚刚拥有的结构或类许多矢量,每个矢量都包含一个vec3或任何你需要的特定结构的数据类型。大多数系统知道他们将要为他们的模型查找什么样的数据,所以静态地实现这些结构应该不成问题。对于最终的顶点数据,您只需创建一个结构,其中包含构成特定顶点的单独组件的许多索引。

是否有一个原因,更简单的系统,如:

class Model 
{ 
private: 
    //These vectors serve just to hold all of the data for all of your vertices 
    vector<vec3<float> > positions; 
    vector<vec3<float> > normals; 
    vector<vec3<float> > colors; 

    //This struct holds indices to the vectors above 
    struct Vertex 
    { 
     int position; 
     int normal; 
     int color; 
    }; 

    //Holds a list of all of your vertices, but allows you to pair different positions with different normals, etc... 
    vector<Vertex> vertices; 

    //Holds a list of indices from vertices that are your points to draw. 
    vector<int> drawPoints; 
public: 
    //constructor, destructor, and accessors to add elements to your various elements. 
}; 

是行不通的?

+0

如果只是一些属性,那将非常简单。但是这种情况下,每个顶点可能有25-30个属性(并非所有属性都用于渲染,大部分属于动画和其他元数据),并且它们是动态加载的。 – rwb

+1

@rwb你可能还是过得更好,因为我还记得刚刚做过的类:只填写所有使用的属性并将剩余的向量留空(或者可能使用指针,甚至不构建向量,如果它不是需要)。除非你甚至不知道每个属性会在运行时分配的类型,在这一点上,上帝保佑你先生,因为你是一个比我更勇敢的人。 – Darinth