🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: pl.comp.grafika.grafika3d
1 messages
1 total messages Started by Wojciech "Spook" Sura Tue, 05 Aug 2008 17:17
[OpenGL, 3D] przekształcenie 2D do 3D
#90282
Author: Wojciech "Spook" Sura
Date: Tue, 05 Aug 2008 17:17
102 lines
6517 bytes
Witam!

Crosspost na pl.comp.grafika.grafika3d; pl.sci.matematyka i
pl.comp.lang.delphi.
Followup-to na pl.comp.lang.delphi

Piszę program wykonujący pewne wizualizacje 3D. Wyświetla on na scenie
widgety umożliwiające przekształcanie jej zawartości, a są one w postaci
(mniej więcej) scrollbara (paska przewijania).

Ogólny problem polega na tym, że użytkownik przeciąga suwak scrollbara na
płaskim, dwuwymiarowym ekranie, ale przesunięcie następuje w przestrzeni
trójwymiarowej, a ja nie umiem znaleźć sprytnego sposobu na wykonanie
jakiejś transformacji 2D->3D by powiązać kliknięte przez usera miejsce z
pewnym miejscem na trójwymiarowej scenie.

Teraz bardziej formalnie. Na scenie dany jest pewien odcinek, wyznaczony -
powiedzmy - punktem zaczepienia P3D i pewnym wektorem V3D. Jest on
wizualizowany na odcinek na płaskim ekranie, który możemy opisać punktem
zaczepienia P2D i pewnym wektorem V2D.

Przekształcenie [punktu] w tą stronę realizowane jest pewnym iloczynem
macierzy:

I * P * R * R * T (x), gdzie:

I - macierz jednostkowa (4x4 !)
P - macierz perspektywy, która jest opisana na stronie:
http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/frustum.html
[1]
R - pewne macierze rotacji
T - pewna macierz translacji.

Poszczególne macierze nie grają chyba specjalnej roli - dosyć, że mogę
dobrać się bez problemów do każdej z osobna, mam kąty rotacji, mam wektor
translacji, mam współrzędne perspektywy i tak dalej. Mam też wynikową
macierz.

Wynik (x1, y1) nałożenia na macierz wektora (x, y, z, 1) (pozostałe
współrzędne są porzucane) jest liniowo skalowany na współrzędne ekranowe
(wynikowe współrzędne są w zakresie od -1 do 1) i tak wyświetlany.

Problem polega na tym, że mam dany pewien punkt (x1, y1) ekranowy (dla
uproszczenia przyjmijmy, że zawsze należy on do "ekranowego" odcinka) i
chciałbym przekształcić go teraz na punkt trójwymiarowy (x, y, z) leżący na
trójwymiarowym odcinku w odpowiednim miejscu. Teoretycznie mógłbym próbować
walczyć z macierzą odwrotną, ale nie mam niestety wartości z1 (będącej, de
facto, odległością punktu na scenie od obserwatora), więc nie jestem w
stanie wykonać przekształcenia odwrotnego.

Myślałem o liniowym przenoszeniu pozycji myszy na odcinku z 2D do 3D, ale
niestety nie jest to rozwiązanie najlepsze. Wyobraźmy sobie bowiem odcinek,
którego lewa strona jest gdzieś daleko, prawa zaś blisko. Jeśli będę
przesuwał liniowo mysz z lewej na prawą stronę, mysz będzie przesuwała się
tak:

a    b    c    d    e    f
--------------------------

Ale "marker" na trójwymiarowym odcinku zwizualizowany w dwóch wymiarach, a z
uwagi na perspektywę, mniej więcej tak:

ab c   d       e         f
--------------------------

Jak widać, funkcja f(x), gdzie x jest pozycją myszy na ekranowym odcinku,
zaś jej wynikiem jest taka pozycja na trójwymiarowym odcinku, która po
wizualizacji pokrywa się z pozycją myszy, nie jest liniowa. Niestety jednak
nie mam pojęcia, jaka jest to funkcja - nawet nie mam żadnych pomysłów,
intuicji. Fragment kwadratowej? Wykładniczej? Ale skąd się wzięła i jak
obliczyć jej współczynniki?

Pomysł niestety upadł. Pojawił się inny - aby próbować obliczyć oś widoku
odpowiadającą pozycji myszy (przeciwobraz miejsca w którym znajduje się
mysz - jak wiadomo, będzie to prosta) i stamtąd próbować powiązać ją z
odcinkiem, ale właściwie nie mam pomysłu co dalej. Kombinowałem z próbą
obliczenia jakiejś płaszczyzny w którą wbije się owa prosta, a następnie
rzutowanie miejsca trafienia na docelowy odcinek, ale i tu było sporo
problemów.

Właściwie pomysły już mi się skończyły. Czy ktoś wie może jak rozwiązać ten
problem?

Pozdrawiam -- Spook.

[1] Obszar widoku opisywany jest następująco:
* Obserwator jest w punkcie (0,0,0)
* Obszar, który jest renderowany ma postać ściętego ostrosłupa o podstawie
prostokąta;
* Jego mniejsza podstawa (ta ścięta) jest opisana wartościami top, left,
bottom i right, a znajduje się w odległości [z]near od obserwatora
* Większa podstawa jest odległa o [z]far od obserwatora (wraz z
wierzchołkiem w (0,0,0) wystarczy to do jednoznacznego wyznaczenia
ostrosłupa widoku)
* Ekranem jest mniejsza podstawa.

-- 
! ._______. Warning: Lucida Console sig!    //)    !
! || spk ||    www.spook.freshsite.pl      / _ """*!
! ||_____||        spook at op.pl         / '  | ""!
! |  ___  |   tlen: spoko_ws gg:1290136  /. __/"\ '!
! |_|[]_|_|  May the SOURCE be with you! \/)     \ !
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads