three.js — разделить грани с длинными ребрами на две грани

Я пишу скрипт, который разделяет слишком длинные края граней (сделайте 2 грани вместо 1 большой)

Экспорт результатов в файл .obj

Геометрия уменьшается нормально, но после рендеринга уменьшенные лица имеют неправильное отражение света, а событие WebGl не показывает некоторые лица. https://yadi.sk/i/yU33fJ51dJaVP

Для новых (дочерних) лиц я сохраняю нормаль и все свойства родительского большого лица.

Вот код:

var loader = new global.THREE.OBJMTLLoader();
var geometry = loader.load("source.obj").children[0].geometry;

var uvs = [];
var limiter = function () {
            var baseLength = 80;
            var createdVertex = {};
            var faces=[];
            var faceVertexUvs = [];
            var l = geometry.faces.length;
            geometry.faces.forEach(function(cFace, i){

                var fromToProgress = function (from, to, third, splitedEdge) {
                    var vFrom = geometry.vertices[from],
                        vTo = geometry.vertices[to],
                        vThird = geometry.vertices[third],
                        newVertexIndex;

                    if (vFrom.distanceTo(vTo) > baseLength) {
                        var exists = createdVertex[from + "_" + to] || createdVertex[to + "_" + from];
                        if (exists) {
                            newVertexIndex = exists;
                        } else {
                            var newVertex = getTheCenter(vFrom, vTo);
                            geometry.vertices.push(newVertex);
                            newVertexIndex = geometry.vertices.length - 1;
                            createdVertex[from + "_" + to] = newVertexIndex;
                        }

                        makeFace(from, newVertexIndex, third, splitedEdge, 0);
                        makeFace(newVertexIndex, to, third, splitedEdge, 1);
                        return true;
                    }
                    return false;
                };
                var makeFace = function (a, b, c, splitedEdge, side) {

                    var templ = cFace.clone();
                    templ.a = a;
                    templ.b = b;
                    templ.c = c;

                    templ.vertexNormals = [ templ.normal, templ.normal, templ.normal];

                    faces.push(templ);
                    splitUvs(templ, splitedEdge, side);
                };
                var copyUvs = function () {
                    faceVertexUvs[faces.length - 1] = geometry.faceVertexUvs[0][i];
                };

                var splitUvs = function (face, splitedEdge, side) {
                    var a,b,c,d;
                    var bigTri = geometry.faceVertexUvs[0][i];
                    if (splitedEdge === 'ab') {
                        if (side === 0) {
                            a = bigTri[0];
                            b = getTheCenter(bigTri[0], bigTri[1]);
                            c = bigTri[2];
                        } else {
                            a = getTheCenter(bigTri[0], bigTri[1]);
                            b = bigTri[1];
                            c = bigTri[2];
                        }
                    }
                    if (splitedEdge === 'ac') {
                        if (side === 0) {
                            a = bigTri[0];
                            b = bigTri[1];
                            c = getTheCenter(bigTri[0], bigTri[2]);
                        } else {
                            a = getTheCenter(bigTri[0], bigTri[2]);
                            b = bigTri[1];
                            c = bigTri[2];
                        }
                    }
                    if (splitedEdge === 'bc') {
                        if (side === 0) {
                            a = bigTri[0];
                            b = bigTri[1];
                            c = getTheCenter(bigTri[1], bigTri[2]);
                        } else {
                            a = bigTri[0];
                            b = getTheCenter(bigTri[1], bigTri[2]);
                            c = bigTri[2];
                        }
                    }

                    faceVertexUvs[faces.length - 1] = [a,b,c];
                };
                // Center of section
                var getTheCenter = function (vFrom, vTo) {
                    return vFrom.clone().add(vTo).multiplyScalar(0.5);
                }

                if (fromToProgress(cFace.a, cFace.b, cFace.c, 'ab')) return;
                if (fromToProgress(cFace.a, cFace.c, cFace.b, 'ac')) return;
                if (fromToProgress(cFace.b, cFace.c, cFace.a, 'bc')) return;
                faces.push(cFace);
                copyUvs();

            });
            geometry.faces = faces;
            geometry.faceVertexUvs[0] = faceVertexUvs;
        };

limiter();

geometry.computeFaceNormals();
geometry.computeVertexNormals();
geometry.computeMorphNormals();

var exp = new THREE.OBJExporter();
console.log(exp.parse(geometry)); 

P.S. Может быть кто-нибудь знает существующее решение для этой цели?


person Rax Wunter    schedule 11.12.2014    source источник
comment
Является ли TessellateModifier тем, что вы ищете?   -  person WestLangley    schedule 11.12.2014
comment
То есть! Я заново изобрел велосипед, спасибо!   -  person Rax Wunter    schedule 11.12.2014


Ответы (1)


Если вы хотите разделить грани с ребрами длиннее указанного значения на две грани, вы можете использовать THREE.TessellateModifier, который вы найдете в папке examples/modifiers.

Вы можете вызвать его повторно, если хотите. Вот так:

var tessellateModifier = new THREE.TessellateModifier( LENGTH );

for ( var i = 0; i < N; i ++ ) {

    tessellateModifier.modify( geometry );

}

три.js р.69

person WestLangley    schedule 11.12.2014