2016-02-01 33 views
5

Próbuję załadować niektóre pliki STL za pomocą pliku Three.js. Modele są poprawnie załadowane, ale jest zbyt wiele trójkątów, które chciałbym scalić/wygładzić.Jak wygładzić trójkąty siatki w załadowanej pamięci STL BufferGeometry

Udało mi się zastosować gładkie tereny do ładowania w innych formatach 3D, ale nie mogę tego zrobić za pomocą BufferGeometry, która wynika z ładowania pliku STL za pomocą STLLoader.

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); 
}); 

To co próbowałem, to zgłasza błąd: Uncaught TypeError: smooth.mergeVertices nie jest funkcją

Gdybym komentować "mergeVertices()" linia, pojawia się inny błąd: Uncaught TypeError: Nie można odczytać właściwości "length" z undefined w SubdivisionsModifier, wiersz 156.

Wygląda na to, że przykładowe kody, które próbuję, są nieaktualne (dzieje się to ostatnio dużo z powodu ogromnych zmian w bibliotece Three.JS). A może coś zapomnę. Faktem jest, że wierzchołki wydają się mieć wartość zerową ...?

Z góry dziękuję!

Odpowiedz

4

Wygląda na to, że patrzyłem w niewłaściwym kierunku: wygładzenie trójkątów nie ma nic wspólnego z SubdivisionsModifier ... To, czego potrzebowałem, było łatwiejsze, wystarczy obliczyć wierzchołek PRZED zastosowaniem materiału, aby mógł zamiast tego użyć SmoothShading FlatShading (czy mam to dobrze?).

Problem polegał na tym, że BufferGeometry zwrócona przez STLLoader nie obliczyła wierzchołków/wierzchołków, więc musiałem to zrobić ręcznie. Następnie zastosuj polecenie mergeVertices() tuż przed computeVertexNormals() i voilà! Trójkąty dissappear i wszystko jest płynne:

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

Proszę ktoś mnie poprawić na to: tak, jeśli chcę po prostu zrobić oczek wygładzić tylko wizualnie, muszę mergeVertices() + computeVertexNormals() przed nałożeniem materiału (lepsza wydajność). Z drugiej strony, SubdivisionsModifiers pozwala modyfikować samą siatkę, dzięki czemu coraz więcej trójkątów wygładza się fizycznie (niska wydajność w dużych modelach). Czy ta koncepcja jest właściwa? – spacorum

+0

Myślę, że musisz zastąpić "obiekt". przez "object.geometry" (razy 4 lokalizacje). (Z tą edycją) twoje rozwiązanie rozwiązało mój problem, próbując uzyskać płynne cieniowanie z pliku źródłowego OBJ, dlatego bardzo dziękuję :-). – steveOw

1

niż można przekonwertować go z powrotem do BufferGeometry, bo to bardziej GPU/CPU wydajny dla bardziej złożonych modeli:

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

Zdarzyło mi się ten problem podczas ładowania pliku obj. Jeśli masz 3d oprogramowania jak 3dsmax:

  1. Otwórz plik obj,
  2. przejść do trybu wyboru wielokątów i zaznaczyć wszystkie wielokąty.
  3. W panelu Właściwości powierzchni kliknij przycisk "Automatyka wygładzania".
  4. Export model z powrotem do formatu obj

Teraz nie będą musieli wezwać geometry.mergeVertices Funkcje() i geometry.computeVertexNormals() ;. Wystarczy załadować obiekt i dodać do sceny, siatka będzie gładka.

EDYCJA: Moje pliki obj miały domyślnie meshphongmaterial i po zmianie właściwości cieniowania na wartość 2 mesh stał się gładki.

child.material.shading = 2 
Powiązane problemy