Преобразование нормалей вершин в нормали граней

У меня есть треугольный многогранник (не обязательно выпуклый) и следующая информация:

Список позиций каждой вершины. Список троек вершин, определяющих каждую грань. Список нормалей вершин (Здесь нормали вершин — это векторы из каждой вершины, которые вычисляются путем усреднения нормалей граней (см. ниже) вокруг каждой вершины).

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


person user1873329    schedule 03.12.2012    source источник
comment
Это хорошо, почему вы не рассчитали это, если хотели? Использовали ли вы метод Ньюэлла (opengl.org/wiki/Calculating_a_Surface_Normal)?   -  person mmgp    schedule 03.12.2012
comment
Я хотел бы иметь возможность использовать это, но я не знаю, какой выход из многогранника, и поэтому я не могу определить, в каком порядке брать векторное произведение. В идеале должен быть какой-то способ использовать вершинные числа, чтобы определить, какое перекрестное произведение является правильным, но я просто не уверен, как это сделать.   -  person user1873329    schedule 03.12.2012
comment
Один из способов локально определить ориентацию — рассмотреть PCA из k-окрестности (набора k точек, ближайших к данной точке), но это может не дать глобально согласованной ориентации. Я также помню несколько работ Нины Аменты по оценке полюсов Вороного и других методов, вы проверяли этого автора или что-то связанное?   -  person mmgp    schedule 04.12.2012
comment
Простое предложение состоит в том, чтобы усреднить 3 нормали, которые у вас уже есть в каждой вершине. Если это значение недостаточно точное, вычислите нормаль лица самостоятельно и сохраните ориентацию, соответствующую нормали, вычисленной путем усреднения.   -  person nbonneel    schedule 04.12.2012


Ответы (2)


Вы можете просто определить ориентацию пересекаемой нормали, поставив точку на одну из вершинных нормалей или среднюю из всех трех вершин.

Вот псевдокод:

Vec3 CalcNormalOfFace( Vec3 pPositions[3], Vec3 pNormals[3] )
{
    Vec3 p0 = pPositions[1] - pPositions[0];
    Vec3 p1 = pPositions[2] - pPositions[0];
    Vec3 faceNormal = crossProduct( p0, p1 );

    Vec3 vertexNormal = pNormals[0]; // or you can average 3 normals.
    float dot = dotProduct( faceNormal, vertexNormal );

    return ( dot < 0.0f ) ? -faceNormal : faceNormal;
}
person SeaStar    schedule 04.12.2012

Собственный код three.js для этого с тремя вершинами a, b и c:

Вы можете получить a, b и c из вершин THREE.Face3 и геометрии:

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

а затем вы делаете:

var normal = new THREE.Vector3().crossVectors( 
    new THREE.Vector3().subVectors( b, a ), 
    new THREE.Vector3().subVectors( c, a ) 
).normalize();

Но в классе THREE.Geometry также есть удобные методы для вычисления вершин и граней: computeVertexNormals и computeFaceNormals.

person Wilt    schedule 04.02.2016