ДР/2015/Л5/hard (7т)

Считаме, че тези задача е трудна - try it on your own risk! Не поемаме отговорност в случай на изгубени много часове в коденето ѝ :)

Задачата е за всички студенти.

Целта на задачата е да се оптимизира алгоритъма за пресичане с булеви обекти, като се направи малко по-умно. В момента се търсят всички пресечни точки на лъча с геометриите, а това може да е излишно в много от случаите. Булевата функция може да се окаже удовлетворена още на първата или втората пресечна точка: например, ако имаме CsgMinus обект, при който лявата геометрия е доста по-голяма от дясната (да речем, една голяма сфера, върха на която е отрязан от куб: в болшинството случаи е достатъчно да проверим къде е първата пресечна точка с куба, и да видим, че лъча не пресича сферата въобще). По-точно, искаме да реализираме следния алгоритъм:

  1. Намираме дали сме вътре в геометриите - но ще ползваме друг метод, който не е базиран на пресичания;
  2. Намираме най-близките пресечни точки с всяка от двете геометрии;
  3. Взимаме по-близката от двете пресечни точки и проверяваме дали булевото условие е изпълнено при нея (като, подобно на стария алгоритъм, трябва да обърнем inside флага за съответната геометрия преди да направим проверката). Ако функцията връща истина - край, намерили сме пресечна точка → изход;
  4. В противен случай, изхвърляме по-близката от двете пресечни точки, и, за нейната геометрия, намираме следващата пресечна точка чрез Geometry::intersect(), актуализираме оставащото разстояние до другата пресечна точка, и отиваме на стъпка 3;
  5. Ако в даден момент се окаже, че нямаме повече пресечни точки с никоя от геометриите, край - нямаме пресичане.
  6. Правилните сметки при т.4 са критични - там е най-трудното в задачата (т.е. да осчетоводим правилно разстоянието, което трябва да се върне в крайното IntersectionData, включая всичките biasing стъпки).

    Архитектурно, трябва да се направят следните промени:
    1. Да се добави абстрактен метод isInside() на класа Geometry, и да се имплементира за Cube и Sphere (за Plane можете да сложите просто едно return false; тъй като не го ползваме).
    2. Да се слеят функционалностите на CsgOp::findAllIntersections и CsgOp::intersect; т.е. findAllIntersections не трябва да се вика въобще.

    Докато пишете вашата реализация, ползвайте тази сцена и се водете от времето за рендериране, което програмата ще ви изписва - то е ориентир как сте се справили с оптимизацията. При добро решение, би трябвало да можете да смъкнете времето с 15-20%. Не забравяйте да сверите картинката от стария метод с новия - не би трябвало да има никакви разлики!

    Крайният срок за тази задача (макар и да е в групата задачи към лекция №5) е 23.12.2015, 23:59.

Comments

Предполагам метода isInside

Предполагам метода isInside проверява дали точка е вътре в Geometry?

Да, това трябва да е

Да, това трябва да е виртуален метод на Geometry, който различните геометрии имплементират.