Warsztat.GDCompo!ProjektyMediaArtykułyQ&AForumOferty pracyPobieranie

Opisz napotkaną sytuację, a redakcja niezwłocznie znajdzie rozwiązanie!

wyślij anuluj

Tworzenie tuneli w przestrzeni

Tekst został importowany z Warsztatowych artykułów. Jego oryginalnym autorem jest Gynvael. Jeżeli został importowany poprawnie, usuń ten szablon!

Artykuł ten traktuje o wykorzytaniu wzorów na obrót (zob. "Wzory - obroty" Grzegorza Tańczyka oraz "Wzory - obroty - uzupełnienie" Stanisława Kulczyckiego) do stworzenia w przestrzestrzeni tunelu (i to nie tylko okrągłego). Całość opiera się o VC++ oraz OpenGL, lecz równie dobrze można by to w podobny sposób zrobić w DX3D.

Część I

Rozdział 1

Tworzenie jakiegokolwiek tunelu najlepiej jest zacząć od wpisania procedur pomocniczych. Będą one (po podaniu im kąta, promienia oraz środka okręgu) podawały nam X oraz Y punktu na tym okręgu który wyznacza podany kąt. W tym celu wykorzystamy wyżej wspomniane wzory na obrót:

x=xo+r*sin(alfa) y=yo+r*cos(alfa)

Procedury które będą nam zwracań X i Y wyglądają tak:

#define PI 3.141592 ... float tObliczX(float kat, float r, float x0) { return float(x0+r*sin(kat*PI/180)); } float tObliczY(float kat, float r, float y0) { return float(y0+r*cos(kat*PI/180)); }

Dzięki tym dwóm procedurką aby obliczyć na przykład punkt wyznaczający kąt 35 stopni w okręgu o promieniu 10 i początku w punkcie (5,3) wystarczy napisać:

X=tObliczX(35, 10, 5); Y=tObliczY(35,10,3);

Jak widać w tym przykładzie kąty można (a nawet trzeba) podawać w stopniach.

Teraz musimy napisać procedure która by owy tunel rysowała. Co ona ma dokładnie robić? Co trzeba jej podać? A więc ma ona rysować tunel (o podanej długości i promieniu) z określonej liczby cylindrów (do ich stworzenia wykorzystamy serie quadów) o określonej liczbie quadów każdy. A procedura o której mówie wygląda tak:

void tRysujTunel(float tDlugosc, float tPromien, int tFaceWCylindrze, int tIloscCylindrow) { float tKat=360/float(tFaceWCylindrze); float tSkok=tDlugosc/float(tIloscCylindrow); for (int tB=1; tB<=tIloscCylindrow; tB++) { glBegin(GL_QUAD_STRIP); for (int tA=1; tA<=tFaceWCylindrze+1; tA++) { glVertex3f(tObliczX(float(tA*tKat), tPromien, 0), tObliczY(float(tA*tKat), tPromien, 0), (tB-1)*tSkok); glVertex3f(tObliczX(float(tA*tKat), tPromien, 0), tObliczY(float(tA*tKat), tPromien, 0), tB*tSkok); } glEnd(); } }

£adnie się to prezentuje, lecz z czym to sie je? No więc przeanalizujmy po kolei każdą linijkę kodu.

void tRysujTunel(float tDlugosc, float tPromien, int tFaceWCylindrze, int tIloscCylindrow) {

W tym miejscu rozpoczyna sie procedura tRysujTunel (jak sie można domyślić rysuje ona tunel :) ). Aby ją wykorzystać należy dać jej czytery parametry, a dokładniej:
float tDlugosc - długość tunelu podana w floacie
float tPromien - promień tunelu podany również w floacie
int tFaceWCylindrze - ilość faców (w zasadzie to quadów a nie faców) z których jest złożony jeden cylinder; czym więcej faców tym cylinder jest bardziej okrągły, lecz pociąga to za sobą również i większe obciążenie akceleratora
int tIloscCylindrow - ilość cylindrów z których jest złożony nasz tunel; narazie wystarczył by w zasadzie jeden cylinder dla całego tunelu, jednak za chwile zajmiemy się wykręcaniem tunelu, a tam jeden cylinder niestety nie wystarczy; podobnie jak w przypadku faców, czym więcej cylindrów tym większe obciążenie akceleratora
Całkowita liczba faców w tunelu jest równa oczywiście iloczynowi liczby cylindrów i liczby faców w cylindrze. Jedźmy dalej.

