将 std::vector 个顶点结构转换为浮点数*

Converting std::vector of Vertices stucts to float*

将 std::vector 个顶点转换为 float* 的最佳方法是什么?我有 vtx 作为我的原始数据,它包含两个具有位置、法线和 uv 的顶点,我有 std::vector 个具有相同位置、法线和 uv 的顶点 v。我想要实现的是使用 std::vector v 将与 vtx 相同的内存布局和数据导入 vtx2。我尝试使用 memcpy 将内存从 v 复制到 vtx2,但是当我打印它们时,它们以不同的方式排序。

#include <iostream>
#include <vector>

using namespace std;

struct Vector3
{
    float x;
    float y;
    float z;
};

struct Vector2
{
    float x;
    float y;
};

struct Vertex
{
    Vector3 position;
    Vector3 normal;
    Vector2 uv;
};

int main(int argc, char *argv[])
{
    const int n = 16;
    float* vtx = new float[n];

    // Vertex 1
    // Position
    vtx[0] = 1.0f;
    vtx[1] = 2.0f;
    vtx[2] = 3.0f;
    // Normal
    vtx[3] = 0.1f;
    vtx[4] = 0.2f;
    vtx[5] = 0.3f;
    // UV
    vtx[6] = 0.0f;
    vtx[7] = 1.0f;

    vtx += 8;

    // Vertex 2
    // Position
    vtx[0] = 4.0f;
    vtx[1] = 5.0f;
    vtx[2] = 6.0f;
    // Normal
    vtx[3] = 0.2f;
    vtx[4] = 0.3f;
    vtx[5] = 0.4f;
    // UV
    vtx[6] = 0.0f;
    vtx[7] = 1.0f;

    vtx += 8;


    for (int i = n; i>0; i--)
    {
        cout << *(vtx + i * -1) << endl;
    }

    vector<Vertex> v;
    Vertex vt;

    // Vertex 1
    // Position
    Vector3 pos1 = {1.0, 2.0, 3.0};
    vt.position = pos1;
    // Normal
    Vector3 normal1 = {0.1, 0.2, 0.3};
    vt.position = normal1;
    // UV
    Vector2 uv1 = {0.0, 1.0};
    vt.uv = uv1;

    v.push_back(vt);

    // Vertex 2
    // Position
    Vector3 pos2 = {4.0, 5.0, 6.0};
    vt.position = pos2;
    // Normal
    Vector3 normal2 = {0.2, 0.3, 0.4};
    vt.position = normal2;
    // UV
    Vector2 uv2 = {0.0, 1.0};
    vt.uv = uv2;

    v.push_back(vt);

    float* vtx2 = new float[n];
    memcpy(vtx2, &v[0], v.size() * sizeof(Vertex));

    for (int i = n; i>0; i--)
    {
        cout << *(vtx2 + i * -1) << endl;
    }

    delete[] vtx;
    delete[] vtx2;

    return 0;
}

您的代码中存在错误:

vt.position = normal1

应该阅读

vt.normal = normal1

向量中的第二个顶点也类似。修复后,您可能会发现输出匹配(对我来说是这样),但这可能取决于您的编译器如何填充结构。

例如,使用 struct Vector3 {...} __attribute__ ((aligned (16)));Vector3 上强制进行不同的对齐将生成 "corrupted" 输出。

#include <cstring>
#include <iostream>
#include <vector>
#include <cstddef>

using namespace std;

struct Vector3
{
    float x;
    float y;
    float z;
};

struct Vector2
{
    float x;
    float y;
};

struct Vertex
{
    Vector3 position;
    Vector3 normal;
    Vector2 uv;
};

int main(int argc, char *argv[])
{
    const int n = 16;
    float* vtx1 = new float[n];
    float* vtx = vtx1;

    cout << offsetof(Vertex, normal) << " " << offsetof(Vertex, uv) << " " << sizeof(Vertex) << "\n";

    // Vertex 1
    // Position
    vtx[0] = 1.0f;
    vtx[1] = 2.0f;
    vtx[2] = 3.0f;
    // Normal
    vtx[3] = 0.1f;
    vtx[4] = 0.2f;
    vtx[5] = 0.3f;
    // UV
    vtx[6] = 0.0f;
    vtx[7] = 1.0f;

    vtx += 8;

    // Vertex 2
    // Position
    vtx[0] = 4.0f;
    vtx[1] = 5.0f;
    vtx[2] = 6.0f;
    // Normal
    vtx[3] = 0.2f;
    vtx[4] = 0.3f;
    vtx[5] = 0.4f;
    // UV
    vtx[6] = 0.0f;
    vtx[7] = 1.0f;

    vtx += 8;


    for (int i = n; i>0; i--)
    {
        cout << *(vtx + i * -1) << endl;
    }

    cout << "\n";

    vector<Vertex> v;
    Vertex vt;

    // Vertex 1
    // Position
    Vector3 pos1 = {1.0, 2.0, 3.0};
    vt.position = pos1;
    // Normal
    Vector3 normal1 = {0.1, 0.2, 0.3};
    vt.normal = normal1;
    // UV
    Vector2 uv1 = {0.0, 1.0};
    vt.uv = uv1;

    v.push_back(vt);

    // Vertex 2
    // Position
    Vector3 pos2 = {4.0, 5.0, 6.0};
    vt.position = pos2;
    // Normal
    Vector3 normal2 = {0.2, 0.3, 0.4};
    vt.normal = normal2;
    // UV
    Vector2 uv2 = {0.0, 1.0};
    vt.uv = uv2;

    v.push_back(vt);

    float* vtx2 = new float[n];
    vtx = vtx2;
    memcpy(vtx, &v[0], n*sizeof(float));
    vtx += n;

    for (int i = n; i>0; i--)
    {
        cout << *(vtx + i * -1) << endl;
    }

    delete[] vtx1;
    delete[] vtx2;

    return 0;
}

这是一些使用 .normal 而不是 .position 的更正代码,它不会通过删除 vtx 来删除随机内存,并且第二个打印循环已修复以显示数组中的数据,而不是前面的 16 字节内存它。它还在第一行打印结构大小和偏移量。如果您没有将 12 24 32 作为第一行,则您的编译器会用空 space 填充结构,这会导致您出现问题。您可以使用 struct Vertex __attribute__((packed)) 来防止在 GCC 或 clang 上出现这种情况。其他编译器有不同的方法。