2016-02-01 17 views
5

Ich versuche, einige STL-Dateien mit Three.js zu laden. Die Modelle werden korrekt geladen, aber es gibt zu viele Dreiecke, die ich zusammenfügen/glätten möchte.Wie glätten Mesh Dreiecke in STL geladen BufferGeometry

Ich hatte glattes Laden Terrains in anderen 3D-Formaten erfolgreich angewendet, aber ich kann es nicht mit der BufferGeometry tun, die aus dem Laden einer STL-Datei mit dem STLLoader resultiert.

enter image description here _

var material = new THREE.MeshLambertMaterial({ ... }); 
var path = "./models/budah.stl"; 
var loader = new THREE.STLLoader(); 
loader.load(path, function (object) { 
       object.computeBoundingBox(); 
       object.computeBoundingSphere(); 
       object.computeFaceNormals(); 
       object.computeVertexNormals(); 
       object.normalizeNormals(); 
       object.center(); 

       // Apply smooth 
       var modifier = new THREE.SubdivisionModifier(1); 
       var smooth = smooth = object.clone(); 
       smooth.mergeVertices(); 
       smooth.computeFaceNormals(); 
       smooth.computeVertexNormals(); 
       modifier.modify(smooth); 
       scene.add(smooth); 
}); 

Das ist, was ich versucht, wirft er einen Fehler: Uncaught Typeerror: smooth.mergeVertices ist keine Funktion

Wenn ich die "mergeVertices()" Kommentar Zeile, was ich bekomme ist ein anderer Fehler: Uncaught TypeError: Kann die Eigenschaft 'Länge' von undefined nicht lesen in SubdivisionsModifier, Zeile 156.

Es scheint, dass die Beispielcodes, die ich versuche, veraltet sind (dies passiert in letzter Zeit aufgrund der massiven Änderungen in der Three.JS-Bibliothek sehr häufig). Oder vielleicht vergesse ich etwas. Tatsache ist, dass die Scheitelpunkte Null zu sein scheinen.

Vielen Dank im Voraus!

Antwort

4

Es scheint, dass ich in die falsche Richtung sah: das Glätten der Dreiecke hat nichts mit dem SubdivisionsModifier zu tun ... Was ich brauchte, war einfacher als das, berechne einfach den Scheitel, bevor du das Material anlegst, damit es SmoothShading verwenden kann von FlatShading (habe ich es richtig verstanden?).

Das Problem hier war, dass die vom STLLoader zurückgegebene BufferGeometry Vertices/Vertex nicht berechnet hat, also musste ich es manuell tun. Danach wenden Sie mergeVertices() kurz vor computeVertexNormals() und voilà! Die Dreiecke verschwinden und alles ist glatt:

var material = new THREE.MeshLambertMaterial({ ... }); 
var path = "./models/budah.stl"; 
var loader = new THREE.STLLoader(); 
loader.load(path, function (object) {     
       object.computeBoundingBox(); 
       object.computeVertexNormals(); 
       object.center(); 
       /////////////////////////////////////////////////////////////// 

       var attrib = object.getAttribute('position'); 
       if(attrib === undefined) { 
        throw new Error('a given BufferGeometry object must have a position attribute.'); 
       } 
       var positions = attrib.array; 
       var vertices = []; 
       for(var i = 0, n = positions.length; i < n; i += 3) { 
        var x = positions[i]; 
        var y = positions[i + 1]; 
        var z = positions[i + 2]; 
        vertices.push(new THREE.Vector3(x, y, z)); 
       } 
       var faces = []; 
       for(var i = 0, n = vertices.length; i < n; i += 3) { 
        faces.push(new THREE.Face3(i, i + 1, i + 2)); 
       } 

       var geometry = new THREE.Geometry(); 
       geometry.vertices = vertices; 
       geometry.faces = faces; 
       geometry.computeFaceNormals();    
       geometry.mergeVertices() 
       geometry.computeVertexNormals(); 

       /////////////////////////////////////////////////////////////// 
       var mesh = new THREE.Mesh(geometry, material); 

       scene.add(mesh); 
}); 

enter image description here

+0

Bitte jemand mir dies korrigieren: also wenn ich das Netz nur optisch glatt machen zu wollen einfach, ich muss mergeVertices() + computeVertexNormals(), bevor das Material (bessere Leistung) Anwendung. Auf der anderen Seite ermöglicht die SubdivisionsModifiers, das Netz selbst zu modifizieren, mehr und mehr Dreiecke zu machen, um phisisch glatt zu machen (niedrige Leistung auf großen Modellen). Ist dieses Konzept richtig? – spacorum

+0

Ich denke, Sie müssen "Objekt" ersetzen. von "object.geometry" (mal 4 Orte). (Mit dieser Änderung) löste Ihre Lösung mein Problem, eine glatte Schattierung aus einer OBJ-Quelldatei zu bekommen, vielen Dank :-). – steveOw

1

als, können Sie es zu BufferGeometry konvertieren zurück, weil es mehr GPU/CPU für komplexere Modelle effizient ist:

var geometry = new THREE.Geometry(); 
geometry.vertices = vertices; 
geometry.faces = faces; 
geometry.computeFaceNormals(); 
geometry.mergeVertices(); 
geometry.computeVertexNormals(); 
var buffer_g = new THREE.BufferGeometry(); 
buffer_g.fromGeometry(geometry); 
var mesh = new THREE.Mesh(buffer_g, material); 
scene.add(mesh) 
1

Dieses Problem ist für mich beim Laden einer Obj-Datei aufgetreten. Wenn Sie eine 3D-Software wie 3ds Max:

  1. Öffnen Sie die OBJ-Datei,
  2. Zum Polygonen Auswahlmodus und wählen Sie alle Polygone.
  3. Klicken Sie im Bereich Oberflächeneigenschaften auf die Schaltfläche "Automatisch glätten".
  4. Export das Modell zurück zu obj Format

Jetzt werden Sie nicht die Funktionen geometry.mergeVertices aufrufen müssen() und geometry.computeVertexNormals() ;. Laden Sie einfach das Objekt und fügen Sie es der Szene hinzu, das Netz wird glatt sein.

EDIT: Meine Obj-Dateien hatten standardmäßig meshphongmaterial und beim Ändern der Schattierungseigenschaft auf Wert 2 wurde das Netz glatt.

child.material.shading = 2