Как я могу вычислить нормали замкнутой формы в three.js?

Я пытаюсь написать свой собственный импортер сетки для моего собственного формата файлов. В моем формате файла нет нормальных данных. Поэтому я пытаюсь вычислить нормали близкой формы и применить эти нормали к сетке.

Мое решение состоит в том, чтобы вычислить нормальный вектор для каждой грани геометрии и создать лучевую передачу от середины этих граней в направлении нормального вектора. Если этот радиопередача поражает что-то (другую плоскость), это означает, что это направление находится внутри. В этом случае я переворачиваюсь нормально, если что-то не попадает, я оставляю это таким образом.

Хотя я написал функцию с этой логикой, нормали вообще не меняются.

        function calculateNormals(object){

            for (var i = 0; i < object.geometry.faces.length; i++) {
                var vertices= object.geometry.vertices;
                var face=object.geometry.faces[i];



                var a=vertices[face.a];
                var b=vertices[face.b];
                var c=vertices[face.c];

                console.log(face.a+" "+face.b+" "+face.c+" "+face.normal.z);
                console.log(face);
                console.log(face[4]);

                var edge0=new THREE.Vector3(0,0,0);
                edge0.subVectors(a,b);

                var edge1=new THREE.Vector3(0,0,0);
                edge1.subVectors(b,c);

                var planeNormal=new THREE.Vector3(0,0,0)
                planeNormal.crossVectors(edge0,edge1);

                // console.log(planeNormal);

                //Raycast from middle point towards plane nrmal direction
                //If it hits anything it means normal direction is wrong
                var midPoint=calculateMiddlePoint([a,b,c]);
                var raycaster = new THREE.Raycaster(midPoint,planeNormal);

                var intersects = raycaster.intersectObjects([object]);
                if(intersects.length==0){
                    console.log("Normal is true");
                    face.normal=planeNormal;
                }else{
                    console.log("Normal is wrong, you should flip normal direction, length: "+intersects.length);

                    console.log("Old face");
                    console.log(face.normal);

                    var newNormal=new THREE.Vector3(-1*planeNormal.x,-1*planeNormal.y,-1*planeNormal.z);
                    console.log(newNormal);
                    face.normal=newNormal;



                    console.log("new face");
                    console.log(face.normal);
                    console.log(face);
                }

                object.geometry.faces[i]=face;


                // console.log(object.geometry.faces);

            };


            return object;


        }

1 ответ

Решение

Матей делает хорошую мысль. Порядок намотки - это то, что определяет нормальное лицо, то есть, какая сторона считается "передней". Вершинные нормали используются для затенения (с MeshPhongMaterial например). Если нормали вашей вершины указывают в противоположном направлении от нормали вашего лица, вы получите непредвиденные результаты (от плохой штриховки до абсолютно черного лица).

Все, что сказал, Geometry имеет вспомогательные функции для вычисления нормалей.

Geometry.computeFaceNormals (в зависимости от порядка намотки)

Geometry.computeFlatVertexNormals (устанавливает нормаль к вершине, совпадающую с нормалью к связанной грани)

Geometry.computeVertexNormals (устанавливает нормаль вершины к среднему значению нормали к окружающему лицу)

После того, как вы вычислили нормали, вы можете сделать второй проход, чтобы попытаться исправить их, либо переупорядочив вершины (чтобы исправить нормаль лица), либо самостоятельно пересчитав нормали вершин.

Другие вопросы по тегам