ДР/2013/Л5/hard (7т)
- Forums:
Считаме, че тази задача е трудна - try it on your own risk! Не поемаме отговорност в случай на изгубени много часове в коденето ѝ :)
Задачата е за всички студенти.
Целта на задачата е да се оптимизира алгоритъма за пресичане с булеви обекти, като се направи малко по-умно. В момента се търсят всички пресечни точки на лъча с геометриите, а това може да е излишно в много от случаите. Булевата функция може да се окаже удовлетворена още на първата или втората пресечна точка: например, ако имаме CsgDiff обект, при който лявата геометрия е доста по-голяма от дясната (да речем, една голяма сфера, върха на която е отрязан от куб: в болшинството случаи е достатъчно да проверим къде е първата пресечна точка с куба, и да видим, че лъча не пресича сферата въобще). По-точно, искаме да реализираме следния алгоритъм:
- Намираме дали сме вътре в геометриите - но ще ползваме друг метод, който не е базиран на пресичания;
- Намираме най-близките пресечни точки с всяка от двете геометрии;
- Взимаме по-близката от двете пресечни точки и проверяваме дали булевото условие е изпълнено при нея (като, подобно на стария алгоритъм, трябва да обърнем inside флага за съответната геометрия преди да направим проверката). Ако функцията връща истина - край, намерили сме пресечна точка → изход;
- В противен случай, изхвърляме по-близката от двете пресечни точки, и, за нейната геометрия, намираме следващата пресечна точка чрез Geometry::intersect(), актуализираме оставащото разстояние до другата пресечна точка, и отиваме на стъпка 3;
- Ако в даден момент се окаже, че нямаме повече пресечни точки с никоя от геометриите, край - нямаме пресичане.
- Да се добави абстрактен метод isInside() на класа Geometry, и да се имплементира за Cube и Sphere (за Plane можете да сложите просто едно return false; тъй като не го ползваме);
- Да се слеят функционалностите на CsgOp::findAllIntersections и CsgOp::intersect; т.е. findAllIntersections не трябва да се вика въобще.
Правилните сметки при т.4 са критични - там е най-трудното в задачата (т.е. да осчетоводим правилно разстоянието, което трябва да се върне в крайното IntersectionData, включая всичките biasing стъпки).
Архитектурно, трябва да се направят следните промени:
Докато пишете вашата реализация, ползвайте тази сцена и се водете от времето за рендериране, което програмата ще ви изписва - то е ориентир как сте се справили с оптимизацията. При добро решение, би трябвало да можете да смъкнете времето с 15-20%. Не забравяйте да сверите картинката от стария метод с новия - не би трябвало да има никакви разлики!