float tKat=360/float(tFaceWCylindrze);

tKat jest to odległość jednego vertexa od sąsiadującego na okręgu, podawana w kątach. Jak nietrudno zauważyć liczy się ją poprzez podzielenie pełnego kąta (360 stopni) przez liczbe faców w cylindrze.

float tSkok=tDlugosc/float(tIloscCylindrow);

Podobnie jak tKat, tSkok jest to również odległość, ale pomiędzy vertexami sąsiadujących ze sobą cylindrów. Jest to iloraz całkowitej długości tunelu i ilości cylindrów podany we floacie.

for (int tB=1; tB<=tIloscCylindrow; tB++) {

W tym miejscu rozpoczyna się pierwsza pętla. Rysuje ona pokolei wszystkie cylindry z których składa się tunel.

glBegin(GL_QUAD_STRIP);

Rozpoczęcie rysowania serii quadów (GL_QUAD_STRIP). Polega to na podawaniu dolych vertexów quadów, natomiast jako górne vertexy quadu są używane dolne vertexy poprzedniego quadu.

for (int tA=1; tA<=tFaceWCylindrze+1; tA++) {

Początek drugiej pętli, odpowiedzialnej za narysowanie (dokładnie za podanie wszystkich vertexów) jednego cylindra. Rysuje ona pokolei każdy quad cylindra. Pare osób pytało się mnie dlaczego w tej lini jest tA<=tFaceWCylindrze+1, a nie samo tA<=tFaceWCylindrze. Wynika to z tego, że pierwszy vertex cylindru musi być podany dwa razy. Raz jako górna część pierwszego quada, a drugi raz jako dolna część ostatniego quada.

glVertex3f( tObliczX(float(tA*tKat), tPromien, 0), tObliczY(float(tA*tKat), tPromien, 0), (tB-1)*tSkok); glVertex3f( tObliczX(float(tA*tKat), tPromien, 0), tObliczY(float(tA*tKat), tPromien, 0), tB*tSkok);

W tym miejscu podajemy prawy dolny oraz lewy donly vertex kolejnego quada. X oraz Y jego są liczone wg. wzorów na obrót, natomiast Z jest to pozycja obecnego cylindra ((tB-1)*tSkok), oraz następnego cylindra (tB*tSkok).

} glEnd(); } }

Reszta procedury to są zakończenia pętli tA, rysowania, pętli tB oraz samej procedury.

Teraz możemy wrzucić wywołanie procedury w odpowiednie miejsc i cieszyć się efektem... Zaraz zaraz... Czy tego samego nie można zrobić poleceniem gluCylinder??? Oczywiście że można, jednak tego co zaraz będziemy robić gluCylinder już nie potrafi :).

Rozdział 2

Na początek drugiej częsci tego swoistego tutoriala proponuje zrobić kopie procedury tRysujTunel i zmienić jej nazwę (tej kopii) na tRysujTunelSkrecony. Teraz trzeba dopisać jeden parametr do nowopowstałej procedury tRysujTunelSkrecony, mianowicie float tKatSkrecenia. Proponuje dopisać go między tPromien a tFaceWCylindrze.

void tRysujTunelSkrecony(float tDlugosc, float tPromien, float tKatSkrecenia, int tFaceWCylindrze, int tIloscCylindrow)

Teraz musimy odnaleźć pętle w której są rysowane quady i tak ją przekształcić, aby w każdym kolejnym cylindrze quad zaczynał sie o tKatSkrecenia dalej od tego samego w poprzednim cylindrze. W tym celu zmieniamy dwie linijki:

