Wpis pokazuje w jaki sposób przenieść punkt kliknięcia o jeden wymiar dalej czyli jak na podstawie współrzędnych ekranowych (2D) obliczyć współrzędne odpowiadającego im punktu w przestrzeni (3D).
FLEX: 3.0, Papervision3D: 2.0.883
Pobierz źródła przykładu
Poniższy kod napisałem w oparciu o tekst Andy’ego Zupko Dragging in 3D – The Right Way.
Zadanie przeniesienia współrzędnych kliknięcia do przestrzeni, w skrócie, będzie polegało na znalezieniu punktu przecięcia prostej z płaszczyzną. Prostą zdefiniujemy na podstawie współrzędnych położenia kamery oraz punktu kliknięcia. Płaszczyznę natomiast określimy jednoznacznie za pomocą wektora normalnego tożsamego z wektorem wyznaczającym kierunek spoglądania kamery oraz dowolnego punktu leżącego na tej płaszczyźnie.
Tym wszystkim zajmie się funkcja convert2Dto3D, której kod zamieszczam poniżej wraz z objaśnieniem:
Funkcja convert2Dto3D przyjmuje dwa parametry:
distance typu Number – Odległość od kamery w jakiej będzie znajdować się punkt w przestrzeni.
viewportClickPoint typu Number2D – Współrzędne kliknięcia w viewport (viewport.containerSprite.mouseX, viewport.containerSprite.mouseY).
var unprojectedPoint:Number3D;
var intersectPoint:Number3D;
var plane3d:Plane3D = new Plane3D();
var planeNormal: Number3D = forward.clone();
Matrix3D.multiplyVector(camera.transform,planeNormal);
planeNormal.normalize();
var planeVertex:Number3D = planeNormal.clone();
plane3d.setNormalAndPoint(planeNormal, planeVertex);
unprojectedPoint= camera.unproject(viewportClickPoint.x,viewportClickPoint.y);
unprojectedPoint= Number3D.add(unprojectedPoint, camera.position);
intersectPoint= plane3d.getIntersectionLineNumbers(camera.position, unprojectedPoint);
intersectPoint.normalize();
intersectPoint.multiplyEq(distance);
return intersectPoint;
}
Zdefiniowanie płaszczyzny
Zmienna planeNormal początkowo jest kopią wektora forward wyznaczającego kierunek „do przodu” czyli ten, w którym przez cały czas spogląda kamera:
Ponieważ możemy obracać kamerą wektor ten ulega zmianie zgodnie ze zmianą wartości kątów obrotu kamery. Żeby znać aktualny wektor wyznaczający kierunek w jakim spogląda kamera musimy pomnożyć wektor forward przez macierz transformacji kamery. Po wykonaniu operacji mnożenia normalizujemy otrzymany wektor.
Żeby jednoznacznie określić płaszczyznę w przestrzeni musimy jeszcze znać współrzędne dowolnego punktu leżącego na tej płaszczyźnie. W tym celu użyjemy współrzędnych obliczonego przed chwilą wektora, który możemy potraktować jako punkt leżący w satysfakcjonującym nas miejscu. Nie musimy przejmować się odległością w jakiej znajdzie się punkt przecięcia prostej z płaszczyzną ponieważ pod koniec skorygujemy ją sobie zgodnie z parametrem distance.
Zdefiniowanie prostej
Jednym z punktów, który posłuży do zdefiniowania prostej w przestrzeni będzie punkt położenia kamery. Drugim zaś punkt powstały przez zastosowanie metody unproject obiektu kamery na współrzędnych kliknięcia. Funkcja unproject wykonuje operację odwrotną do rzutowania (projekcji współrzędnych 3D na 2D) w wyniku, której otrzymujemy punkt 3D leżący na przedniej płaszczyźnie odcinania. Na koniec dodajemy do drugiego punktu współrzędne położenia kamery w celu uzyskania jego rzeczywistego położenia w przestrzeni.
Punkt przecięcia prostej i płaszczyzny
Punkt przecięcia prostej i płaszczyzny oblicza metoda getIntersectionLineNumbers obiektu Plane3D, która jako parametry przyjmuje dwa punkty definiujące prostą.
Korekcja współrzędnych punktu przecięcia
Założeniem naszej funkcji jest obliczanie współrzędnych 3D klikniętego punktu w odległości od kamery określonej przez parametr distance. W tym celu wystarczy znormalizować otrzymany punkt przecięcia i pomnożyć przez parametr distance.