2016-03-25 22 views
1

Ich brauche Hilfe bei dem richtigen Algorithmus kommt eine Ecke Schwimmerpufferarray mit Daten zu füllen ...Index in Array von XYZ berechnen?

Da jeder Punkt 9 Attribute (XYZ, UV, RGBA) in meinem Setup, und ich bin Zeichnung mit Quads, jedes Gesicht hat insgesamt 36 Indizes. Ich zeichne Würfel so, dass es 6 Gesichter für insgesamt 216 (9 * 4 * 6) Indizes gibt. Anstatt nur den Puffer Iterieren es zu füllen durch:

public void AddVertex(int x, int y, int z, float u, float v, Color4 color) 
    { 
     if (vCount >= vertex_data.Length) 
      return; 
     else 
     { 
      vertex_data[vCount++] = x; 
      vertex_data[vCount++] = y; 
      vertex_data[vCount++] = z; 
      vertex_data[vCount++] = u; 
      vertex_data[vCount++] = v; 
      vertex_data[vCount++] = color.R; 
      vertex_data[vCount++] = color.G; 
      vertex_data[vCount++] = color.B; 
      vertex_data[vCount++] = color.A; 
     } 
    } 

Ich mag eine direkt Offset verwenden, um die Position im Puffer Ziel auf der GPU aktualisiert werden (durch Verwendung von BufferSubData). Das Problem besteht jedoch darin, den relativen Positionswert eines Cubes (XYZ) in die Position im Pufferarray zu übertragen, damit ich seine Werte aktualisieren kann.

Dies ist, wie ich Würfel bin iteriert, und mein Versuch, die richtige Position bekommen ...

for (int x = 0; x < Chunk.DEFAULT_SIZE; x++) 
     { 
      for (int y = 0; y < Chunk.DEFAULT_SIZE; y++) 
      { 
       for (int z = 0; z < Chunk.DEFAULT_SIZE; z++) 
       { 
        <...> 
        offset = (x + size * (y + size * z)) * 216; 
        SetVertex(offset, face_i.X + absX, face_i.Y + absY, face_i.Z + -absZ, u, v, color); 
        //SetVertex (...) would be called 3 more times, and "offset" would be supplemented by 0,9,18, and 27 (totalling 36 indices). 
        <...> 
       } 
      } 
     } 

Ich habe sogar versucht Bitverschiebung die XYZ-Werte:

int offset = 216 * (x<<10) + 216 * (y<<5) + 216*z; 

dass nur gearbeitet in bestimmten Situationen. Gehe ich in die falsche Richtung oder? Das Ergebnis des obigen Codes erstellt nur die untere Fläche der Würfel, aber sie erstellt sie in allen richtigen Intervallen.

+0

Sollte '216' in diesem Code nicht:' offset = (x + size * (y + size * z)) * 216; 'ersetzt werden durch was auch immer die aktuelle Indexzahl ist? Wenn also "x = y = z = 0" ist, sollte nicht diese "216" -Nummer "0" sein? Auch was ist mit allen Klammern in 'SetVertex (Offset, Gesicht_i.X + absX), Gesicht_i.Y + absY), Gesicht_i.Z + -absZ), u, v, Farbe);', gibt es eine öffnende und vier schließende Klammern . – Quantic

+0

Whoops, Tippfehler, den ich vermisste, während ich ihn vereinfachte. Thx - korrigiere jetzt. –

+0

Ja, normalerweise wäre es Offset + i. Ich bin 9 * (x <4). Frage bearbeiten, um das einzuschließen. –

Antwort

1

Die erste Sache, die ich tun würde, ist Code schreiben, der Ihnen den Offset der Adresse des Eckpunkts gibt, den Sie ändern möchten, gegeben eine Koordinate, ein Gesicht und einen Scheitelpunkt. Dies erspart Ihnen viele Kopfschmerzen beim Adressieren von Datenzeigern. Dies würde wahrscheinlich so etwas wie folgt aussehen:

size_t get_offset(int x, int y, int z, face_enum face, vertex_enum vertex) { 
    size_t x_offset = x * Chunk.DEFAULT_SIZE * Chunk.DEFAULT_SIZE; 
    size_t y_offset = y * Chunk.DEFAULT_SIZE; 
    size_t z_offset = z; 

    size_t cube_offset = x_offset + y_offset + z_offset; 

    size_t face_offset = convert_face_enum_to_index(face); //I'm here assuming that all the possible enums map to indexes in the range [0,5] 

    size_t quad_offset = cube_offset * 6 + face_offset; //Multiplied by six for six faces 

    size_t vertex_offset = convert_vertex_enum_to_index(vertex); //I'm here assuming that all the possible enums map to indexes in the range [0,3] 

    size_t vertex_location = quad_offset * 4 + vertex_offset; //Multiplied by four for four vertices per quad. 
    const size_t num_of_floats_per_vertex = 9; //Based on your problem description, this should be correct 

    return vertex_location * num_of_floats_per_vertex; 
} 

public void modify_vertex(float * location, float x, float y, float z, float u, float v, Color4 color) { 
    location[0] = x; 
    location[1] = y; 
    location[2] = z; 
    location[3] = u; 
    location[4] = v; 
    location[5] = color.R; 
    location[6] = color.G; 
    location[7] = color.B; 
    location[8] = color.A; 
} 

Wenn alle Versuche, Vertex-Daten hinzufügen oder ändern in dieser Art und Weise durchgeführt wird, es wird Ihr Leben viel einfacher. Sobald Sie dies getan haben, können Sie dann Code schreiben, der wie folgt aussieht:

for(cube qube : cubes) { //Depends on your implementation. If you've literally stored all the cubes in a cube[][][] array, then the triple-nested code you wrote above would be adequate. 
    for(face_enum face = FACE0; face <= FACE5; face++) { //I'm assuming that face_enum has an increment operator; this may need to be adjusted depending on what you write. 
     for(vertex_enum vertex = VERTEX0; vertex <= VERTEX3; vertex++) { //same deal here. 
      size_t vertex_offset = get_offset(qube.x, qube.y, qube.z, face, vertex); 
      float * data_offset = my_mapped_vertex_buffer + vertex_offset; 
      modify_vertex(data_offset, /*insert appropriate data here*/); 
     } 
    } 
} 

Und dann einrichten, solange Sie Objekt Ihre Eckpunktpufferspeicher (und alle zugehörigen Attribut Zeiger) richtig, diese speichert alle relevanten Rendering-Daten in einer konsistenten und einfach zu modifizieren (aus der Perspektive eines Programmierers).

Natürlich müssen Sie sicherstellen, dass der Eckenpuffer groß genug ist, um jeden Würfel zu speichern, aber das war immer noch ein Problem mit dem alten Code.

+0

Danke für die Antwort. Wenige Fragen ... - "convert_vertex_enum_to_index (Vertex)", meinst du wörtlich welches Gesicht 0-5? - "float * data_offset = mein_mapped_vertex_buffer + vertex_offset;", was ist "my_mapped_vertex_buffer"? das Puffer-Float-Array? –

+0

@ChrisGlenn 'my_mapped_vertex_buffer' ist im Grunde genommen eine Abkürzung für das Speichermedium, das Sie zum Verwalten der Scheitelpunktdaten verwenden. Ob es auf dem Heap in einem 'std :: vector 'gespeichert ist oder ob Sie es von der Grafikkarte abbilden, spielt keine Rolle. 'convert_vertex_enum_to_index' ist das gleiche: Es ist eine Abkürzung für" welchen Knoten adressiere ich, den ersten, den zweiten, den dritten oder den vierten? " umgewandelt in "erste == 0, zweite == 1, dritte == 2 und vierte == 3". – Xirema

+0

Rechts. Stellen Sie sicher, dass wir auf der gleichen Seite sind :) Also habe ich Ihren Code an meinen angepasst, aber es ist nur die unteren Flächen jedes Würfels jetzt Rendern. Ich bin nicht sicher, warum es nur ein einzelnes Gesicht pro Würfel obwohl aktualisiert ... Hier ist der vollständige Code :: http://pastebin.com/ANLnVvmc –