Czy ktoś ma algorytm do tworzenia kuli proceduralnie z la
ilością linii szerokości, lo
ilością linii długości i promieniem r
? Potrzebuję go do pracy z Unity, więc pozycje wierzchołków muszą zostać zdefiniowane, a następnie trójkąty zdefiniowane za pomocą indeksów ( więcej informacji ).
EDYTOWAĆ
Udało mi się sprawić, że kod działa w jedności. Ale myślę, że mogłem zrobić coś złego. Kiedy podkręcam detailLevel
, jedyne co robi to dodawanie kolejnych wierzchołków i wielokątów bez ich przesuwania. Zapomniałem czegoś?
EDYCJA 2
Próbowałem przeskalować siatkę wzdłuż jej normalnych. Oto co mam. Chyba coś mi umknęło. Czy mam skalować tylko niektóre normalne?
unity
procedural-generation
3d-meshes
Daniel Pendergast
źródło
źródło
vertices[i] = normalize(vertices[i])
. Nawiasem mówiąc, daje to również nowe, prawidłowe wartości normalne, więc powinieneś to zrobićnormals[i] = vertices[i]
później.Odpowiedzi:
Aby uzyskać coś takiego:
Utwórz dwudziestościan (20-stronna regularna bryła) i podziel ściany, aby uzyskać kulę (patrz kod poniżej).
Pomysł jest w zasadzie:
Podziel każdą twarz na cztery równe twarze. Za każdym razem, gdy to zrobisz, czterokrotnie zwiększy liczbę twarzy w modelu.
i0
,i1
ii2
są wierzchołkami oryginalnego trójkąta. (Właściwie indeksy w buforze wierzchołków, ale to już inny temat).m01
jest punktem środkowym krawędzi(i0,i1)
, m12 jest punktem środkowym krawędzi(i1,12)
im02
jest oczywiście punktem środkowym krawędzi(i0,i2)
.Za każdym razem, gdy dzielisz twarz, upewnij się, że nie tworzysz duplikatów wierzchołków. Każdy punkt środkowy będzie współdzielony przez jedną inną ścianę źródłową (ponieważ krawędzie są wspólne między ścianami). Poniższy kod bierze to pod uwagę, utrzymując słownik nazwanych punktów środkowych, które zostały utworzone, i zwraca indeks wcześniej utworzonego punktu środkowego, gdy jest on dostępny, zamiast tworzenia nowego.
Powtarzaj, aż osiągniesz żądaną liczbę ścian dla swojej kostki.
Po zakończeniu normalizuj wszystkie wierzchołki, aby wygładzić powierzchnię. Jeśli tego nie zrobisz, zamiast kuli dostaniesz dwudziestościan o wyższej rozdzielczości.
Voila! Jesteś skończony. Konwertuj powstałe bufory wektorowe i indeksowe na
VertexBuffer
aIndexBuffer
i rysuj za pomocąDevice.DrawIndexedPrimitives()
.Oto, czego użyłbyś w swojej klasie „Sphere” do stworzenia modelu (typy danych XNA i C #, ale powinno być całkiem jasne):
I
GeometryProvider
klasaźródło
int
tablicy? A co robi.Select(i => i + vertices.Count)
?.Select(i => i + vertices.Count)
ogóle nie działa dla mnie. Czy jest to funkcja tylko XNA?Rozważmy parametryczną definicję kuli:
gdzie theta i phi to dwa narastające kąty, które będziemy określać jako
var t
i,var u
a Rx, Ry i Rz są niezależnymi promieniami (promieniami) we wszystkich trzech kierunkach kartezjańskich, które w przypadku kuli będą zdefiniowane jako jeden pojedynczy promieńvar rad
.Rozważmy teraz fakt, że
...
symbol wskazuje iterację wskazującą na użycie pętli. Pojęciestacks
irows
brzmi „ile razy będziesz iterować”. Ponieważ każda iteracja dodaje wartość t lub u, im więcej iteracji, tym mniejsza wartość, a zatem dokładniejsza jest krzywizna kuli.„Sfera rysunek” Warunkiem funkcja jest mieć następujące parametry podane:
int latitudes, int longitudes, float radius
. Warunki końcowe (wynik) mają zwrócić lub zastosować obliczone wierzchołki. W zależności od tego, jak zamierzasz tego użyć, funkcja może zwrócić tablicęvector3
(wektory trójwymiarowe) lub, jeśli używasz jakiegoś prostego OpenGL, przed wersją 2.0, możesz chcieć zastosować wierzchołki bezpośrednio do kontekstu.NB: Zastosowanie wierzchołka w openGL wywołuje następującą funkcję
glVertex3f(x, y, z)
. W przypadku przechowywania wierzchołków dodalibyśmy nowyvector3(x, y, z)
dla łatwiejszego przechowywania.Również sposób, w jaki poprosiłeś o działanie systemu szerokości i długości geograficznej, wymagał dostosowania definicji kuli (w zasadzie przełączania z i y), ale to po prostu pokazuje, że definicja jest bardzo plastyczna i że możesz swobodnie przełączać się między parametry x, y i z, aby zmienić kierunek, w którym rysowana jest kula (gdzie znajdują się szerokości i długości geograficzne).
Teraz spójrzmy na to, jak będziemy robić szerokości i długości geograficzne. Szerokości są reprezentowane przez zmienną
u
, iterują od 0 do 2π radianów (360 stopni). Możemy zatem zakodować jego iterację w następujący sposób:Teraz długości geograficzne są reprezentowane przez zmienną
t
i iterują się od 0 do π (180 stopni). dlatego poniższy kod wygląda podobnie do poprzedniego:(Należy pamiętać, że pętle są Inclusive od tam stan terminala, ponieważ przedział dla parametrycznego integracji wynosi od 0 do 2 n Inclusive . Dostaniesz częściową sferę jeśli warunki są non-inclusive).
Teraz, zgodnie z prostą definicją sfery, możemy uzyskać definicję zmiennej w następujący sposób (załóżmy
float rad = radius;
):Jeszcze jedno ważne ostrzeżenie! W większości przypadków będziesz używać jakiejś formy OpenGL, a nawet jeśli nie, nadal będziesz musiał to zrobić. Obiekt trójwymiarowy wymaga zdefiniowania kilku wierzchołków. Zazwyczaj osiąga się to przez zapewnienie następnego obliczalnego wierzchołka.
Tak jak na powyższym rysunku są różne współrzędne
x+∂
iy+∂
możemy z łatwością wygenerować trzy inne wierzchołki dla dowolnego pożądanego zastosowania. Pozostałe wierzchołki to (załóżmyfloat rad = radius;
):Na koniec, oto działająca pełna funkcja, która zwróciłaby wszystkie wierzchołki kuli, a druga pokazuje działającą implementację kodu OpenGL (jest to składnia w stylu C, a nie JavaScript, to powinno działać ze wszystkimi językami w stylu C, w tym C # podczas korzystania z Unity).
Kod OpenGL:
PS Być może zauważyłeś to oświadczenie
rad = radius;
. Umożliwia to modyfikację promienia w pętli na podstawie położenia lub kąta. Oznacza to, że możesz zastosować hałas do kuli, aby ją zszorstkować, dzięki czemu będzie wyglądać bardziej naturalnie, jeśli pożądany efekt będzie podobny do planety. Na przykładfloat rad = radius * noise[x][y][z];
Claude-Henry.
źródło
rad
. Teraz tworzysz tę jedną nogę z trójkąta i sugerujesz, że jest również przeciwprostokątna tego trójkątarad
. To skutecznie daje promieńrad * sqrt(2)
.Jakiś czas temu stworzyłem coś takiego, aby stworzyć kulę z kostek dla zabawy i nauki. To nie jest zbyt trudne. Zasadniczo bierzesz funkcję, która tworzy okrąg wierzchołków, a następnie przechodzisz przez przyrosty wysokości, które chcesz tworzyć koła na każdej wysokości w promieniu wymaganym do utworzenia kuli. Tutaj zmodyfikowałem kod, aby nie był dla kostek:
Teraz ten kod po prostu stworzy punkty dla szerokości geograficznej. Możesz jednak prawie użyć tego samego kodu, aby utworzyć linie długości geograficznej. Tyle, że będziesz musiał obracać się między kolejnymi iteracjami i tworzyć wokół siebie pełne koło
degreeStep
.Niestety, nie jest to pełna odpowiedź ani odpowiedź na temat Jedności, ale mam nadzieję, że to pomoże.
źródło
Czy nie możesz po prostu zacząć od prostego kształtu, może to być pudełko o odległości od środka do rogu. Aby stworzyć bardziej szczegółową kulę, podziel wszystkie wielokąty, a następnie przesuń wierzchołki na odległość r od środka, tak aby wektor przechodził przez ich bieżącą pozycję.
Powtarzaj, aż będzie wystarczająco sferyczny dla swoich upodobań.
źródło
Czy potrzebujesz geometrii 3D, czy tylko kształtu?
Możesz stworzyć „fałszywą” kulę za pomocą pojedynczego kwadratu. Po prostu nałóż na nią kółko i cieniuj je poprawnie. Ma to tę zaletę, że będzie miała dokładnie wymaganą rozdzielczość niezależnie od odległości od kamery lub rozdzielczości.
Tutaj jest tutorial .
źródło
oto kod dla dowolnej liczby równomiernie rozmieszczonych wierzchołków kuli, jej jak pomarańczowa skórka nawija linię kropek wokół kuli w spiralę. potem, jak dołączyć do wierzchołków, zależy od ciebie. możesz użyć sąsiednich kropek w pętli jako 2 każdego trójkąta, a następnie znajdź trzeci byłby proporcjonalny jeden obrót wokół kuli wyżej lub niżej ... możesz również wykonywać trójkąty po pętli i na najbliższym sąsiadu, robi to ktoś znasz lepszy sposób?
};
źródło
Chociaż David ma absolutną rację w swojej odpowiedzi, chcę zaoferować inną perspektywę.
W ramach mojego zadania generowania treści proceduralnych spojrzałem (między innymi) na dwudziestościan w porównaniu z bardziej tradycyjnymi podzielonymi sferami. Spójrz na te generowane proceduralnie sfery:
Oba wyglądają jak idealnie poprawne kule, prawda? Spójrzmy na ich szkielety:
Wow, co się tam stało? Druga kula w wersji szkieletowej jest tak gęsta , że wygląda na teksturowaną! Powiem ci o tajemnicy: druga wersja to dwudziestościan. To prawie idealna kula, ale ma wysoką cenę.
Sfera 1 wykorzystuje 31 podpodziałów na osi x i 31 podpodziałów na osi z, co daje łącznie 3 844 ścianki.
Sfera 2 wykorzystuje 5 rekurencyjnych podziałów, co daje w sumie 109 220 twarzy.
Ale dobrze, to nie do końca uczciwe. Zmniejszmy znacznie jakość:
Sfera 1 wykorzystuje 5 podziałów na osi X i 5 podziałów na osi Z, co daje łącznie 100 ścian.
Sfera 2 wykorzystuje 0 rekurencyjnych podziałów, co daje łącznie 100 twarzy.
Używają tej samej liczby twarzy, ale moim zdaniem kula po lewej wygląda lepiej. Wygląda mniej nierówno i jest bardziej okrągły. Zobaczmy, ile twarzy generujemy za pomocą obu metod.
Dwudziestościan:
Podzielona kula:
Jak widać, dwudziestościan rośnie w tempie wykładniczym do trzeciej potęgi! Jest tak, ponieważ dla każdego trójkąta musimy podzielić je na trzy nowe trójkąty.
Prawda jest taka: nie potrzebujesz precyzji, którą da ci dwudziestościan. Ponieważ oba kryją znacznie trudniejszy problem: teksturowanie płaszczyzny 2D na kuli 3D. Oto jak wygląda góra:
W lewym górnym rogu widać używaną teksturę. Przypadkowo jest również generowany proceduralnie. (Hej, to był kurs generowania procedur, prawda?)
Wygląda okropnie, prawda? Cóż, to jest tak dobre, jak się da. Mam najlepsze oceny za mapowanie tekstur, ponieważ większość ludzi nawet tego nie rozumie.
Rozważ więc użycie cosinusa i sinusa do wygenerowania kuli. Generuje o wiele mniej twarzy dla tej samej ilości szczegółów.
źródło
N
części da ciN*N
nowe trójkąty, które są kwadratowe, dokładnie tak, jak robisz z kulą UV.Poniższy skrypt utworzy Dwudziestościan z n Wielokątami ... podstawa 12. Podzielą również wieloboki na osobne siatki i obliczą całkowitą liczbę duplikatów i wielokątów.
Nie mogłem znaleźć niczego podobnego, więc to stworzyłem. Wystarczy dołączyć skrypt do GameObject i ustawić podziały w Edytorze. Następne prace nad modyfikacją hałasu.
źródło