【问题标题】:Data Structure for storing Vertex Attributes存储顶点属性的数据结构
【发布时间】:2014-01-27 22:36:50
【问题描述】:

我需要实现一个按属性存储顶点的结构。例如,每个顶点都有一个属性,如“Normals”或“Position”、“Colors”等,并且可以通过它们的名称访问它们。

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;
};

最后,使用 char 数组结构为 described in this question 那么,创建一个抽象向量并可以保存任何类型的属性流的结构的最佳方法是什么?

【问题讨论】:

  • 你过火了:VEC2_DOUBLE。首先,双精度顶点属性是 GL4 的特性;事实上,D3D11 甚至不支持它们。您应该做的是将基本组件类型和组件数量存储为两个单独的属性。例如,您在此类属性中有 2 个GLdouble 组件。计数 = 2,组件 = GLdouble。双精度对于渲染并不是特别有用。
  • 数据不应该与 OpenGL 兼容。我只是用它作为例子。但你是对的。
  • 好吧,您在问题中提到了 “就像 OpenGL 是如何做到的一样”。这实际上并不是 GL 的做法。虽然 GL 确实有 DOUBLE_VEC2 作为常量枚举,但它用于 describe the type of a GLSL variable。您永远不会使用该枚举告诉 GL 顶点属性,它总是通过告诉 GL 底层数据类型和组件数量来完成。如果你想像 GL 那样做,那么你会遵循那个模式。
  • 明白了。但是,这仍然意味着 POD 结构必须分解为单独的属性。

标签: c++ opengl data-structures stl


【解决方案1】:

好的,看起来您正在尝试创建一个结构来存储 3D 模型的数据。顶点坐标和法线。老实说,我认为你只是想让它变得花哨。带有一对vec3&lt;double&gt;s 存储位置和法线的结构(实际上,如果你想在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.
};

没有用?

【讨论】:

  • 如果只是几个属性,那就很容易了。但是这种情况下,每个顶点可能有 25-30 个属性(并非所有属性都用于渲染,大多数用于动画和其他元数据)并且它们是动态加载的。
  • @rwb 您最好还是按照我的说明进行课程:只需填写所有使用的属性并将剩余的向量留空(或者可能使用指针而不是如果不需要,甚至构建向量)。除非您甚至不知道每个属性将采用的类型以及在运行时分配的类型,否则上帝保佑您先生,因为您比我更勇敢。:)
猜你喜欢
  • 1970-01-01
  • 2013-06-28
  • 2021-01-08
  • 2015-07-09
  • 1970-01-01
  • 2016-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多