Jestem w trakcie opracowywania podstawowego edytora 3D. Używa OpenGL do renderowania świata 3D. Obecnie moja scena to tylko kilka pudełek o różnych rozmiarach i jestem na etapie, w którym chcę móc wybrać każde pudełko, a następnie przesuwać / skalować / obracać je, aby uzyskać dowolną transformację.
Jak mogę rozwiązać problem zaimplementowania zarówno renderowania gadżetów tych narzędzi (lub uchwytów, lub jak zwykle nazywają je ludzie), a także wybierania ich na każdej osi, aby wykonać zmianę transformacji za pomocą myszy? Dla jasności:
Moje dotychczasowe badania sugerowały, że najczystszym podejściem jest posiadanie wyrównanego do osi obramowania na strzałkę w gizmo i kolejnego na kwadrat (te, które poruszają obiektem w płaszczyźnie zamiast pojedynczej osi), a następnie rzucają promień z myszy ustaw pozycję i zobacz, z czym się zderza. Ale dla mnie jest to wciąż zbyt abstrakcyjne, doceniłbym dalsze wskazówki na temat tego, jak pójdzie ten algorytm (pseudokod jest więcej niż wystarczający)
Odpowiedzi:
W pewnym momencie w e-on utrzymałem gadżety z linii produktów Vue .
Mogę ci powiedzieć, że zajmie ci to wiele dni, w pełnym wymiarze godzin.
O ile nie znajdziesz jakiejś biblioteki lub super sprytnego sposobu, klasycznym sposobem jest uzyskanie współrzędnej myszy w oknie po kliknięciu, jeśli jest to względna współrzędna do rzutni, możesz po prostu podzielić xiy przez szerokość i wysokość, możesz uzyskaj wektor (liczba zmiennoprzecinkowa 2d) w zakresie [0,1]. odejmij (0,5,0,5), aby dostać się do zakresu [-0,5, 0,5] zarówno dla x, jak i y.
Następnie wykonujesz promień z tej współrzędnej, używając xiy po prostu jako promień xiy, i ustawiasz z na odległość ogniskową. czasami proporcje to ból w tyłku podczas tej operacji. Trochę majstrowania i błąd próbny naprawi cię.
Następnie musisz sprawdzić skrzyżowanie z elementami gizmos, albo masz siatkę, którą wygenerowałeś, albo zamodelowałeś w blenderze lub innym DCC, albo części siatki, które mogą się między sobą przesuwać ... Po prostu użyj tej części siatki jako promienia / zapytanie o przecięcie trójkąta.
Lub jeśli masz, promień / cylinder, promień / kula zgodnie z twoim wyglądem i częściami Gizmo.
Musisz mieć procedury przecinania, które są w stanie zastosować macierz transformacji na zderzających się operacjach pierwotnych . Niezwykle ważne, ponieważ twoje gadżet będzie tłumaczył obiekt, który ma się poruszyć, będzie się obracał i będzie skalował się wraz z odwrotnością odległości do kamery, dzięki czemu zachowa ustalony rozmiar na ekranie.
Następnie masz część interakcji, najłatwiej jest wziąć deltę punktu, w którym mysz była po raz pierwszy zdarzeniem „mysz w dół”, i bieżącą pozycję „Ruch myszy”, w czystym 2D, i użyć tej delty jako bieżącego ruchu osi w przestrzeni świata pomnożonej przez niektóre
k
, które zdecydujesz empirycznie. Zgodnie z jednostkami wewnętrznymi kontra piksel kontra aktualna skala zoomu itp.Ostatnim krokiem jest po prostu nałożenie matrycy Gizmo na manipulowany obiekt, aby podążał za nim.
Mówię wam, że jest to dość piekielna podróż do wdrożenia, a jeśli robicie to w wolnym czasie, spodziewajcie się więcej niż tydzień. Wiele tygodni, jeśli całkowicie odkrywasz pole. Ponad miesiąc, jeśli weekendy są zajęte innymi zajęciami :)
Sugeruję, aby pobrać Embree 2.0 z Intel, aby wykonać dla ciebie zapytanie o skrzyżowanie promień / trójkąt, więc nie musisz się martwić o kodowanie. Czy możesz bezlitośnie kopiować / wklejać i dostosowywać kod z blendera ... Myślę, że przenieśli się na licencję Apache? Powinno to być możliwe zgodnie z prawem.
źródło
Do manipulatora-tłumacza używam algorytmu następującego:
1) Po najechaniu myszką musimy sprawdzić, czy promień przecina strzałkę. Na przykład rozważamy strzałkę X. Konstruujemy Ray w przestrzeni świata (na podstawie fragmentu kamery i pozycji myszy). Budujemy płaszczyznę, na której leży oś x: jej normalna wartość jest równa V przecina X przecina V, gdzie V - wektor od środka do kamery, X - reprezentuje oś x. Następnie przecinamy promień z płaszczyzną i dlatego znajdujemy punkt przecięcia we współrzędnych świata. Następnie rzutujemy segment osi x i wynikowy punkt z powrotem na ekran, znajdujemy odległość między rzutowanym segmentem a rzutowanym punktem na ekranie. jeśli jest mniejsza niż kilka pikseli, mysz przecina oś. Obliczamy również wektor delta przestrzeni świata między środkiem selekcji a naszym przecięciem.
Tę procedurę wykonujemy dla 3 osi, więc znajdujemy odległości do wszystkich osi. Znajdź minimalną odległość. więc ustaliliśmy, z którą osią przecina się mysz.
2) Po poruszeniu myszą. wiemy o jaką oś porusza się obiekt (od 1). znajdujemy przecięcie promienia z płaszczyzną w przestrzeni świata (jak w 1). dodatkowo rzutujemy punkt przecięcia na linię, po której porusza się obiekt. końcowa pozycja manipulatora = skrzyżowanie + delta.
źródło