Как обнаружить перевернутые лица (перевернутые нормали)? - PullRequest
0 голосов
/ 10 апреля 2019

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

Если я понимаю, зеркальное / перевернутое / перевернутое лицо рисуется по часовой стрелке, а не против часовой стрелки. Но мы говорим о трех векторах, которые формируют лицо? Если это так, порядок намотки устанавливается в face.a, face.b и face.c? Или мне нужно сравнить значение индекса лица, чтобы узнать порядок рисования лица?

Я настроил JSFiddle , чтобы проиллюстрировать проблему: эта модель STL имеет 10 граней, и 3 из них перевернуты или перевернуты. Используя FaceNormalsHelper, вы можете видеть, что эти 3 обычных помощника указывают на внутреннюю часть модели, а не на внешнюю. Я попробовал 6 различных способов проверить это, некоторые из них извлечены из кода в computeFaceNormals (), но безуспешно. Я также изучил FaceNormalsHelper, чтобы увидеть, как он работает, но он просто рисует линию от центроида лица в направлении нормали, но ему никогда не удается вычислить, указывает ли она внутрь или снаружи.

(Примечание: чтобы перейти от одного метода к другому, необходимо изменить переменную в начале сценария. Метод 1 вручную переопределяет индекс материала этих трех граней только для визуализации неправильных (как проверка всех других методов.) Никто другой не получает хороших результатов .. Но методы 2 и 3 действительно очень близки к этому, хотя как-то две другие грани обнаруживаются как перевернутые. Интересно, имеет ли отношение угол лица к это)

РЕДАКТИРОВАТЬ: Метод, предложенный @manthrax отлично работает, сравнивая края каждой грани со всеми остальными. Если ребро нарисовано таким же образом (пример: грань 1 грани a-b совпадает с гранью 2 ребра a-b вместо b-a), она переворачивается. По сути, если у грани есть два или более ребер, помеченных как перевернутые, мы можем сказать, что перевернуто все лицо. Проверьте JSFiddle, чтобы увидеть, как он работает.

enter image description here

function paintFlippedFaces(faceCheck){
    for(var x=0; x<Object.keys(faceCheck).length; x++){
    var flipCounter = 0;
    if(faceCheck[x]['a-b']) flipCounter++;
    if(faceCheck[x]['b-c']) flipCounter++;
    if(faceCheck[x]['c-a']) flipCounter++;        
    console.log("face " + x + " has " +flipCounter+ " flipped edges" );
    if(flipCounter >= 2){
      geometry.faces[x].materialIndex = 1;
      //geometry.faces.elementsNeedUpdate = true;
    }
  } 
}

1 Ответ

1 голос
/ 10 апреля 2019

Во-первых, «перевернутые» лица абсолютно субъективны. Вам нужно определиться с некоторыми параметрами. Для выпуклого объекта существует несубъективное определение ... например, что нормаль грани, усеянная одной из вершин грани, равна> 0.

Для невыпуклых объектов вы можете сделать некоторые предположения, основываясь на порядке намотки вершин, и на том, содержит ли любые 2 ребра одинаковый порядок, подразумевая, что у вас есть 1 фронтальный и 1 обратный треугольник с общим ребром. (Какой из этих треугольников перевернут, не обязательно идентифицировать в невыпуклом случае.)

Во-первых, вам нужно будет .mergeVertices в вашей геометрии, чтобы вершины были общими для граней ... Я думаю, что stl определяет уникальные вершины для каждого треугольника, поэтому нет понятия "ребро", которое совместно используется двумя стоит.

Затем вы можете проходить через каждую грань ... и, в принципе, любые 2 ребра, которые имеют одинаковые 2 вершины, должны иметь порядок оппозиции или грани обращены друг к другу ..

Таким образом, если 2 грани имеют ребро, такое как 3,2 и 2,3, то они оба обращены в одном направлении ... и грани совпадают.

Если две разные грани обе имеют ребро 3,2 и 3,2, то они обращены в разные стороны, и вы можете пометить обе грани как перевернутые. Чаще всего помечаются лица, которые, вероятно, фактически перевернуты.

Это лучшие тесты на догадки, которые я могу придумать для определения внутри / снаружи, но это сложная проблема.

В Blender есть пара методов "пересчета нормалей" для пересчета "внутри" / "снаружи", которые, я думаю, работают по схожему принципу ... так что вы также можете взглянуть на них.

...