glVertex3f( tObliczX(float(tA*tKat), tPromien, 0), tObliczY(float(tA*tKat), tPromien, 0), (tB-1)*tSkok); glVertex3f( tObliczX(float(tA*tKat), tPromien, 0), tObliczY(float(tA*tKat), tPromien, 0), tB*tSkok);

Na:

glVertex3f( tObliczX(float(tA*tKat+tKatSkrecenia*(tB-1)), tPromien, 0), tObliczY(float(tA*tKat+tKatSkrecenia*(tB-1)), tPromien, 0), (tB-1)*tSkok ); glVertex3f( tObliczX(float(tA*tKat+tKatSkrecenia*tB), tPromien, 0), tObliczY(float(tA*tKat+tKatSkrecenia*tB), tPromien, 0), tB*tSkok );

Teraz wystarczy wywołać tą procedurę i podziwiać coś czego gluCylinder nie umiał by zrobić, a czego my dokonaliśmy :).

Rozdział 3

Trzecia część tutoriala jest o tworzeniu tunelu o przekroju elipsy. Całość jest bardzo prosta do zrobienia. Jako procedurą bazową ponownie posłużymy się tRysujTunel, jak i poprzednio najlepiej jest zrobić jej kopie i zmienić nazwę, na przykład na tRysujTunelElip. Teraz należy zmienić nazwę float tPromien na float tPromien1, oraz zaraz za nim wstawic nowy parametr float tPromien2. Po tej zmianie początek procedury powienien wyglądać tak:

void tRysujTunelElip(float tDlugosc, float tPromien1, float tPromien2, int tFaceWCylindrze, int tIloscCylindrow)

Teraz, podobnie jak w części drugiej tutoriala, należy odnaleźć pętle podającą vertexy i zmienić je odrobinkę. Trzeba doprowadzić do tego aby promieniem wykorzystywanym przy liczeniu X-a vertexa był tPromien1, a przy liczeniu Y-ka tPromien2.

glVertex3f(tObliczX(float(tA*tKat), tPromien1, 0), tObliczY(float(tA*tKat), tPromien2, 0), (tB-1)*tSkok); glVertex3f(tObliczX(float(tA*tKat), tPromien1, 0), tObliczY(float(tA*tKat), tPromien2, 0), tB*tSkok);

A nie mówiłem że proste?

W ramach ćwiczeń proponuje połączyć procedury tRysujTunelSkrecony i tRysujTunelElip w jedną. Życze powodzenia :))

Rozdział 4

Najpierw troche wyjaśnień co chemy teraz zrobić oraz jak to chemy zrobić. A więc :). Chemy zmusić nasz tunel (nieźle już wygimnastykowany zresztą) aby udawał spiralę. Jak? W tym celu trzeba zmieniać płynnie jego X0 oraz Y0 czyli środek każdego cylindra, najlepiej żeby środek "poruszał się" po jeszcze jednym okręgu (tak jak to jest przedstawione na rysunku obok). TAK! Zgadliście, jeszcze raz bedzie trzeba użyć wzorów na obroty, tym razem do wyliczenia X0 oraz Y0. Ale zacznijmy od początku, a dokładniej zacznijmy od zrobienia kolejnej kopii tRysujTunel, oraz zmienienia jej nazwy na tRysujTunelSpiralny. Trzeba też (jak zwykle) dodać parę nowych parametrów. W tym wypadku są to float tPromienDuzy oraz float tKatObrotu.

void tRysujTunelSpiralny(float tDlugosc, float tPromien, float tPromienDuzy, float tKatObrotu, int tFaceWCylindrze, int tIloscCylindrow)

tPromienDuzy jest to promień okręgu po którym się X0 i Y0 "porusza" (rd na rysunku), a tKatObrotu jest to całkowity kąt o jaki ma być obrócony pierwszy cylinder w stosunku do ostatniego. Następną rzeczą wpisujemy po obliczeniach związanych z tKat i tSkok.

float tObrot=tKatObrotu/float(tIloscCylindrow);

