Jak mogę zgiąć obiekt w OpenGL?

11

Czy istnieje sposób wygięcia obiektu, takiego jak walec lub płaszczyzna, za pomocą OpenGL?

Jestem początkującym w OpenGL (używam OpenGL ES 2.0, jeśli to ma znaczenie, chociaż podejrzewam, że matematyka ma w tym przypadku największe znaczenie, więc jest w jakiś sposób niezależna od wersji), rozumiem podstawy: tłumaczyć, obracać, transformacje macierzowe itp. Zastanawiałem się, czy istnieje technika, która pozwala faktycznie zmienić geometrię twoich obiektów (w tym przypadku przez ich zgięcie)?

Wszelkie linki, samouczki i inne odniesienia są mile widziane!

Valentin Radu
źródło

Odpowiedzi:

11

Aby „zgiąć” obiekt, należy zastosować odpowiednią kombinację translacji / obrotu / skalowania tylko do niektórych podzbiorów wierzchołków danego obiektu - prawdopodobnie odpowiednio ważąc tę ​​transformację.

Jest to przyjemny sposób, który będzie wymagał użycia większej liczby wierzchołków, niż byłoby to absolutnie konieczne do opisania oryginalnej siatki. Na przykład prosty cylinder może mieć tylko wierzchołki na obu końcach, ale jeśli chcesz, aby ten cylinder zginał się na środku, będziesz potrzebował również wierzchołków.

Jeśli wszystko, co Cię interesuje, jest bardzo specyficzne, jednorazowe deformacje bardzo prostych kształtów (takich jak wspomniana wcześniej płaszczyzna) prawdopodobnie możesz po prostu zrobić to ręcznie. Na przykład wybierz „oś zgięcia” dla swojej płaszczyzny i oblicz odpowiednie transformacje dla każdego rzędu wierzchołków płaszczyzny, aby uzyskać odpowiedni obrót wokół tej osi zgięcia w zależności od ich odległości od niego, a następnie zastosuj ją do geometrii (ewentualnie na Procesor, ponieważ byłby to najprostszy, przynajmniej początkowo). Ale taka technika nie byłaby dobrze skalowana i byłaby bardzo nużąca.

Ponieważ prawidłowe ustalenie sposobu ważenia transformacji dla każdego wierzchołka w zestawie może być tak kłopotliwe, aby uzyskać pożądaną deformację (szczególnie w przypadku bardziej praktycznych i skomplikowanych obiektów), wiele gier wykorzystuje technikę zwaną animacją szkieletu . Na wysokim poziomie wiąże się to z powiązaniem oddzielnego zestawu geometrii („szkieletu”) z siatką. Ta geometria reprezentuje kości Twojego obiektu, a Ty definiujesz (często w narzędziach do modelowania) mapowanie między wierzchołkami modelu rzeczywistego i kości szkieletu - które kości są powiązane z każdym wierzchołkiem i jak bardzo ta kość wpływa na deformację tego wierzchołka. Następnie szkielet jest animowany bezpośrednio, a animacja jest przenoszona do rzeczywistego modelu poprzez związek między kościami i ich wierzchołkami.

Zazwyczaj w tej technice odwzorowanie między szkieletem a rzeczywistą siatką jest definiowane w czasie produkcji zasobu. Animacje mogą być również budowane lub mogą być budowane proceduralnie w czasie wykonywania. Zastosowanie transformacji animacji do rzeczywistej siatki zachodzi w czasie wykonywania. Zasadniczo w czasie wykonywania nie są generowane żadne nowe wierzchołki, co oznacza, że ​​zakres dobrze wyglądających deformacji jest domyślnie ustalony w siatce podczas jej tworzenia.

Teoretycznie można również zastosować teselację i podział na siatkę w czasie wykonywania na podstawie analizy przekształceń w animacji, a tym samym wytworzyć odpowiednie wierzchołki, aby utworzyć animację, która niekoniecznie była planowana. Nie znam od razu żadnych artykułów na ten temat.

Zobacz też:

Vaillancourt
źródło
9

Jeśli chodzi o rzeczywistą matematykę wypaczania, może to być bardzo skomplikowane, dlaczego nie zaczniesz tutaj? .

Teraz porozmawiam o tym, jak możesz to zastosować, zakładając, że masz już matematykę na temat tego, jak zmniejszysz swoje deformacje.

2 drogi:

1) Każdą ramkę odwiedzaj każdy wierzchołek w modelu walca i w pewien sposób przesuwaj.

2) Przesuwaj wierzchołki w module cieniującym wierzchołków podczas renderowania. OpenGL ES 2.0 obsługuje shadery wierzchołków. W pewnym sensie masz szczęście.

Czy chcesz tylko wypaczać obiekt, który pojawia się na ekranie , czy chcesz wypaczać obiekt, aby każdy obiekt w grze wiedział, że został zdeformowany?

Jeśli zniekształcisz obiekt w module cieniującym wierzchołki, nastąpi to tylko bezpośrednio przed wyświetleniem / rasteryzacją , co oznacza, że żaden z obiektów gry nie będzie wiedział o deformacji . Jest to w porządku, jeśli po prostu wygaszacz ekranu lub deformacje są tak małe, że nie mają wpływu na zderzalny kształt obiektu.

Kiedy zniekształcasz geometrię w module cieniującym wierzchołki, oryginalne wierzchołki modelu w rzeczywistości się nie poruszają ( wydają się tylko poruszać ).

Deformacja w module cieniującym wierzchołki

Nieformalne:

nie zdeformowany

Zdeformowany

zdeformowany

To jest z rozdziału 6 samouczka cg (program nr 14).

Kod modułu cieniującego do wytworzenia tego odkształcenia jest podobny

// choose a displacement amount
float displacement = scaleFactor * 0.5 * sin(position.y * frequency * time) + 1 ;

// displace it in the direction of the normal
float4 displacementDirection = float4(normal.x, normal.y, normal.z, 0) ;

// move the vertex
float4 newPosition = position + displacement * displacementDirection ;

// transform (as normal)
oPosition = mul(modelViewProj, newPosition) ;

Tak więc widać, że dzieje się to PRAWO PRZED wyświetleniem (moduł cieniujący wierzchołek dzieje się na GPU), więc kod procesora praktycznie nie ma dostępu do przekształconej pozycji wierzchołka (istnieją sposoby przesyłania danych z GPU do procesora (głównie poprzez tekstury), ale my nie pójdę tam).

Bobobobo
źródło
8

To, co próbujesz osiągnąć, to w zasadzie podzbiór tematu deformacji siatki. Ale ponieważ jesteś początkujący, obawiam się, że tego rodzaju informacje mogą być na razie zbyt dziwne. Spróbuję jednak ustalić podstawowe pojęcia.

Aby to zrobić, potrzebujesz dwóch rzeczy:

  1. Twoja siatka musi mieć wystarczającą liczbę wierzchołków, abyś mógł ją przekształcić. Na przykład, jeśli jest to płaszczyzna, musisz upewnić się, że faktycznie została utworzona jako rodzaj siatki z wieloma wierzchołkami do odkształcenia. To samo z cylindrem. Być może uda się to osiągnąć w czasie wykonywania z teselacją, ale niewiele wiem na ten temat.
  2. Aby zdeformować wierzchołki, musisz użyć modułu cieniującego wierzchołki. Zasadniczo moduł cieniujący wierzchołków zajmuje się obliczeniem ostatecznej transformowanej pozycji każdego wierzchołka, dzięki czemu można skorzystać z możliwości zastosowania do nich wszelkich deformacji.

Nie jestem pewien, jak pomocna będzie, ale spójrz na ten zasób OpenGL, ponieważ wydaje się, że to coś, czego potrzebujesz:

http://www.ozone3d.net/tutorials/mesh_deformer_p3.php#part_3

Zrzut ekranu z tego linku:

wprowadź opis zdjęcia tutaj

Edytować

Właśnie zobaczyłem odpowiedź Josha i zgadzam się, że animacja szkieletowa jest również bardzo eleganckim sposobem na zamknięcie tego problemu, szczególnie gdy twoje deformacje stają się coraz bardziej złożone i trudniejsze do przedstawienia matematycznego.

Pamiętaj jednak, że oba powyższe punkty nadal obowiązują - możesz jedynie deformować wierzchołki, więc oczywiście muszą one istnieć przede wszystkim, dlatego twoja siatka musi mieć przyzwoitą gęstość wierzchołków. I zwykle jest to moduł cieniujący wierzchołki, który napędza szkieletową animację i dokonuje mieszania wierzchołków i tak dalej.

Nawiasem mówiąc, możesz to zrobić również na procesorze, ale obecnie jest to zwykle lepsza opcja, aby zrobić je na GPU, dlatego kładę nacisk na moduł cieniujący wierzchołek i powinieneś się temu przyjrzeć. W rzeczywistości nie jest to wcale o wiele trudniejsze programowo niż robienie tego na CPU.

David Gouveia
źródło