2017-05-15 1 views
1

頂点のstd :: vectorをfloat *に変換する最良の方法は何ですか?私は元のデータとしてvtxを持っています。これには、位置、通常、およびuvの2つの頂点が含まれています。また、同じ位置、通常、およびuvの頂点vのベクトルがあります。私が達成しようとしているのは、std :: vector vを使ってvtxと同じメモリレイアウトとデータを取得することです。memcpyを使ってvからvtx2にメモリをコピーしようとしましたが、それらを印刷すると、頂点のベクトル:: stuctsをfloatに変換する*

#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; 
} 
+0

あなたはそれをどうしようとしていますか? 'data'メンバにアクセスして基本となる配列へのポインタを得ることができますが、これは定数であり、直接変更しないでください。 – Donnie

+0

私はいくつかのVBOを元々フロート*を使用していました。私は代わりにそれらを標準のベクトルに変換しようとしています:: Verticesの代わりに、同じメモリレイアウトを保持します。 – sabotage3d

+0

*なぜ*メモリレイアウトを保存しますか?通常、標準のコンテナを使用する場合、メモリのレイアウトは問題ではありません。 – Beta

答えて

1
#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を最初の行にしないと、コンパイラーは構造体に空のスペースを埋め込み、問題を引き起こしています。 struct Vertex __attribute__((packed))を使ってGCCやclangでこれを防ぐことができます。他のコンパイラにはさまざまな方法があります。

+0

vtxは8だけシフトしましたvtx2と同じレイアウトを維持する必要があります。 – sabotage3d

+0

vtxは、8を2度追加したためにシフトされます。どちらの場合でも、データはメモリ内の同じ場所に残ります。 memcpyの後ろに 'vtx2 + = 16;'を置くことで同等にすることができます。 – patstew

+0

@ sabotage3d @patstewは、 'vtx2'の内容を出力するとナンセンスです...' vtx2'は配列の**フロント**を指しています。あなたは ' vtx2 + i * -1' – donkopotamus

1

あなたのコードにバグがあります:

vt.position = normal1 

はあなたのベクトルにおける第二の頂点のための

vt.normal = normal1 

と同様にをお読みください。修正すると出力が一致することがわかりますが、それはコンパイラがどのように構造体を埋めているかによって異なります。

たとえば、Vector3で異なるアライメントを強制すると、struct Vector3 {...} __attribute__ ((aligned (16)));を使用すると、「破損した」出力が生成されます。ここ

+0

また、2番目の印刷ループがvtx2から後方に印刷されています – patstew

+0

私はvtxを8にシフトしています。なぜなら、vtx2のレイアウトを同じにすることです。 – sabotage3d

+0

@ sabotage3d @patstewが作ったのは、 'vtx2'の内容を印刷すると、ナンセンスです...' vtx2'は配列の**フロント**を指しています。あなたは ' vtx2 + i * -1' – donkopotamus

関連する問題