W tej linijce obliczane jest tObrot, jest to kąt o jaki są oddalone od siebie środki sąsiadujących cylindrów.
Następnie musimy zdefiniować dwie zmienne (w zasadzie dwie tablice) które będą odpowiedzialne za przechowywanie i obliczanie X0 oraz Y0.

float x0[2], y0[2];

Teraz musimy w pętli tB dopisać:

x0[0]=tObliczX(float(tObrot*(tB-1)), tPromienDuzy, 0); y0[0]=tObliczY(float(tObrot*(tB-1)), tPromienDuzy, 0); x0[1]=tObliczX(float(tObrot*tB), tPromienDuzy, 0); y0[1]=tObliczY(float(tObrot*tB), tPromienDuzy, 0);

Te cztery linijki obliczają X0 i Y0 obecnego oraz następnego cylindra. Teraz trzeba je (te X0 i Y0) podstawić w odpowiednie miejsce, tzn. trzeba lekko przekształcić glVertex3f w pętli tA:

glVertex3f(tObliczX(float(tA*tKat), tPromien, x0[0]), tObliczY(float(tA*tKat), tPromien, y0[0]),(tB-1)*tSkok); glVertex3f(tObliczX(float(tA*tKat), tPromien, x0[1]), tObliczY(float(tA*tKat), tPromien, y0[1]), tB*tSkok);

To w zasadzie na tyle. Teraz wystarczy wrzucić wywołanie tej procedury w odpowiednie miejsce i podziwiać efekt swojej pracy :).

Podsumowanie

Część II

As the tunel saga continues...
Takim radosnym (?) mottem (?) witam w drugiej części tutoriala dotyczącego tuneli w przestrzeni. Czemu musi być druga część? Ponieważ właściwie w pierwszej części nie doszło do zrobienia prawdziwego tunelu. "Więc o czym była pierwsza część? Nie o tunelach?" Spiesze z wyjaśnieniem. Pierwsz część była jakby wstępem do robienia tuneli, wyjaśniłem tam wzory, oraz wytłumaczyłem jak stworzyć procedury rysujące taki tunel. Zacznijmy więc...

Rozdział 1

Rozpocznijmy od małych rozrób w plikach. Aby nie było bałaganu, proponuje przerzucić polecenia z pierwszej części tutoriala (te rysujące tunel: tRysujTunel i co.) do oddzielnego pliku, tzn. zróbmy sobie biblioteke rysującą tunele - nazwijmy ją "tunel". W tym celu tworzymy dwa pliki - header file (tunel.h) oraz source file (tunel.cpp). Plik nagłówkowy będzie wyglądał tak:

#ifndef TUNEL3D_H #define TUNEL3D_H float tObliczX(float kat, float r, float x0); float tObliczY(float kat, float r, float y0); void tRysujTunelSpiralny(float tDlugosc, float tPromien, float tPromienDuzy, float tKatObrotu, int tFaceWCylindrze, int tIloscCylindrow); void tRysujTunelElip(float tDlugosc, float tPromien1, float tPromien2, int tFaceWCylindrze, int tIloscCylindrow); void tRysujTunel(float tDlugosc, float tPromien, int tFaceWCylindrze, int tIloscCylindrow); void tRysujTunelSkrecony(float tDlugosc, float tPromien, float tKatSkrecenia, int tFaceWCylindrze, int tIloscCylindrow); #endif

Jeżeli nic nie pokręciłem to plik źródłowy wygląda tak:

#include <windows.h> #include <gl\gl.h> #include <gl\glu.h> #include <gl\glaux.h> #include <math.h> #include "tunel.h" #define PI 3.141592 // ustalenie wartosci PI // Funkcje liczace X i Y float tObliczX(float kat, float r, float x0) { ... } float tObliczY(float kat, float r, float y0) { ... } // Procedura rysująca tunel powyginany void tRysujTunelSpiralny(float tDlugosc, float tPromien, float tPromienDuzy, float tKatObrotu, int tFaceWCylindrze, int tIloscCylindrow) { ... } // Procedura rysujaca tunel eliptyczny void tRysujTunelElip(float tDlugosc, float tPromien1, float tPromien2, int tFaceWCylindrze, int tIloscCylindrow) { ... } // Procedura rysujaca tunel zwykły void tRysujTunel(float tDlugosc, float tPromien, int tFaceWCylindrze, int tIloscCylindrow) { ... } // Procedura rysujaca tunel skrecony void tRysujTunelSkrecony(float tDlugosc, float tPromien, float tKatSkrecenia, int tFaceWCylindrze, int tIloscCylindrow) { ... }

