Как сгладить треугольники сетки в загруженной STL BufferGeometry
Я пытаюсь загрузить некоторые файлы STL, используя Three.js. Модели загружены правильно, но есть слишком много треугольников, которые я хотел бы объединить / сгладить.
Я успешно применил плавную загрузку ландшафта в других 3D-форматах, но я не могу сделать это с помощью BufferGeometry, которая получается в результате загрузки файла STL с помощью STLLoader.
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 );
});
Это то, что я пытался, выдает ошибку : Uncaught TypeError: smooth.mergeVertices не является функцией
Если я прокомментирую строку "mergeVertices()", я получу другую ошибку: Uncaught TypeError: Невозможно прочитать свойство 'length' undefined в SubdivisionsModifier, строка 156.
Кажется, что примеры кода, которые я пробую, устарели (это часто случается в последнее время из-за огромных изменений в библиотеке Three.JS). Или, может быть, я что-то забыл. Дело в том, что вершины кажутся нулевыми..?
Заранее спасибо!
4 ответа
Кажется, я смотрел в неправильном направлении: сглаживание треугольников не имеет ничего общего с SubdivisionsModifier... То, что мне нужно, было проще, чем просто, просто вычислите вершину ПЕРЕД применением материала, чтобы он мог использовать SmoothShading вместо FlatShading (сделал Я правильно понял?).
Проблема здесь заключалась в том, что BufferGeometry, возвращаемая STLLoader, не рассчитала вершины / вершины, поэтому мне пришлось делать это вручную. После этого примените mergeVertices() непосредственно перед computeVertexNormals() и вуаля! Треугольники исчезают и все гладко:
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 );
});
Затем вы можете преобразовать его обратно в BufferGeometry, потому что он более эффективен на GPU/CPU для более сложных моделей:
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 )
Произошла эта проблема для меня при загрузке файла obj. Если у вас есть 3D-программное обеспечение, такое как 3dsmax:
- Откройте файл obj,
- Перейдите в режим выбора полигонов и выберите все полигоны.
- Под панелью свойств поверхности нажмите кнопку "Auto Smooth".
- Экспорт модели обратно в формат obj
Теперь вам не нужно вызывать функции geometry.mergeVertices() и geometry.computeVertexNormals();. Просто загрузите объект и добавьте к сцене, сетка будет гладкой.
РЕДАКТИРОВАТЬ: мои файлы obj по умолчанию содержали meshphongmaterial, и при изменении свойства затенения на значение 2 сетка стала гладкой.
child.material.shading = 2
STL не поддерживает индекс вершины. По этой причине он продублировал вершины всех треугольников. Каждая вершина имеет нормаль как нормаль треугольника. В результате в одной и той же позиции (несколько очень замкнутых вершин) существует несколько нормальных значений. Это приводит к негладкой поверхности геометрии при использовании Нормального для расчета освещения.