2017-07-21 5 views
1
void GeometryGenerator::Subdivide(MeshData& meshData) 
{ 
    // Save a copy of the input geometry. 
    MeshData inputCopy = meshData; 


    meshData.Vertices.resize(0); 
    meshData.Indices.resize(0); 

    //  v1 
    //  * 
    // /\ 
    // / \ 
    // m0*-----*m1 
    // /\ /\ 
    /// \/ \ 
    // *-----*-----* 
    // v0 m2  v2 

    UINT numTris = inputCopy.Indices.size()/3; 
    for(UINT i = 0; i < numTris; ++i) 
    { 
     Vertex v0 = inputCopy.Vertices[ inputCopy.Indices[i*3+0] ]; 
     Vertex v1 = inputCopy.Vertices[ inputCopy.Indices[i*3+1] ]; 
     Vertex v2 = inputCopy.Vertices[ inputCopy.Indices[i*3+2] ]; 

     // 
     // Generate the midpoints. 
     // 

     Vertex m0, m1, m2; 

     // For subdivision, we just care about the position component. We 
     // derive the other 
     // vertex components in CreateGeosphere. 

     m0.Position = XMFLOAT3(
      0.5f*(v0.Position.x + v1.Position.x), 
      0.5f*(v0.Position.y + v1.Position.y), 
      0.5f*(v0.Position.z + v1.Position.z)); 

     m1.Position = XMFLOAT3(
      0.5f*(v1.Position.x + v2.Position.x), 
      0.5f*(v1.Position.y + v2.Position.y), 
      0.5f*(v1.Position.z + v2.Position.z)); 

     m2.Position = XMFLOAT3(
      0.5f*(v0.Position.x + v2.Position.x), 
      0.5f*(v0.Position.y + v2.Position.y), 
      0.5f*(v0.Position.z + v2.Position.z)); 

     // 
     // Add new geometry. 
     // 

     meshData.Vertices.push_back(v0); // 0 
     meshData.Vertices.push_back(v1); // 1 
     meshData.Vertices.push_back(v2); // 2 
     meshData.Vertices.push_back(m0); // 3 
     meshData.Vertices.push_back(m1); // 4 
     meshData.Vertices.push_back(m2); // 5 

     meshData.Indices.push_back(i*6+0); 
     meshData.Indices.push_back(i*6+3); 
     meshData.Indices.push_back(i*6+5); 

     meshData.Indices.push_back(i*6+3); 
     meshData.Indices.push_back(i*6+4); 
     meshData.Indices.push_back(i*6+5); 

     meshData.Indices.push_back(i*6+5); 
     meshData.Indices.push_back(i*6+4); 
     meshData.Indices.push_back(i*6+2); 

     meshData.Indices.push_back(i*6+3); 
     meshData.Indices.push_back(i*6+1); 
     meshData.Indices.push_back(i*6+4); 
    } 
} 

Diese Funktion ist in ‚GeometryGenerator.cpp‘ Datei und hat ein Netz unterteilen. Bevor diese Funktion aufgerufen wird, wird ein Ikosaeder erstellt und als Parameter meshData übertragen. Die Member von MeshData, Vertices und Indices sind Vektoren von STL.In einem Beispielcode des Buches „Einführung in die 3D-Spieleprogrammierung mit DirectX 11“

Meiner Meinung nach, ruft diese Funktion diese Reihe von Funktionen, meshData.Vertices.push_back, in der nächsten Iteration der Schleife einige der Scheitelpunkte wiederholt gespeichert werden.

Jeder konnte

  • beantworten, ob ich falsch bin,
  • , warum der Autor die Codes wie diese machen,
  • oder ob es effizienter, wenn meine Gedanken richtig ist.

Danke an alle, die mein schlechtes Englisch gelesen haben.

Antwort

0

ob ich falsch bin

Ich bin ziemlich sicher, dass Sie sind rechts, vor allem über die duplizierten Ecken!

warum machen der Autor die Codes wie diese

Niemand sich diese außer dem Autor beantworten kann. Ich würde erraten dass er/sie einfach die Duplizierung Problem beaufsichtigt ...

oder ob es effizienter ist, wenn meine Gedanken richtig sind.

Ich würde für efficency so lange egal, wie der Algorithmus nicht korrekt ist!

Zuerst müssen wir Vertex-Duplizierung vermeiden. Ich würde einfach die vorhandenen Vertices belassen wie sie sind (also nur die Indizes) und die neuen am Ende anhängen. Zu diesem Zweck würde ich die Kanten in einer temporären std :: map speichern, ein Paar Indizes (die Kante) dem neu erstellten Index zuordnen (immer kleinerer Index zuerst, um Probleme mit (10,12) vs. zu vermeiden, die die gleiche Kante ...).

Dann für v0, v1, v2 würde ich die Indizes verwenden, nicht die Scheitelpunkte selbst.m0, m1, m2 werden zuerst in der Map nachgeschlagen, falls gefunden, verwenden Sie andernfalls, erstellen Sie einen neuen Vertex, fügen Sie ihn dem Vertices-Vektor hinzu und fügen Sie einen Eintrag in unsere Map ein.

UINT v0 = copiedIndices[i*3+0]; 
// ... 

UINT m0; 
auto key = std::make_pair(v0, v1); // TODO: order indices!!! 
auto entry = myMap.find(key); 
if(entry != myMap.end()) 
{ 
    m0 = entry->second; 
} 
else 
{ 
    meshData.Vertices.push_back(newVertex); 
    m0 = meshData.Vertices.size() - 1; 
    myMap.insert(key, m0); 
} 

Dann werden Sie Ihre neue Dreiecke hinzufügen, nehmen Sie nur die Indizes sind:

meshdata.indices.pushback(v0); // one of the original indices 
meshdata.indices.pushback(m0); // one of the new ones 
meshdata.indices.pushback(m2); 

// ... 
+0

Ich habe einige Tage und heute weggegangen sah ich Ihre feine Antwort! Vielen Dank für Ihre Hilfe und Entschuldigung für einen Kommentar zu spät. Es war sehr hilfreich, also überarbeite ich die Codes mit Bezug auf Ihre Antwort. Danach kann ich auch eine Formel finden, die hilft, die Anzahl der Eckpunkte der 'aktuellen' Geosphäre zu erhalten. Die Anzahl der Seiten ist die Anzahl der Scheitelpunkte, die erstellt werden, und ersteres kann dadurch erreicht werden: (aktuelle Dreieckszahl) * 3/2. Ihre Antwort gab mir die Möglichkeit, weiter fortgeschritten zu denken, danke :) – Owen

0
  • Wenn neben der v1 - v2 Seite noch ein weiteres Dreieck ist, dann werden v1, v2 und m1 doppelt hinzugefügt und so weiter.
  • Wer weiß? Vielleicht gibt es danach einen zusätzlichen Deduplizierungsdurchlauf.
  • Es ist möglich, dies auf der GPU entweder mit Geometrieshader oder direkter Tessellation durchzuführen. Siehe this example.
Verwandte Themen