Prezentowane materiały są przeznaczone dla uczniów szkół ponadgimnazjalnych. Autor artykułu: mgr Jerzy Wałaszek, wersja1.0 |
©2011 mgr
Jerzy Wałaszek
|
Tablica V będzie wciąż zawierała definicje wierzchołków. Każdy element tej tablicy składa się z 3 współrzędnych w przestrzeni, które określają położenie wierzchołka figury.
Tablica S będzie zawierała kolejne numery wierzchołków, które należą do danej ściany.
Tablica C będzie zawierała kolory wierzchołków lub ścian.
Tablica F będzie definiowała rodzaj ściany (wachlarz lub wstęga), liczbę wierzchołków i początek sekwencji wierzchołków w tablicy.
Załóżmy, że zechcemy stworzyć definicję kostki o boku równym 1. Środek kostki w środku układu współrzędnych.
Współrzędne wierzchołków będą następujące:
v0 = { 0.5f,-0.5f, 0.5f}
v1 = { 0.5f, 0.5f, 0.5f}
v2 = { 0.5f, 0.5f,-0.5f}
v3 = { 0.5f,-0.5f,-0.5f}
v4 = {-0.5f,-0.5f, 0.5f}
v5 = {-0.5f, 0.5f, 0.5f}
v6 = {-0.5f, 0.5f,-0.5f}
v7 = {-0.5f,-0.5f,-0.5f}
Ściany zrealizujemy jako dwa wachlarze trójkątów (jest to jedna z możliwości):
Wachlarz trójkątów zwróconych przodem 1, 2, 3, 0, 4, 5, 6, 2 |
Wachlarz trójkątów zwróconych tyłem 7, 4, 0, 3, 2, 6, 5, 4 |
S0-7 = { 1, 2, 3, 0, 4, 5, 6, 2 }
S8-15 = { 7, 4, 0, 3, 2, 6, 5, 4 }
Teraz możemy zdefiniować tablicę F. Będzie się składała z dwóch elementów, gdyż nasza figura zawiera tylko dwa wachlarze:
F0 = {wachlarz, 8
wierzchołków, od S0}
F1 = {wachlarz, 8 wierzchołków, od S8}
Na początku programu wpisz kod funkcji rysującej figurę:
//--------------------------------------------------------------------------- void Figure3D(int n, bool cmode, GLfloat v[][3], int s[], GLfloat c[][3], int f[][3]) { for(int i = 0; i < n; i++) { if(cmode) glColor3fv(c[i]); // kolor ściany glBegin(f[i][0]); // wachlarz, wstęga, lub coś innego for(int j = 0; j < f[i][1]; j++) { if(!cmode) glColor3fv(c[s[f[i][2]+j]]); // kolor wierzchołka glVertex3fv(v[s[f[i][2]+j]]); } glEnd(); } } //---------------------------------------------------------------------------
Zwróć uwagę, że funkcja rysująca naszą figurę jest bardzo ogólna. Struktura danych określa rodzaj prymitywu, który chcemy użyć. Zatem w figurze możemy dowolnie mieszać wstęgi, wachlarze, wielokąty, itp.
Resztę kodu wprowadź do funkcji Timera:
// Tutaj umieszczamy program dla OpenGL static GLfloat alphax = 0; static GLfloat alphay = 0; static GLfloat alphaz = 0; static GLfloat V[][3] = {{ 0.5f,-0.5f, 0.5f}, // v0 { 0.5f, 0.5f, 0.5f}, // v1 { 0.5f, 0.5f,-0.5f}, // v2 { 0.5f,-0.5f,-0.5f}, // v3 {-0.5f,-0.5f, 0.5f}, // v4 {-0.5f, 0.5f, 0.5f}, // v5 {-0.5f, 0.5f,-0.5f}, // v6 {-0.5f,-0.5f,-0.5f}}; // v7 static int S[] = { 1, 2, 3, 0, 4, 5, 6, 2, // 0..7 wachlarz 1 7, 4, 0, 3, 2, 6, 5, 4}; // 8..15 wachlarz 2 static GLfloat C[][3] = {{1.0f,0.0f,0.0f}, // kolor v0 {0.0f,1.0f,0.0f}, // kolor v1 {0.0f,0.0f,1.0f}, // kolor v2 {1.0f,0.0f,1.0f}, // kolor v3 {0.0f,1.0f,1.0f}, // kolor v4 {1.0f,1.0f,0.0f}, // kolor v5 {1.0f,1.0f,1.0f}, // kolor v6 {0.5f,1.0f,0.0f}}; // kolor v7 static int F[][3] = {{GL_TRIANGLE_FAN,8,0}, // wachlarz 1 {GL_TRIANGLE_FAN,8,8}}; // wachlarz 2 glTranslatef(0.0f,0.0f,-3.0f); glRotatef(alphax,1.0f,0.0f,0.0f); glRotatef(alphay,0.0f,1.0f,0.0f); glRotatef(alphaz,0.0f,0.0f,1.0f); Figure3D(2,false,V,S,C,F); // rysujemy figurę alphax += 0.5; if(alphax >= 360) alphax = 0; alphay += 0.2; if(alphay >= 360) alphay = 0; alphaz += 0.3; if(alphaz >= 360) alphaz = 0; // Koniec kodu dla OpenGL
W ramach ćwiczeń zaprojektuj sześcian, który będzie zbudowany z dwóch wachlarzy oraz jednej wstęgi trójkątów. A może wykorzystasz czworoboki i wstęgę czworoboków. Wykonaj te ćwiczenia, gdyż uczą one tworzenia figur, co się bardzo nam przyda.
Aby otrzymać kolejne punkty na powierzchni kuli, postępujemy następująco:
Pierwszy i ostatni wierzchołek znajduje się na osi OZ. Zakładamy, że r = 1. Współrzędne są następujące:
vp = {0.0f, 0.0f, 1.0f}
vk = {0.0f, 0.0f,-1.0f}
Teraz na osi OZ wyznaczamy kolejne punkty z, które posłużą nam do określenia płaszczyzn tnących naszą kulę. Liczba tych punktów definiuje ilość warstw. Oznaczmy ją przez N.
Naszą kulę przecinamy płaszczyzną równoległą do OXY i przechodzącą przez wyznaczony punkt zi. Przecięcie to wyznacza na powierzchni kuli okrąg o promieniu ri.
Na tym okręgu wyznaczamy M równoodległych od siebie punktów wg wzoru:
Współrzędna zj dla wszystkich punktów wynosi zi. Dla kolejnych warstw zi otrzymamy punkty leżące na kuli. Poniższy program testuje te zasadę.
// Tutaj umieszczamy program dla OpenGL static bool init_data = false; const int N = 20; // liczba warstw w osi OZ const int M = 22; // liczba punktów na okręgach const double PI = 3.14159265358979; static GLfloat V[N * M + 2][3]; if(!init_data) { init_data = true; V[0][0] = V[N*M+1][0] = V[0][1] = V[N*M+1][1] = 0.0f; V[0][2] = 1.0f; V[N*M+1][2] = -1.0f; for(int i = 1; i <= N; i++) { GLfloat z = cos(i * PI / (N + 1)); GLfloat r = sin(i * PI / (N + 1)); for(int j = 0; j < M; j++) { GLfloat x = r * cos(2 * PI * j / M); GLfloat y = r * sin(2 * PI * j / M); int idx = 1 + (i - 1) * M + j; V[idx][0] = x; V[idx][1] = y; V[idx][2] = z; } } } static GLfloat alphax = 0; static GLfloat alphay = 0; static GLfloat alphaz = 0; glTranslatef(0.0f,0.0f,-3.0f); glRotatef(alphax,1.0f,0.0f,0.0f); glRotatef(alphay,0.0f,1.0f,0.0f); glRotatef(alphaz,0.0f,0.0f,1.0f); glBegin(GL_POINTS); for(int i = 0; i < N * M + 2; i++) glVertex3fv(V[i]); glEnd(); alphax += 0.5; if(alphax >= 360) alphax = 0; alphay += 0.2; if(alphay >= 360) alphay = 0; alphaz += 0.3; if(alphaz >= 360) alphaz = 0; // Koniec kodu dla OpenGL
Jeśli masz okulary anaglifowe, to wypróbuj ten program:
// Tutaj umieszczamy program dla OpenGL static bool init_data = false; const int N = 20; // liczba warstw w osi OZ const int M = 22; // liczba punktów na okręgach const double PI = 3.14159265358979; static GLfloat V[N * M + 2][3]; if(!init_data) { init_data = true; V[0][0] = V[N*M+1][0] = V[0][1] = V[N*M+1][1] = 0.0f; V[0][2] = 1.0f; V[N*M+1][2] = -1.0f; for(int i = 1; i <= N; i++) { GLfloat z = cos(i * PI / (N + 1)); GLfloat r = sin(i * PI / (N + 1)); for(int j = 0; j < M; j++) { GLfloat x = r * cos(2 * PI * j / M); GLfloat y = r * sin(2 * PI * j / M); int idx = 1 + (i - 1) * M + j; V[idx][0] = x; V[idx][1] = y; V[idx][2] = z; } } } static GLfloat alphax = 0; static GLfloat alphay = 0; static GLfloat alphaz = 0; glPointSize(4.0f); for(int j = -1; j <= 1; j+=2) { glPushMatrix(); // zachowujemy macierz przekształcenia glTranslatef(-0.1*j,0.0f,-3.0f); glColor3f((j==-1),0.5*(j==1),0.5*(j==1)); glRotatef(alphax,1.0f,0.0f,0.0f); glRotatef(alphay,0.0f,1.0f,0.0f); glRotatef(alphaz,0.0f,0.0f,1.0f); glBegin(GL_POINTS); for(int i = 0; i < N * M + 2; i++) glVertex3fv(V[i]); glEnd(); glPopMatrix(); // odtwarzamy macierz przekształcenia } alphax += 0.5; if(alphax >= 360) alphax = 0; alphay += 0.2; if(alphay >= 360) alphay = 0; alphaz += 0.3; if(alphaz >= 360) alphaz = 0; // Koniec kodu dla OpenGL
Program rysuje punkty kuli dwa razy z przesunięciem. Raz na czerwono, a raz na zielono-niebiesko. W wyniku dostajemy obraz anaglifowy kuli, który po zastosowaniu odpowiednich okularów daje wrażenie trójwymiarowe.
Otrzymane punkty możemy połączyć w ściany na kilka różnych sposobów. Pierwszy polega na wykorzystaniu dwóch wachlarzy trójkątów oraz odpowiedniej liczby wstęg czworokątów. Zasadę tę obrazuje poniższy rysunek:
Punkt początkowy łączymy wachlarzem z punktami, które leżą na pierwszym okręgu warstwy podziałowej. Następnie punkty tego okręgu łączymy z odpowiednimi punktami drugiego okręgu za pomocą wstęgi czworoboków. Operację tę kontynuujemy aż do przedostatniego okręgu. Na koniec zamykamy kulę wachlarzem, który łączy ostatni punkt z punktami na ostatnim okręgu podziałowym.
Załóżmy, że mamy N warstw, a każda wyznacza na kuli okrąg podzielony na M punktów. Obliczmy niezbędne rozmiary poszczególnych tablic.
C → 2 + N x M
Jeśli określamy kolory osobne dla każdego wierzchołka, to tablica
kolorów musi mieć ten sam rozmiar co V.
S → 2 x (M + 2) + (N - 1) x (2M + 2)
Tablica definiująca ściany wg tworzących je wierzchołków będzie
zawierała definicje dwóch wachlarzy trójkątów oraz N-1 wstęg
czworokątów. Wachlarz wymaga jednego wierzchołka startowego oraz M +
1 wierzchołków na okręgu, przy czym pierwszy i ostatni wierzchołek
muszą posiadać ten sam numer, aby wachlarz był zamknięty. Daje nam
to M+2 elementy. Ponieważ kula będzie się składała z 2 wachlarzy,
otrzymujemy 2 x (M + 2).
Dalej uwzględniamy boczne wstęgi czworokątów. Każda wstęga wykorzystuje wszystkie punkty dwóch sąsiednich okręgów. Punkty startowy i końcowy muszą być takie same, aby wstęga się zamknęła na kuli. Dlatego Potrzebujemy 2M + 2 elementy. Wstęg jest N - 1, zatem potrzeba będzie na nie (N - 1) x (2M + 2) elementy.
F → N + 1
Tablica F zawiera informację o dwóch wachlarzach trójkątów oraz o N
- 1 wstęgach czworokątów. Zatem musi mieć rozmiar N + 1.
Jeśli stosujemy ukrywanie ścian odwróconych tyłem, to musimy pamiętać o odpowiedniej kolejności wierzchołków dla każdej ściany. Po tych wstępnych rozważaniach możemy już napisać program, który będzie tworzył kulę o promieniu 1 i środku w punkcie (0,0,0).
// Tutaj umieszczamy program dla OpenGL static bool init_data = false; const int N = 10; // liczba warstw w osi OZ const int M = 20; // liczba punktów na okręgach const double PI = 3.14159265358979; static GLfloat V[N * M + 2][3]; // wierzchołki static GLfloat C[N * M + 2][3]; // kolory wierzchołków static int S[2*(M+2) + (N-1)*(2*M+2)]; // ściany static int F[N+1][3]; // ściany if(!init_data) { init_data = true; int idx, i, j, k; // Tworzymy wierzchołki na powierzchni kuli w V V[0][0] = V[N*M+1][0] = V[0][1] = V[N*M+1][1] = 0.0f; V[0][2] = 1.0f; V[N*M+1][2] = -1.0f; C[N*M+1][0] = C[0][0] = C[N*M+1][1] = C[0][1] = C[N*M+1][2] = C[0][2] = 1.0f; for(i = 1; i <= N; i++) { GLfloat z = cos(i * PI / (N + 1)); GLfloat r = sin(i * PI / (N + 1)); for(j = 0; j < M; j++) { GLfloat x = r * cos(2 * PI * j / M); GLfloat y = r * sin(2 * PI * j / M); idx = 1 + (i - 1) * M + j; V[idx][0] = x; V[idx][1] = y; V[idx][2] = z; C[idx][0] = fabs(x); C[idx][1] = fabs(1-y); C[idx][2] = fabs(1-z); } } // Tworzymy definicje ścian w S i F // Przedni wachlarz idx = 0; F[0][2] = 0; // Pozycja w S S[idx++] = 0; for(i = M; i >= 0; i--) S[idx++] = 1 + (i % M); F[0][0] = GL_TRIANGLE_FAN; // Typ ściany F[0][1] = M + 2; // Liczba wierzchołków // boczne wstęgi czworoboków for(i = 0; i < N-1; i++) { F[i+1][2] = idx; // Pozycja w S for(j = 0; j <= M; j++) { S[idx++] = 1 + (i+1) * M + (j % M); S[idx++] = 1 + i * M + (j % M); } F[i+1][0] = GL_QUAD_STRIP; // Typ ściany F[i+1][1] = 2*M+2; // Liczba wierzchołków } // Tylni wachlarz F[N][2] = idx; // Pozycja w S S[idx++] = N * M+1; for(i = 0; i <= M; i++) S[idx++] = 1 + (N - 1) * M + (i % M); F[N][0] = GL_TRIANGLE_FAN; // Typ ściany F[N][1] = M + 2; // Liczba wierzchołków } static GLfloat alphax = 0; static GLfloat alphay =1; static GLfloat alphaz = 0; glTranslatef(0.0f,0.0f,-3.0f); glRotatef(alphax,1.0f,0.0f,0.0f); glRotatef(alphay,0.0f,1.0f,0.0f); glRotatef(alphaz,0.0f,0.0f,1.0f); // glPolygonMode(GL_FRONT,GL_LINE); Figure3D(N+1,false,V,S,C,F); // Rysujemy figurę alphax += 0.5; if(alphax >= 360) alphax = 0; alphay += 0.2; if(alphay >= 360) alphay = 0; alphaz += 0.3; if(alphaz >= 360) alphaz = 0; // Koniec kodu dla OpenGL
Zmieniając w powyższym kodzie N i M możemy otrzymywać ciekawe figury geometryczne:
N = 1, M = 20 |
N = 2, M = 20 |
N = 20, M = 3 |
Wypróbuj też inne wartości i wyciągnij odpowiednie wnioski. A jak uzyskać taki efekt?
Drugi sposób tworzenia kuli będzie polegał na stworzeniu ciągu wstęg trójkątów, które będą łączyły kolejne wierzchołki od punktu startowego kuli do punktu końcowego.
Rozważmy potrzebne rozmiary tablic.
C → 2 + N x M
Jeśli określamy kolory osobne dla każdego wierzchołka, to tablica
kolorów musi mieć ten sam rozmiar co V.
S → M * (2 * N + 2)
W S będzie zdefiniowane M wstęg trójkątów. W każdej wstędze mamy
punkt startowy i końcowy oraz po dwa punkty z każdej warstwy.
F → M
Tablica F zawiera informację o M wstęgach..
Wprowadź kod do funkcji Timera:
// Tutaj umieszczamy program dla OpenGL static bool init_data = false; const int N = 10; // liczba warstw w osi OZ const int M = 20; // liczba punktów na okręgach const double PI = 3.14159265358979; static GLfloat V[N * M + 2][3]; // wierzchołki static GLfloat C[N * M + 2][3]; // kolory wierzchołków static int S[M * (2 * N + 2)]; // ściany static int F[M][3]; // ściany if(!init_data) { init_data = true; int idx, i, j, k; V[0][0] = V[N*M+1][0] = V[0][1] = V[N*M+1][1] = 0.0f; V[0][2] = 1.0f; V[N*M+1][2] = -1.0f; C[N*M+1][0] = C[0][0] = C[N*M+1][1] = C[0][1] = C[N*M+1][2] = C[0][2] = 1.0f; for(i = 1; i <= N; i++) { GLfloat z = cos(i * PI / (N + 1)); GLfloat r = sin(i * PI / (N + 1)); for(j = 0; j < M; j++) { GLfloat x = r * cos(2 * PI * j / M); GLfloat y = r * sin(2 * PI * j / M); idx = 1 + (i - 1) * M + j; V[idx][0] = x; V[idx][1] = y; V[idx][2] = z; C[idx][0] = fabs(x); C[idx][1] = fabs(1-y); C[idx][2] = fabs(1-z); } } // Definiujemy ściany S i F idx = 0; for(i = 0; i < M; i++) { F[i][2] = idx; // Pozycja w S S[idx++] = 0; // Wierzchołek startowy for(j = 0; j < N; j++) { S[idx++] = 1 + j * M + (i + 1) % M; S[idx++] = 1 + j * M + i; } S[idx++] = N*M+1; // Wierzchołek końcowy F[i][0] = GL_TRIANGLE_STRIP; F[i][1] = 2*N+2; } } static GLfloat alphax = 0; static GLfloat alphay =1; static GLfloat alphaz = 0; glTranslatef(0.0f,0.0f,-3.0f); glRotatef(alphax,1.0f,0.0f,0.0f); glRotatef(alphay,0.0f,1.0f,0.0f); glRotatef(alphaz,0.0f,0.0f,1.0f); // glPolygonMode(GL_FRONT,GL_LINE); Figure3D(M,false,V,S,C,F); alphax += 0.5; if(alphax >= 360) alphax = 0; alphay += 0.2; if(alphay >= 360) alphay = 0; alphaz += 0.3; if(alphaz >= 360) alphaz = 0; // Koniec kodu dla OpenGL
Zastanów się, jak uzyskać poniższe efekty:
Kolejny program prezentujemy jako swego rodzaju ciekawostkę. Tworzy on animację przekształcenia sześcianu w kulę. Wykorzystuje proste zależności wektorowe oraz symetrie kuli.
// Tutaj umieszczamy program dla OpenGL const int N = 32; // rozmiar tablicy - 1 dla pierwszej ściany const int L = (N+1)*(N+1); // długość tablicy static GLfloat P[N+1][N+1][3]; // wierzchołki pierwszej ściany static GLfloat V[6*L][3]; // wierzchołki static GLfloat C[6*L][3]; // kolory static int S[6*N*(N+N+2)]; // ściany static int F[6*N][3]; // ściany static int count = 0; // licznik klatek static int n = 0; // liczba podziałów ściany static int dn = 1; // przyrost dla n if(!count) { count = 25; // szybkośc morfingu, mniej = szybciej int test = n + dn; if(test > N || test < 1) dn = -dn; n += dn; int l = (n+1) * (n+1); GLfloat p = sqrt(3)/3; // do wyznaczenie początkowych wierzchołków GLfloat z = p; // dla pierwszej ściany z jest stałe for(int i = 0; i <= n; i++) // wyznaczamy punkty na kuli { GLfloat y = p - i*2*p/n; for(int j = 0; j <= n; j++) { GLfloat x = -p + j*2*p/n; double m = sqrt(x*x + y*y + z*z); m = 1 + (1 - m) / m; P[i][j][0] = m * x; P[i][j][1] = m * y; P[i][j][2] = m * z; } } int idx = 0; for(int i = 0; i < 6; i++) // wyznaczone punkty przekształcamy na punkty ścian { for(int j = 0; j <= n; j++) for(int k = 0; k <= n; k++) { switch(i) { case 0: V[idx][0] = P[j][k][0]; // x <- x // ściana przednia, bez zmian V[idx][1] = P[j][k][1]; // y <- y V[idx][2] = P[j][k][2]; // z <- z break; case 1: V[idx][0] = P[j][k][0]; // x <- x // ściana górna V[idx][1] = P[j][k][2]; // y <- z V[idx][2] =-P[j][k][1]; // z <--y break; case 2: V[idx][0] = P[j][k][0]; // x <- x // ściana tylna V[idx][1] =-P[j][k][1]; // y <--y V[idx][2] =-P[j][k][2]; // z <--z break; case 3: V[idx][0] = P[j][k][0]; // x <- x // ściana spodnia V[idx][1] =-P[j][k][2]; // y <--z V[idx][2] = P[j][k][1]; // z <- y break; case 4: V[idx][0] = P[j][k][2]; // x <- z // ściana prawa V[idx][1] = P[j][k][1]; // y <- y V[idx][2] =-P[j][k][0]; // z <--x break; case 5: V[idx][0] =-P[j][k][2]; // x <--z // ściana lewa V[idx][1] = P[j][k][1]; // y <- y V[idx][2] = P[j][k][0]; // z <- x break; } C[idx][0] = (1 + V[idx][0]) / 2; C[idx][1] = (1 + V[idx][1]) / 2; C[idx][2] = (1 + V[idx][2]) / 2; idx++; } } idx = 0; for(int i = 0; i < 6; i++) // punkty łączymy w ściany { for(int j = 0; j < n; j++) { F[i*n+j][0] = GL_QUAD_STRIP; F[i*n+j][2] = idx; for(int k = 0; k <= n; k++) { S[idx++] = i * l + (j + 1) * (n+1) + k; S[idx++] = i * l + j * (n+1) + k; } F[i*n+j][1] = idx - F[i*n+j][2]; } } } count--; static GLfloat alphax = 0; static GLfloat alphay = 0; static GLfloat alphaz = 0; glTranslatef(0.0f,0.0f,-3.0f); glRotatef(alphax,1,0,0); glRotatef(alphay,0,1,0); glRotatef(alphaz,0,0,1); glPolygonMode(GL_FRONT,GL_LINE); Figure3D(6*n,false,V,S,C,F); alphax += 0.5; if(alphax >= 360) alphax = 0; alphay += 0.2; if(alphay >= 360) alphay = 0; alphaz += 0.3; if(alphaz >= 360) alphaz = 0; // Koniec kodu dla OpenGL
Następny program dokonuje animacji przekształcenia sześcianu w kulę. Działa on na podobnej zasadzie jak poprzedni.
// Tutaj umieszczamy program dla OpenGL static bool init_data = false; const int N = 16; // rozmiar tablicy - 1 dla pierwszej ściany const int L = (N+1)*(N+1); // długość tablicy static GLfloat P[N+1][N+1][3]; // wierzchołki pierwszej ściany static GLfloat V[6*L][3]; // wierzchołki static GLfloat C[6*L][3]; // kolory static int S[6*N*(N+N+2)]; // ściany static int F[6*N][3]; // ściany static int count = 50; // licznik klatek animacji static int ncount = 0; // licznik klatek morfingu static double M = 0.01; // współczynnik morfingu if(!init_data) { init_data = true; GLfloat p = sqrt(3)/3; GLfloat z = p; for(int i = 0; i <= N; i++) // tworzymy punkty siatki przedniej ściany { GLfloat y = p - i*2*p/N; for(int j = 0; j <= N; j++) { GLfloat x = -p + j*2*p/N; P[i][j][0] = x; P[i][j][1] = y; P[i][j][2] = z; } } int idx = 0; for(int i = 0; i < 6; i++) // tworzymy punkty siatki pozostałych ścian { for(int j = 0; j <= N; j++) for(int k = 0; k <= N; k++) { switch(i) { case 0: V[idx][0] = P[j][k][0]; // x <- x V[idx][1] = P[j][k][1]; // y <- y V[idx][2] = P[j][k][2]; // z <- z break; case 1: V[idx][0] = P[j][k][0]; // x <- x V[idx][1] = P[j][k][2]; // y <- z V[idx][2] =-P[j][k][1]; // z <--y break; case 2: V[idx][0] = P[j][k][0]; // x <- x V[idx][1] =-P[j][k][1]; // y <--y V[idx][2] =-P[j][k][2]; // z <--z break; case 3: V[idx][0] = P[j][k][0]; // x <- x V[idx][1] =-P[j][k][2]; // y <--z V[idx][2] = P[j][k][1]; // z <- y break; case 4: V[idx][0] = P[j][k][2]; // x <- z V[idx][1] = P[j][k][1]; // y <- y V[idx][2] =-P[j][k][0]; // z <--x break; case 5: V[idx][0] =-P[j][k][2]; // x <--z V[idx][1] = P[j][k][1]; // y <- y V[idx][2] = P[j][k][0]; // z <- x break; } C[idx][0] = 1-j / (double)N; C[idx][1] = i / 5.0; C[idx][2] = k / (double)N; idx++; } } idx = 0; for(int i = 0; i < 6; i++) // tworzymy ściany sześcianu { for(int j = 0; j < N; j++) { F[i*N+j][0] = GL_QUAD_STRIP; F[i*N+j][2] = idx; for(int k = 0; k <= N; k++) { S[idx++] = i * L + (j + 1) * (N+1) + k; S[idx++] = i * L + j * (N+1) + k; } F[i*N+j][1] = idx - F[i*N+j][2]; } } } count--; if(!count) // dokonujemy stopniowego przekształcenia sześcianu w kulę { count = 1; ncount++; if(ncount == 500) { ncount = 0; count = 50; init_data = false; } for(int i = 0; i < 6*L; i++) { double x,y,z,m; x = V[i][0]; // współrzędne wektora y = V[i][1]; z = V[i][2]; m = sqrt(x*x + y*y + z*z); // długość wektora m = 1 + M * (1 - m) / m; // współczynnik mnożenia V[i][0] = m * x; // zmieniamy długość wektora V[i][1] = m * y; V[i][2] = m * z; } } static GLfloat alphax = 0; static GLfloat alphay = 0; static GLfloat alphaz = 0; glTranslatef(0.0f,0.0f,-3.0f); glRotatef(alphax,1,0,0); glRotatef(alphay,0,1,0); glRotatef(alphaz,0,0,1); glPolygonMode(GL_FRONT,GL_LINE); Figure3D(6*N,false,V,S,C,F); alphax += 0.5; if(alphax >= 360) alphax = 0; alphay += 0.2; if(alphay >= 360) alphay = 0; alphaz += 0.3; if(alphaz >= 360) alphaz = 0; // Koniec kodu dla OpenGL
Z przedstawionych powyżej rozwiązań wynika, że obiekty 3D można tworzyć na wiele różnych sposobów. Zawsze wybieramy ten sposób, który w danej sytuacji będzie dla nas najbardziej wygodny.
glPopMatrix() – odtwarza zapamiętaną wcześniej macierz przekształcenia.
I Liceum Ogólnokształcące |
Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl
W artykułach serwisu są używane cookies. Jeśli nie chcesz ich otrzymywać,
zablokuj je w swojej przeglądarce.
Informacje dodatkowe