Seite 1 von 1

Struct mit dynamic array

Verfasst: 06.08.2013, 09:49
von snoob741
Aktuell implementiere ich für mich einen ASSIMP Importer. Um beim Auslesen der Texturdaten nicht für jede Channel Kombinationsmöglichkeit ein eigenes Texture-Struct zu definieren (Nutze VBO-Multistreaming) wollte ich ein TextureStruct verwenden, dass ein dynamisch allokiertes Array nutzt:

Code: Alles auswählen

struct TXSTREAM
{
  float* uv;
};
Beim Import der Texturdaten mache ich folgendes:

Code: Alles auswählen

    unsigned int channels = 1; // mesh->GetNumUVChannels();
    std::shared_ptr<brGraphics::brVertexDeclaration> vxDecl = system.createVertexDeclaration();
    for(int c=0; c<channels; c++){ 
        vxDecl->addElement(brGraphics::brVertexElement(brGraphics::brVertexElement::TYPE_FLOAT_2, 
                                                       brGraphics::brVertexElement::USE_TEXCOORD, 
                                                       sizeof(float)*(c*2)));                                            
    }
    
    std::vector<TXSTREAM> texCoords;     
    for(unsigned int v = 0 ; v < mesh->mNumVertices; v++) 
    {    
        struct TXSTREAM coord;
        coord.uv = (float*)malloc((channels*2)*sizeof(float));
             
        for(int c=0; c<channels; c++){ 
           const aiVector3D texCoord  = (mesh->mTextureCoords[c][v]);
           coord.uv[0+(c*2)] = texCoord.x;
           coord.uv[1+(c*2)] = texCoord.y;                                                                                       
        }         
        texCoords.push_back(coord);                                             
    }   
    
    unsigned int size = texCoords.size();    
    unsigned int bytes = sizeof(TXSTREAM)+((channels*2)*sizeof(float));
     
    std::shared_ptr<brGraphics::brVertexBuffer> tbo =
    system.createVertexBuffer(brGraphics::brVertexBuffer::USE_STATIC, 
                              bytes, 
                              size); 
    tbo->writeData(0, size, &texCoords[0]);
    tbo->setVertexDeclaration(vxDecl);
Irgendwie wird nur Müll gemapped. Habe ich bei der Berechnung der Bytegröße evtl. einen gedanklichen Fehler?

Re: Struct mit dynamic array

Verfasst: 06.08.2013, 09:58
von Artificial Mind
Ehm ja, ich glaube ich sehe dein Problem.

Du hast texCoords als vector von TXSTREAMs gemacht, also einen Vektor von Pointern. Die Daten liegen also mit einer Indirektion zu viel im Speicher und "tbo->writeData(0, size, &texCoords[0]);" schreibt die Pointer und nicht die Daten in den Buffer.

Meine Lösung: nutz einen vector<char> und push dort alle Daten rein. Alternativ ein vector<float>.

Re: Struct mit dynamic array

Verfasst: 06.08.2013, 12:35
von snoob741
Danke für Deinen Hinweis. Hab einmal versucht das ganze mit einem std::vector<float> abzuhandlen. Aber irgendwie
bekomme ich das nicht gebacken (k.A. ob die Hitze mir mal wieder zu Kopf steigt :? )

Code: Alles auswählen

    std::vector<float> texCoords;   
    for(unsigned int v = 0 ; v < mesh->mNumVertices; v++) 
    {           
        for(int c=0; c<channels; c++){ 
           const aiVector3D texCoord  = (mesh->mTextureCoords[c][v]);
           texCoords.push_back(texCoord.x);
           texCoords.push_back(texCoord.y);
        }                                            
    }   
    
    unsigned int size = texCoords.size();         
    std::shared_ptr<brGraphics::brVertexBuffer> tbo =
    system.createVertexBuffer(brGraphics::brVertexBuffer::USE_STATIC, 
                              (sizeof(float)*(channels*2), 
                              size); 
    tbo->writeData(0, size, texCoords.data());
    tbo->setVertexDeclaration(vxDecl);
Klappt soweit ich nur einen texture channel habe. Sobald die Mesh 2 Channels hat, steigt mir das ganze beim schreiben der Daten aus. Hab ich etwas übersehen oder meintest Du generell etwas anderes?

Re: Struct mit dynamic array

Verfasst: 06.08.2013, 12:56
von Artificial Mind
Dein size scheint viel zu groß zu sein. Wenn ich die binrevengine richtig verstehe, muss size bei createVB die Anzahl der vertices sein, also texCoord.size() / (channels * 2).
Gleiches gilt dann natürlich auch bei writeData, dort muss auch die Anzahl der vertices stehen.
Weiterhin fehlt mir bei (sizeof ..., (in createVB) die schließende Klammer, ich gehe davon aus, dass das ein copy'n'paste Fehler ist.

Re: Struct mit dynamic array

Verfasst: 06.08.2013, 13:29
von snoob741
Eigentlich nicht. CreateVB erwartet die Size eines einzelnen Vertex bzw. Datensatzes als 2. Parameter und die Anzahl der Vertices als 3. Daraus wird dann dynamisch die Anzahl der Bytes berechnet:

Code: Alles auswählen

/**
@brief Default constructor.
@param usage The buffer usage enum type.
@param sizeVertex The size of a single vertex.
@param numVertices The number of vertices append to this buffer.
*/
brVertexBuffer::brVertexBuffer(brDataBuffer::eBufferUsage usage, unsigned int sizeVertex, unsigned int numVertices)
: brDataBuffer(usage), m_numVertices(numVertices), m_sizeVertex(sizeVertex), m_useIndices(false)
{
    // calculate the number of bytes of data
    m_size = m_sizeVertex*m_numVertices;
}
Somit müsste doch die Größe eines Datensatzes im std::vector doch sizeof(float)*2*channels (2 floats pro channel) sein, oder bin ich da grad auf dem Holzweg? P.S. Jupp das mit der fehlenden Klammer war ein C&P Fehler ...

Re: Struct mit dynamic array

Verfasst: 06.08.2013, 13:46
von Artificial Mind
die Size pro Vertex ist sizeof(float)*2*channels, aber die Anzahl der Vertices ist NICHT texCoord.size() sondern texCoord.size() / (2 * channels)

Re: Struct mit dynamic array

Verfasst: 06.08.2013, 13:54
von snoob741
Oh man danke! Das quiescht ja schon vor Dummheit :? Ich glaub ich geh erstmal ne runde Schwimmen um den Kopf frei zu bekommen 8-)