ДР/2011/Л5/medium (4т)
- Forums:
Да се добави възможност камерата да се позиционира чрез "lookAt" система.
Т.е. да се напише метод setPosition(), приемащ три параметъра:
- pos - позиция на камерата;
- lookAt - това е точка от сцената, която е "целта", към която гледа камерата. Т.е., лъча, изстрелян през средата на кадъра, трябва да отива в посока на точката lookAt;
- upDir - вектор, задаващ ориентацията "нагоре". Влияе, например, на roll ъгъла - досега в нашите сцени upDir беше винаги (0, 1, 0), но ако го зададем (0, -1, 0), би следвало кадъра да се обърне с главата надолу.
Методът трябва да зададе стойности Camera::pos, както и на yaw, pitch и roll ъглите (може да приемете, че методът ще бъде извикан преди Camera::beginRender()).
Задачата е за всички студенти.
За да тествате реализацията си, можете да пробвате да задавате за стойности на lookAt центровете на обектите в сцената - би следвало камерата да се обръща фронтално към тях.
Реализацията ви трябва да работи коректно и когато имаме gimbal lock - т.е., ако човек зададе на камерата да гледа право към пода, upDir трябва да работи, както би очаквал човек - промяната на upDir да оказва влияние на "завъртането на пода".
Comments
въпрос
upDir... как се използва фактически? Трябва да е перпендикулярен на вектора посока (зададен с pos и lookAt)... само Y компонентата ли играе значение от upDir? и директно да се прави на ъгъл за roll? Доколкото разбирам трябва само позицията и 3-те ъгъла да се нагласят с тази функция.
Разяснения
Сега ще обясня.
Нека v = lookAt - pos.
Дефинираме равнината α, с нормален вектор v (т.е. v е перпендикулярен на α).
Принципно, човек би очаквал upDir да е успоредна на α. Реално не е задължително да е така - можем да вземем проекцията на upDir в α (нека я означим с upDir').
Та upDir' задава посоката "отдолу-нагоре" в кадъра. Т.е., ако се върнем на онази абстракция за изстрелване на лъчи от камерата, която ползвах в лекция 4 (с трите краища на "невидим лист", през който изстрелваме лъчите), то upDir' трябва да е успоредна на (upLeft-downLeft).
Давам и по-конкретен пример. Нека камерата гледа надолу към пода: pos = (50, 80, 30), lookAt = (50, 0, 30). Тогава v = (0, -80, 0), и имаме равнината α с нормален вектор (0, -1, 0). Демек, равнината α е успоредна на XZ. В този случай, бихме могли да имаме upDir = (1, 0, 1) (ето виж - тук Y компонентата е 0!). Така, камерата гледа пода, завъртяна с ъгъл 45° спрямо оста Y. Емпирично, посоката на ротация (ако не се бъркам) трябва да е отрицателна - т.е. за да се постигнат тези настройки, трябва на Camera::pos да се зададе (50, 80, 30), pitch = -90°, yaw = 0, roll = -45° (в случая, системата е вкарана в gimbal lock, т.е. промяната на yaw и roll ъглите ще прави едно и също нещо, така че yaw = -45°, pitch = -90° и roll = 0° също е валидно решение).
Уточнение
Всъщност - към всички, които пишат тази задача - може въобще да не се ограничавате до yaw-pitch-roll системата при решаването на задачата; ако ви е по-удобно, направо заменете изцяло класа Camera (или го наследете, и заместете getScreenRay() на базовия клас с ваш код) - както ви е по-удобно.