Как сгладить треугольники сетки в загруженной 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 is not a function

Если я прокомментирую строку «mergeVertices()», я получу другую ошибку: Uncaught TypeError: Cannot read property 'length' of undefined в SubdivisionsModifier, строка 156.

Кажется, что пробные коды, которые я пробую, устарели (в последнее время это часто происходит из-за массовых изменений в библиотеке Three.JS). Или, может быть, я что-то забываю. Дело в том, что вершины кажутся нулевыми..?

Заранее спасибо!


person spacorum    schedule 01.02.2016    source источник


Ответы (4)


Кажется, я искал не в том направлении: сглаживание треугольников не имеет ничего общего с SubdivisionsModifier... Мне нужно было проще, просто вычислить вершину ДО применения материала, чтобы он мог использовать SmoothShading вместо FlatShading (сделал Я правильно понял?).

Проблема здесь заключалась в том, что BufferGeometry, возвращаемый STLLoader, не вычислял вершины/вершины, поэтому мне пришлось делать это вручную. После этого примените mergeVertices() непосредственно перед calculateVertexNormals() и вуаля! Треугольники исчезают и все гладко:

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

введите описание изображения здесь

person spacorum    schedule 01.02.2016
comment
Пожалуйста, кто-нибудь поправьте меня в этом: поэтому, если я хочу просто визуально сделать сетку гладкой, мне нужно выполнить mergeVertices() + calculateVertexNormals() перед применением материала (лучшая производительность). С другой стороны, SubdivisionsModifiers позволяет изменять саму сетку, делая все больше и больше треугольников физически сглаженными (низкая производительность на больших моделях). Верна ли эта концепция? - person spacorum; 01.02.2016
comment
Я думаю, вам нужно заменить объект. по object.geometry (умножить на 4 местоположения). (С этим редактированием) ваше решение решило мою проблему с попыткой получить плавное затенение из исходного файла OBJ, большое спасибо :-). - person steveOw; 03.12.2016

Затем вы можете преобразовать его обратно в 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 )
person Zydnar    schedule 29.08.2016

У меня возникла эта проблема при загрузке файла obj. Если у вас есть 3D-программа, такая как 3dsmax:

  1. Откройте файл obj,
  2. Перейдите в режим выбора полигонов и выберите все полигоны.
  3. На панели свойств поверхности нажмите кнопку "Автоматическое сглаживание".
  4. Экспортируйте модель обратно в формат obj

Теперь вам не нужно будет вызывать функции геометрии.mergeVertices() и геометрии.computeVertexNormals();. Просто загрузите объект и добавьте его в сцену, сетка будет гладкой.

РЕДАКТИРОВАТЬ: в моих файлах obj по умолчанию был материал meshphongmaterial, и при изменении свойства затенения на значение 2 сетка стала гладкой.

child.material.shading = 2
person coderSree    schedule 01.02.2017

STL не поддерживает индекс вершин. По этой причине у него дублируются вершины всех треугольников. Каждая вершина имеет свою нормаль, как нормаль треугольника. В результате в одной и той же позиции (несколько очень закрытых вершин) есть несколько значений нормали. Это приводит к негладкой поверхности геометрии при использовании Normal для расчета освещения.

person Karoshi    schedule 27.06.2021