Oczywiście w miejscach kropek jest kod procedur (powinniście go mieć z popszedniej części tutoriala). Jeszcze wystarczy teraz dodac #include "tunel.h" do pliku głównego i wszystko powinno chodzić dobrze jak dawniej, tyle że nie mieszają się nam już procedurki.

Rozdział 2

Do stworzenia ładnego tunelu potrzebujemy jeszcze jednej procedurki. Będzie ona jakby połączeniem wszystkich procedur które dotychczas napisaliśmy (tzn. procedur z rodziny tRysujTunel...) z małymi dodatkami pozwalającymi tworzy bardziej skomplikowane wzory. Nazwijmy ją na przyklad tRysujTunelPower ("Power" ponieważ będzie ona miała większe możliwości od procedur bez Power w nazwie :) ). Jakie ona ma mieć dokładnie możliwości? Ma rysować tunele elipsowate, spiralne oraz normalne (wszystkie te efekty zawarte w jednym tunelu), oraz ma mieć możliwość płynej zmiany długości promieni (oby dwóch w przypadku elipsy), oraz do płynnej zmiany promienia okręgu po którym "porusza się" środek okręgu (w przypadku zastosowania efektu spiralności). A procedura ta wygląda tak:

void tRysujTunelPower( float tDlugosc, // Długość tunelu float tPromien11, // Promień X pierwszego cylindra float tPromien12, // Promień Y pierwszego cylindra float tPromien21, // Promień X ostatniego cylindra float tPromien22, // Promień Y ostatniego cylindra float tPromienDuzy1, // Promień okręgu wyznaczającego środek pierwszego cylindra float tPromienDuzy2, // Promień okręgu wyznaczającego środek ostatniego cylindra float tKatObrotu, // Całkowity kąt o jaki ma być obrócony pierwszy cylinder w stosunku do ostatniego int tFaceWCylindrze, // Ilość faców w jednym cylindrze int tIloscCylindrow) // Całkowita liczba cylindrów {

Początek procedury. Jak widać parametrów jest w tym wypadku dużo więcej niż w poprzednich procedurach. Parametry tPromien11, 12, 21 i 22 sa odpowiedzialne za elipsowaty (lub tesz okrągły) wygląd tunely, a tPromienDuzy1 i 2 oraz tKatObrotu za jej spiralny (lub nie) wygląd. Reszta parametrów jest chyba zrozumiała.

float tProm1=(tPromien21-tPromien11)/tIloscCylindrow; float tProm2=(tPromien22-tPromien12)/tIloscCylindrow; float tPromDuzy=(tPromienDuzy2-tPromienDuzy1)/tIloscCylindrow; float tObrot=tKatObrotu/float(tIloscCylindrow); float tKat=360/float(tFaceWCylindrze); float tSkok=tDlugosc/float(tIloscCylindrow); float x0[2], y0[2];

Jeżeli chodzi o opis wyliczenia zmiennych tObrot, tKat i tSkok, oraz opis zmiennych x0 i y0, to znajduje się on w części pierwszej tutoriala. Nowe jest natomiast wyliczenie zmiennych tProm1 i tProm2 odpowiedzialnych za różnice promieni X i Y pomiędzy sąsiadującymi cylindrami (iloraz delty promienia i całkowitej ilości cylindrów). Podobnie jest z tPromDuzy, lecz w tym przypadku jest to różnica pomiędzy promieniami okręgu który wyznacza środek cylindra (efekt spirali).

for (int tB=1; tB<=tIloscCylindrow; tB++) {

W tym miejscu zaczyna sie pętla odpowiedzialna za rysowanie całych cylindrów.

x0[0]=tObliczX(float(tObrot*(tB-1)), tPromienDuzy1+tPromDuzy*(tB-1), 0); y0[0]=tObliczY(float(tObrot*(tB-1)), tPromienDuzy1+tPromDuzy*(tB-1), 0); x0[1]=tObliczX(float(tObrot*tB), tPromienDuzy1+tPromDuzy*tB, 0); y0[1]=tObliczY(float(tObrot*tB), tPromienDuzy1+tPromDuzy*tB, 0);

Jak widać wzory obliczeń x0 i y0 troche się zmieniły. Mianowicie promień okręgu wyznacząjącego środek cylindra dzięki tej operacji może się zmieniać (zwiększać, zmniejszać). Jest to uzyskiwane z dodania do pierwszego promienia iloczynu współczynnika zmiany promienia między cylindrami i obecnego cylindra.

glBegin(GL_QUAD_STRIP); for (int tA=1; tA<=tFaceWCylindrze+1; tA++) {

Rozpoczęcie rysowania serii quadów i pętli odpowiedzialnej za podanie wszystkich vertexów danego cylindra.

glVertex3f( tObliczX(float(tA*tKat), tPromien11+(tB-1)*tProm1, x0[0]), tObliczY(float(tA*tKat), tPromien12+(tB-1)*tProm2, y0[0]), (tB-1)*tSkok); glVertex3f( tObliczX(float(tA*tKat), tPromien11+tB*tProm1, x0[1]), tObliczY(float(tA*tKat), tPromien12+tB*tProm2, y0[1]), tB*tSkok);

Jedyne co się zmienia to we wzorach tObliczX i Y to promień. Zwiększa się on (lub zmiejsza) zgodnie z postępem cylindrów.

} glEnd(); } }

