ДР/2011/Л8/Зад. 0

Генериране на нормали

Укажете на рендера да ползва сцената "data/hw8/axe_test.retrace". От нея може да закоментирате "Node axeNode" блока - няма да ни трябва.
В случаи като примера със сърцето в тестовата сцена, няма как да пуснем normal smoothing върху обекта, защото нямаме самите нормали, т.е. няма върху какво да интерполираме. Целта на задачата е да решите този проблем, като напишете алгоритъм, който създава нормалите във върховете на сърцето чрез усредняване на геометричните нормали на прилежащите триъгълници. Т.е., за всеки връх в Mesh-а, създавате по един нормален вектор, който е "вързан" към върха, и го задавате като сума на всички геометрични нормали (gnormals) на триъгълниците, в който съответния връх участва. Понеже всеки получен нормал накрая ще представлява сума от няколко други нормала, ще трябва да ги нормирате. По-конкретно:

  1. Добавете проверка в края на loadFromOBJ метода на класа Mesh. Ако флагът hasNormals е false, значи вашият алгоритъм трябва да се изпълни
  2. Добавете толкова нормални вектора към масива normals, колкото и върха има обекта, т.е. vertices и normals трябва да имат еднакъв брой елементи. Новите елементи в normals инициализирайте с нули
  3. Обходете всички триъгълници на Mesh-а. На всеки триъгълник, сложете normal indices да съвпадат с vertex indices (n[i] = v[i]), и добавете gnormal-а на триъгълника към трите нормални вектора на триъгълника.
  4. След като приключите с триъгълниците, обходете новополучените нормални вектори и ги нормирайте (normalize())
  5. Не забравяйте да сложите и hasNormals = true

В резултат, трябва да получите нещо такова: пример

Бонус (1т):
Добавете ново bool свойство "autoSmooth" към класа Mesh (ориентирайте се по околния код в Mesh::fillProperties). Разкоментирайте съответния ред с autoSmooth от тестовата сцена.
Новото свойство да определя дали да се пуска написаният от вас алгоритъм. В резултат на това, ако в axe_test.retrace в "Mesh heart {..." разкоментирате реда "autoSmooth true", то сърцето трябва да е загладено. Ако го смените на false или махнете въобще, сърцето трябва да си стои както сега (фасетно). Не забравяйте да вземете стойността на това свойство (pb.getBoolProperty...) преди извикването на loadFromOBJ() в fillProperties() метода!