Домашна работа - лекция 13 / 2013

И последното домашно за тази година: само една-единствена задача, носеща 8 точки.

Сега както си имаме интерактивен режим, ще искаме да добавим към него възможност да се редактира сцената (да се променят, изтриват, добавят Node-ове). При стартиране, трябва да се зарежда сцена (както и досега), а след което, освен да летим из сцената, ще искаме да можем да я променяме.
Изисквания:

  1. Трябва да се поддържа един "текущ" Node, който е "избран на фокус". Редактиращите операции (по-долу) работят върху него. За да си личи кой е "избраният" Node, направете го мигащ. Мигането може да стане така: половин секунда Node-а е нормален, след което половин секунда е по-ярък от нормалното. За целта, в началото на кадъра в mainloop(), проверете в коя половина от секундата сте с SDL_GetTicks() и вдигнете подходящ флаг. После, в raytrace(), ако удареният най-близък Node е "избраният", и флагът указва по-висока яркост, умножавайте резултата от шейдъра по 1.2.
  2. Чрез два клавиша (например, '[' и ']', проверявайте ev.key.keysym.sym в mainloop), да може да се сменя текущо избрания обект (селекцията се сменя на предходния/следващия обект от nodes).
  3. Чрез клавишни комбинации, направете текущо избрания Node да може да се транслира, ротира, и мащабира. Например, клавишите Q A Z, да транслират, респективно, по X, Y и Z осите; WSX за ротация, EDC за скалиране. Например, ако потребителят натисне Z, то на трансформацията на текущия Node трябва да се извика translate(0, 0, Ct), като добавеното число Ct е някаква конкретна стойност (виж следващата точка).
  4. Модифициращите стойности Ct, Cr, Cs (примерни начални стойности: 5, 30°, 1.2), да могат да се променят чрез клавишите 1-9. "5" трябва да задава началите стойности, а по-ниските клавиши да задават по-ниски числа (по-фино регулиране). Обратно за по-високите. Идеята е, че човек може да започне с '5' (или по-голямо) и да позиционира, ротира и скалира грубо обекта си, след което използвайки по-ниски клавиши (4, 3, 2, 1) да задава по-финни настройки и с тях постепенно да прецизира трансформацията. Направете клавиш '-' да обръща значението на тези стойности, т.е. вместо транслация по +Z, да е транслация по -Z, ротирането да е в обратна посока, уголемяването да се превърне в свиване и т.н.
  5. Сложете някой клавиш (напр., Del) да изтрива избрания Node. След изтриването, някой друг Node става активен (освен ако списъка с Nodes остане празен).
  6. Добавете два клавиша, които да сменят шейдъра на текущо избрания Node. Т.е. всички налични шейдъри са в scene.shaders, трябва да определите кой е текущо избрания шейдър за този Node и да го смените на предходния/следващия от списъка.
  7. Добавете клавиши, с които да можете да генерирате нов обект, позициониран пред камерата. Трябва да можете да генерирате сфера, куб, цилиндър и чайник. При натискане на съответния клавиш, в геометриите се добавя нова геометрия от съответния клас, към шейдърите се добавя нов Lambert със случаен цвят, и се създава нов Node, който ползва въпросните геометрия и шейдър, и е поставен "пред" камерата (например на 10 единици пред камерата; това трябва да става само чрез транслацията на трансформацията, ротирането и скалирането остават идентитет)
  8. Добавете клавиш, който проверява дали на текущо избрания Node шейдърът е от тип Lamert и, ако да, сменя цвета му със случаен друг

Бонус (4т): направете клавиш (напр., F2), който "записва" текущата сцена в обратно в .trinity файла. Сцената после трябва да се отваря и всичките "промени" по нея да са запазени. Самият сценови файл може да изгуби произволно количество незначещи данни (вероятно няма да има коментари, може имената да са различни и т.н.).

Съвет: направете си малка, "почти празна" сцена (примерно: Environment + една сферичка), за да тествате по-лесно.

tag: homework12
Краен срок: 19.02.2012 23:59.

Comments

Изпуснах срока за домашното,

Изпуснах срока за домашното, но почнах да си имплементирам тази задача в курсовия си проект.
Направих ротацията и скалирането, но може ли малко Hint-че за транслацията - как да го направя като плавно движение.

node->transform.translate(Vector(t, 0, 0)) - например това го мести еднократно по x оста.

Трябва ли да си направя position вектор за самия Node и да смятам по формулата :
pos + dir * speed; ? Или нещо друго може да се направи ?

Защо, тя транслацията си е с

Защо, тя транслацията си е с натрупване, т.е. като дадеш Transform::transalte(5, 0, 0), обекта се мести още 5 единици по X, демек не се презаписва старата транслация, а се добавя. Само добавяш dir * speed и си готов.

Мерси за отговора, като

Мерси за отговора, като спомена натрупване се сетих да погледна Transform класа и го направих по следния начин:

node->transform.translate(node->transform.point(Vector(5, 0, 0)))

Работи добре :)