Zakończenia wszelkich rozpoczętych rzeczy.
Tak przygotowana procedura jest już gotowa do użycia :), proponuje sobie ją przetestować by wiedzieć jak działa... Co? Czyżbym słyszał pytanie "to po co nam tamte procedury jak mamy jedną taką???" Ponieważ jeżeli nie kożystamy z połączonych efektów modyfikacji tunelu, to nie warto używać procedury w której wykonywane są obliczenia dla wszystkich (nawet tych nie używanych) efektów. Tzn. jeżeli chcemy zrobić tunel spiralny (tylko spiralny, bez żadnych zmian promieni, elips. itd.) to nie warto liczyć co klatke (bo obliczenia te są wykonywane za każdym razem gdy tunel jest rysowany) jeszcze współczynników zmiany promienia (który przecież się nie zmienia), lepiej jest użyć procedury która nie wykonuje tych obliczeń. Logiczne? :)

Rozdział 3

Mamy już wszystkie potrzebne procedury gotowe, więc możemy stworzyć sobie ładny tunelik. W tym celu proponuje zrobić jakąś procedure (w głównym pliku, nie w bibliotece), w której umieścimy wszystkie polecenia odpowiedzialne za rysowanie tunelu. Nazwijmy ją jakoś orginalnie, np. RysowanieTunelu :).

void RysowanieTunelu() {

Teraz rysujemy pokolei wszystkie częsci tunelu, oraz translacje matrycy (glTranslatef). Zróbmy sobie narazie jakiś prosty tunelik:

tRysujTunelPower(20,2,2,3,3,0,0,0,20,10); glTranslatef(0,0,20); tRysujTunelPower(10,3,3,6,6,0,0,0,20,10); glTranslatef(0,0,10); tRysujTunel(10,6,20,10); glTranslatef(0,0,10); tRysujTunelPower(10,6,6,6,3,0,0,0,20,10); glTranslatef(0,0,10); tRysujTunelPower(50,6,3,3,6,0,0,0,20,10); glTranslatef(0,0,50); tRysujTunelPower(60,3,6,3,3,0,2,720,20,10); glTranslatef(0,0,60); tRysujTunelPower(60,3,3,6,3,2,0,720,20,10);

No i oczywiście trzeba zakończyć procedure:

}

Teraz musimy odpowiednio ustawić kamere (narazie niewymyślnie) i sprawić żeby się przesuwała. W tym celu na początku (tzn. po includach) głównego pliku proponuje zdefiniować jakąc zmienną typu float. W moim przypadku będzie to Idz.

float Idz=0;

Następnie w głównej pętli odpowiedzialnej za rysowanie (zazwyczaj DrawGLScene, lub DrawMyGLScene) musimy dodać pare linijek odpowiedzialnych za posuwanie kamery do przodu oraz obracanie tunelu (to ostatnie to tylko po to żeby ładnie wyglądało :) ).

glTranslatef(0,0,-5+Idz); glRotatef(Idz,0,0,1); glRotatef(180,0,1,0); RysowanieTunelu(); Idz+=0.1f

Powoduje to ustawienie kamery na początku tunelu i stopniowe przesuwanie jej w jego głąb, oraz obracanie w okół własnej osi.
Tunelik mamy narysowany, źle on nie wygląda, ale można by go odrobine upiększyć. Jak? Poprzez dodanie na przykład mgły (glFog) oraz podwójne narysowanie tunelu (tzn. raz GL_FILL oraz drugi raz odrobinke mniejszy GL_LINE). Mgłe dodajemy np. poprzez zdefiniowanie zmiennej z kolorem mgły, oraz ustawienie początka, końca oraz typu mgły. Najlepiej umieścić to w procedurze z inicjacją OpenGL-a (zazwyczaj InitGL).

float KolorMgly[4]={0.0f, 0.0f, 0.0f, 1.0f}; glFogfv(GL_FOG_COLOR, KolorMgly); glFogf(GL_FOG_START, 2.00f); glFogf(GL_FOG_END, 20.00f); glFogf(GL_FOG_MODE, GL_LINEAR); glEnable(GL_FOG);

Teraz zrobimy małe zamieszanie w wywołaniu procedury rysującej tunel. Zmieńmy:

glTranslatef(0,0,-5+Idz); glRotatef(Idz,0,0,1); glRotatef(180,0,1,0); RysowanieTunelu(); Idz+=0.1f;

Na:

glScalef(1,1,1); glColor3f(0.0f, 0.0f, 1.0f); glPolygonMode( GL_BACK, GL_FILL ); glPolygonMode( GL_FRONT, GL_FILL ); glPushMatrix(); RysowanieTunelu(); glPopMatrix(); glColor3f(0.2f, 1.0f, 0.2f); glScalef(0.99f, 0.99f, 1.0f); glPolygonMode( GL_BACK, GL_LINE ); glPolygonMode( GL_FRONT, GL_LINE ); glPushMatrix(); RysowanieTunelu(); glPopMatrix();

Można też ustawić mgłe tylko dla linii lub tylko dla wypełnionego tunelu. Sposobów na upiększenie jest oczywiście baaaaaaardzo wiele :). Dwa najprostsze z nich można podziwiać klikając na miniaturki (niestety fatalna jakość :/ )

Screen shot 1Screen shot 2

Kod źródłowy, który się zachował: Tunnel.zip (5.8 kB)

Autor: Gynvael
Data: 21-22 kwietnia 2001

Tekst dodał:
Adam Sawicki
28.03.2006 17:19

Ostatnia edycja:
Adam Sawicki
28.03.2006 17:19

Kategorie:

Aby edytować tekst, musisz się zalogować.

# Edytuj Porównaj Czas Autor Rozmiar
#1 edytuj 28.03.2006 17:19 Adam Sawicki 25.85 KB
Zwykły
Do sprawdzenia
Do akceptacji
  • Napisz komentarz:
    Aby dodać swój komentarz, musisz się zalogować.
Licencja Creative Commons

Warsztat używa plików cookies. | Copyright © 2006-2017 Warsztat · Kontakt · Regulamin i polityka prywatności
build #ff080b4740 (Tue Mar 25 11:39:28 CET 2014)