opengl definiowanie sceny 3d

background image

Janusz Ganczarski

OpenGL

Definiowanie sceny 3D

background image

Spis treści

Spis treści . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1

1. Definiowanie sceny 3D . . . . . . . . . . . . . . . . . . . . . . . . . . .

1

1.1.

Obszar renderingu . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1

1.1.1.

Plik kwadrat2.cpp . . . . . . . . . . . . . . . . . . . . . . . .

2

1.2.

Rzutowanie prostokątne . . . . . . . . . . . . . . . . . . . . . . . . .

4

1.2.1.

Plik szescian1.cpp . . . . . . . . . . . . . . . . . . . . . . . .

7

1.3.

Rzutowanie perspektywiczne . . . . . . . . . . . . . . . . . . . . . .

10

1.3.1.

Plik szescian2.cpp . . . . . . . . . . . . . . . . . . . . . . . .

13

1.3.2.

Plik szescian3.cpp . . . . . . . . . . . . . . . . . . . . . . . .

16

1.4.

Położenie obserwatora . . . . . . . . . . . . . . . . . . . . . . . . . .

19

1.4.1.

Plik szescian4.cpp . . . . . . . . . . . . . . . . . . . . . . . .

21

Literatura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

26

background image

1. Definiowanie sceny 3D

W kolejnych programach korzystających z biblioteki OpenGL zajmie-

my się podstawowymi zagadnieniami, związanymi ze sceną 3D: obszarem
renderingu, rzutowaniem i położeniem obserwatora. Informacje tu zawarte
stanowią podstawę do wszystkich następnych programów.

1.1. Obszar renderingu

W pierwszym programie obszar renderingu, który zajmował początko-

wo całe okno, nie był modyfikowany podczas zmiany rozmiarów tego okna.
W efekcie jedyny element sceny 3D - kwadrat - zawsze znajdował się w tym
samym miejscu względem lewego dolnego narożnika okna.

W aplikacjach pracujących w systemach okienkowych problem zmiany

rozmiaru okna jest jednak tak powszechny, że wymaga specjalnego potrak-
towania. Jednym z możliwych sposobów jego rozwiązania jest dynamiczna
modyfikacja obszaru renderingu. Służy to tego funkcja:

void glViewport (GLint x, GLint y,

GLsizei width, GLsizei height)

której parametry oznaczają:
— x, y - współrzędne lewego dolnego narożnika obszaru renderingu wzglę-

dem lewego dolnego narożnika okna,

— width - szerokość okna renderingu,
— height - wysokość okna renderingu.

Domyślnie obszar renderingu zajmuje całe okno udostępnione dla aplika-

cji OpenGL. W naszym drugim programie w trakcie zmiany rozmiaru okna
(funkcja Reshape) będziemy modyfikować obszar renderingu na dwa spo-
soby. Pierwszy polega na objęciu obszarem renderingu całego dostępnego
okna, drugi na takim wyborze okna renderingu aby okno zachowało pier-
wotny aspekt obrazu, czyli stosunek szerokości do wysokości. Oczywiście
przy zastosowaniu pierwszej metody kwadrat będzie zazwyczaj zdeformo-
wany (patrz rysunki 1 i 2). Zmiany sposobu definiowania okna renderin-
gu można dokonać w dowolnym momencie, poprzez wybranie odpowiedniej
opcji w menu podręcznym.

W funkcji Menu została użyta do tej pory nieopisana funkcja z biblioteki

GLUT:

int glutGet (GLenum type)

O tym jakiego rodzaju informacje zwróci funkcja glutGet decyduje para-

metr type. W przykładowym programie są to szerokość i wysokość okna, co
odpowiada parametrom opisanym stałymi GLUT WINDOW WIDTH i GLUT WIN-
DOW HEIGHT.

background image

1. Definiowanie sceny 3D

2

Warto jeszcze kilka słów poświęcić zagadnieniu aspektu obrazu. Typowe

monitory komputerowe posiadają aspekt 4:3, który jest zgodny z większością
popularnych rozdzielczości roboczych (np. 640 × 480, 800 × 600, 1.024 ×
768, 1.600 × 1.200), ale inna popularna rozdzielczość 1.280 × 1.024 pikseli
odpowiada aspektowi 5:4.

Rysunek 1. Programu Kwadrat 2 - rendering na całym oknie

Rysunek 2. Programu Kwadrat 2 - rendering z zachowaniem aspektu 1:1

1.1.1. Plik kwadrat2.cpp

/

( c )

J a n u s z

G a n c z a r s k i

h t t p : / / www . j a n u s z g . h g . p l

J a n u s z G @ e n t e r . n e t . p l
/

#i n c l u d e <GL/ g l u t . h>
#i n c l u d e < s t d l i b . h>

//

s t a ł e

do

o b s ł u g i

menu

p o d r ę c z n e g o

enum

{

FULL WINDOW,

//

o b s z a r

r e n d e r i n g u c a ł e

o k n o

ASPECT 1 1 ,

//

o b s z a r

r e n d e r i n g u a s p e k t

1 : 1

background image

1. Definiowanie sceny 3D

3

EXIT

//

w y j ś c i e

} ;

//

a s p e k t

o b r a z u

i n t

A s p e c t = FULL WINDOW ;

//

f u n k c j a

g e n e r u j ą c a

s c e n ę

3D

void

D i s p l a y

( )

{

//

k o l o r

t ł a z a w a r t o ś ć

b u f o r a

k o l o r u

g l C l e a r C o l o r

( 1 . 0 , 1 . 0 , 1 . 0 , 1 . 0 ) ;

//

c z y s z c z e n i e

b u f o r a

k o l o r u

g l C l e a r

( GL COLOR BUFFER BIT ) ;

//

k o l o r

k w a d r a t u

g l C o l o r 3 f

( 1 . 0 , 0 . 0 , 0 . 0 ) ;

//

p o c z ą t e k

d e f i n i c j i

w i e l o k ą t a

g l B e g i n

(GL POLYGON ) ;

//

k o l e j n e

w i e r z c h o ł k i

w i e l o k ą t a

g l V e r t e x 3 f

( 0 . 0 ,

0 . 0 ,

0 . 0 ) ;

g l V e r t e x 3 f

( 0 . 0 ,

1 . 0 ,

0 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

1 . 0 ,

0 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

0 . 0 ,

0 . 0 ) ;

//

k o n i e c

d e f i n i c j i

p r y m i t y w u

g l E n d

( ) ;

//

s k i e r o w a n i e

p o l e c e ń

do

w y k o n a n i a

g l F l u s h

( ) ;

//

z a m i a n a

b u f o r ó w

k o l o r u

g l u t S w a p B u f f e r s ( ) ;

}

//

z m i a n a

w i e l k o ś c i

o k n a

void

R esh ape

( i n t

width ,

i n t

h e i g h t )

{

//

o b s z a r

r e n d e r i n g u a s p e k t

1 : 1

i f

( A s p e c t == ASPECT 1 1 )

{

//

s z e r o k o ś ć

o k n a

w i ę k s z a

od

w y s o k o ś c i

o k n a

i f

( w i d t h > h e i g h t )

g l V i e w p o r t

( ( w i d t h − h e i g h t ) / 2 , 0 , h e i g h t , h e i g h t ) ;

e l s e

//

w y s o k o ś ć

o k n a

w i ę k s z a

od

w y s o k o ś c i

o k n a

i f

( w i d t h < h e i g h t )

g l V i e w p o r t

( 0 , ( h e i g h t − w i d t h ) / 2 , width , w i d t h ) ;

}

e l s e

//

o b s z a r

r e n d e r i n g u c a ł e

o k n o

( t a k ż e ,

g d y

a s p e k t

w y n o s i

1 : 1 )

g l V i e w p o r t

( 0 , 0 , width , h e i g h t ) ;

//

g e n e r o w a n i e

s c e n y

3D

D i s p l a y

( ) ;

}

//

o b s ł u g a

menu

p o d r ę c z n e g o

void Menu ( i n t

v a l u e )

{

switch

( v a l u e )

{

//

o b s z a r

r e n d e r i n g u c a ł e

o k n o

c a s e FULL WINDOW :
A s p e c t = FULL WINDOW ;
R esha pe

( g l u t G e t

(GLUT WINDOW WIDTH) , g l u t G e t

(GLUT WINDOW HEIGHT ) ) ;

break ;

//

o b s z a r

r e n d e r i n g u a s p e k t

1 : 1

c a s e ASPECT 1 1 :
A s p e c t = ASPECT 1 1 ;
R esha pe

( g l u t G e t

(GLUT WINDOW WIDTH) , g l u t G e t

(GLUT WINDOW HEIGHT ) ) ;

break ;

background image

1. Definiowanie sceny 3D

4

//

w y j ś c i e

c a s e EXIT :

e x i t

( 0 ) ;

}

}

i n t

main

( i n t

a r g c ,

char ∗ a r g v [ ] )

{

//

i n i c j a l i z a c j a

b i b l i o t e k i

GLUT

g l u t I n i t

(& a r g c , a r g v ) ;

//

i n i c j a l i z a c j a

b u f o r a

r a m k i

g l u t I n i t D i s p l a y M o d e

(GLUT DOUBLE | GLUT RGB ) ;

//

r o z m i a r y

g ł ó w n e g o

o k n a

p r o g r a m u

g l u t I n i t W i n d o w S i z e

( 4 0 0 , 4 0 0 ) ;

//

u t w o r z e n i e

g ł ó w n e g o

o k n a

p r o g r a m u

g l u t C r e a t e W i n d o w

( ” Kwadrat 2 ” ) ;

//

d o ł ą c z e n i e

f u n k c j i

g e n e r u j ą c e j

s c e n ę

3D

g l u t D i s p l a y F u n c

( D i s p l a y ) ;

//

d o ł ą c z e n i e

f u n k c j i

w y w o ł y w a n e j

p r z y

z m i a n i e

r o z m i a r u

o k n a

g l u t R e s h a p e F u n c

( Re sha pe ) ;

//

u t w o r z e n i e

menu

p o d r ę c z n e g o

g l u t C r e a t e M e n u

( Menu ) ;

//

d o d a n i e

p o z y c j i

do menu

p o d r ę c z n e g o

#i f d e f WIN32

glutAddMenuEntry

( ” O b s z a r

r e n d e r i n g u − c a ł e

okno ” ,FULL WINDOW ) ;

glutAddMenuEntry

( ” O b s z a r

r e n d e r i n g u − a s p e k t

1 : 1 ” , ASPECT 1 1 ) ;

glutAddMenuEntry

( ” W y j ś c i e ” , EXIT ) ;

#e l s e

glutAddMenuEntry

( ” O b s z a r

r e n d e r i n g u − c a l e

okno ” ,FULL WINDOW ) ;

glutAddMenuEntry

( ” O b s z a r

r e n d e r i n g u − a s p e k t

1 : 1 ” , ASPECT 1 1 ) ;

glutAddMenuEntry

( ” W y j s c i e ” , EXIT ) ;

#e n d i f

//

o k r e ś l e n i e

p r z y c i s k u

m y s z k i

o b s ł u g u j ą c e j

menu

p o d r ę c z n e

g l u t A t t a c h M e n u

(GLUT RIGHT BUTTON ) ;

//

w p r o w a d z e n i e

p r o g r a m u

do

o b s ł u g i

p ę t l i

k o m u n i k a t ó w

g l u t M a i n L o o p

( ) ;

return

0 ;

}

1.2. Rzutowanie prostokątne

Rzutowaniem określamy odwzorowanie zawartości trójwymiarowej sceny

graficznej na płaskim ekranie monitora. Biblioteka OpenGL oferuje standar-
dowo dwie metody rzutowania: rzutowanie prostokątne i rzutowanie perspek-
tywiczne. Domyślnie stosowane jest rzutowanie prostokątne.

W rzutowaniu prostokątnym (lub ortogonalnym) proste rzutowania są

prostopadłe do rzutni, która jest reprezentowana przez obszar renderingu.
Z rzutowaniem prostokątnym ściśle związane jest pojęcie bryły odcinania -
prostopadłościanu, który stanowi ograniczenie sceny 3D. Obiekty znajdujące
się poza bryłą odcinania nie są rysowane, a obiekty ją przecinające rysowane
są tylko częściowo.

background image

1. Definiowanie sceny 3D

5

Rozmiar bryły odcinania w rzutowaniu prostokątnym określa funkcja:

void glOrtho (GLdouble left, GLdouble right,

GLdouble bottom, GLdouble top,
GLdouble near, GLdouble far)

której parametry określają współrzędne punktów przecięcia płaszczyzn two-
rzących bryłę odcinania z osiami układu współrzędnych kartezjańskich. Płasz-
czyzny te opisane są następującymi równaniami:

x = right
x = lef t
y = top
y = bottm
z = −near
z = −f ar

Obszar renderingu zawiera się w płaszczyźnie o równaniu z = −near.

Położenie poszczególnych płaszczyzn tworzących bryłę odcinania przedsta-
wia rysunek 3. Trzeba jednak wyraźnie zwrócić uwagę, że początek układu
współrzędnych nie musi znajdować się wewnątrz bryły odcinania - rozmiary
i położenie bryły ograniczone są jedynie zakresem stosowanych liczb.

bottom

right

left

top

-near

-far

X

Y

Z

Rysunek 3. Położenie płaszczyzn bryły odcinania w rzutowaniu prostokąt-

nym

background image

1. Definiowanie sceny 3D

6

Domyślnie bryła odcinania ma postać sześcianu o bokach równych 2, któ-

rego środek pokrywa się z początkiem układu współrzędnych, co odpowia-
da wywołaniu funkcji glOrtho (-1,1,-1,1,-1,1). Oś OZ jest prostopadła
do płaszczyzny obszaru renderingu i przechodzi przez środek tego obsza-
ru. Dlatego rysowany w pierwszym i drugim programie kwadrat zajmował
początkowo czwartą część okna.

Funkcja glOrtho tworzy macierz rzutu prostokątnego:





2

right−lef t

0

0

right+lef t
right−lef t

0

2

top−bottom

0

top+bottom
top−bottom

0

0

−2

f ar−near

f ar+near
f ar−near

0

0

0

1





która jest następnie mnożona przez bieżącą macierz i umieszczona na szczy-
cie stosu z bieżącą macierzą. OpenGL zawiera kilka stosów macierzy, z któ-
rych w przykładowym programie wykorzystamy stos macierzy rzutowania
oraz stos macierzy modelowania. Wybór bieżącej macierzy umożliwia funk-
cja:

void glMatrixMode (GLenum mode)

gdzie parametr mode może przyjąć jedną z wartości:
— GL MODELVIEW - macierz modelowania,
— GL PROJECTION - macierz rzutowania,
— GL TEXTURE - macierz tekstury (omówiona później).

Ponieważ początkowa wartość wybranej macierzy jest nieokreślona, przed

wywołaniem glOrtho należy bieżącej macierzy przyporządkować macierz
jednostkową. Najłatwiej można to zrobić używając funkcji:

void glLoadIdentity (void)

Analogiczne postępowanie dotyczy macierzy modelowania. Po jej wyborze
przykładowym programie (plik szescian1.cpp) w funkcji Display macierzy
modelowania także przyporządkowywana jest macierz jednostkowa.

Jeżeli renderowana scena jest dwuwymiarowa, do ustawienia parametrów

bryły odcinania w rzutowaniu prostokątnym można użyć funkcji z biblioteki
GLU:

void gluOrtho2D (GLdouble left, GLdouble right,

GLdouble bottom, GLdouble top)

której parametry left, right, bottom i top odpowiadają parametrom funk-
cji glOrtho, a przednia (near) i tylna (far) płaszczyzna obcinania mają
wartości odpowiednio -1 i 1.

background image

1. Definiowanie sceny 3D

7

W przykładowym programie początkowa bryła odcinania ma postać sze-

ścianu o krawędziach długości 4, a rysowana figura - także sześcian - ma
krawędzie o długości 2. Centralne umieszczenie rysowanego sześcianu w po-
łączeniu z zastosowanym rzutowaniem prostokątnym daje w efekcie kwadrat
(patrz rysunek 4). Podobnie jak w poprzednim programie możliwy jest wy-
bór, czy scena ma być rysowana z zachowaniem początkowego aspektu ob-
razu czy też bez zachowania tej proporcji. Jednak w tym przypadku nie jest
modyfikowany obszar renderingu ale współrzędne bryły odcinania (funkcja
Reshape).

Rysunek 4. Początkowe okno programu Sześcian 1

1.2.1. Plik szescian1.cpp

/

( c )

J a n u s z

G a n c z a r s k i

h t t p : / / www . j a n u s z g . h g . p l

J a n u s z G @ e n t e r . n e t . p l
/

#i n c l u d e <GL/ g l u t . h>
#i n c l u d e < s t d l i b . h>

//

s t a ł e

do

o b s ł u g i

menu

p o d r ę c z n e g o

enum

{

background image

1. Definiowanie sceny 3D

8

FULL WINDOW,

//

a s p e k t

o b r a z u c a ł e

o k n o

ASPECT 1 1 ,

//

a s p e k t

o b r a z u

1 : 1

EXIT

//

w y j ś c i e

} ;

//

a s p e k t

o b r a z u

i n t

A s p e c t = FULL WINDOW ;

//

f u n k c j a

g e n e r u j ą c a

s c e n ę

3D

void

D i s p l a y

( )

{

//

k o l o r

t ł a z a w a r t o ś ć

b u f o r a

k o l o r u

g l C l e a r C o l o r

( 1 . 0 , 1 . 0 , 1 . 0 , 1 . 0 ) ;

//

c z y s z c z e n i e

b u f o r a

k o l o r u

g l C l e a r

( GL COLOR BUFFER BIT ) ;

//

w y b ó r

m a c i e r z y

m o d e l o w a n i a

g l M a t r i x M o d e

(GL MODELVIEW ) ;

//

m a c i e r z

m o d e l o w a n i a = m a c i e r z

j e d n o s t k o w a

g l L o a d I d e n t i t y

( ) ;

//

k o l o r

k r a w ę d z i

s z e ś c i a n u

g l C o l o r 3 f

( 0 . 0 , 0 . 0 , 0 . 0 ) ;

//

p o c z ą t e k

d e f i n i c j i

k r a w ę d z i

s z e ś c i a n u

g l B e g i n

( GL LINES ) ;

//

w s p ó ł r z ę d n e

k o l e j n y c h

k r a w ę d z i

s z e ś c i a n u

g l V e r t e x 3 f

( 1 . 0 ,

1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

− 1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

− 1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

− 1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

− 1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

− 1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

− 1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

− 1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

− 1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

− 1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

− 1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

− 1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

− 1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

1 . 0 ,

− 1 . 0 ) ;

//

k o n i e c

d e f i n i c j i

p r y m i t y w u

g l E n d

( ) ;

//

s k i e r o w a n i e

p o l e c e ń

do

w y k o n a n i a

g l F l u s h

( ) ;

//

z a m i a n a

b u f o r ó w

k o l o r u

g l u t S w a p B u f f e r s ( ) ;

}

//

z m i a n a

w i e l k o ś c i

o k n a

background image

1. Definiowanie sceny 3D

9

void

R esh ape

( i n t

width ,

i n t

h e i g h t )

{

//

o b s z a r

r e n d e r i n g u c a ł e

o k n o

g l V i e w p o r t

( 0 , 0 , width , h e i g h t ) ;

//

w y b ó r

m a c i e r z y

r z u t o w a n i a

g l M a t r i x M o d e

(GL PROJECTION ) ;

//

m a c i e r z

r z u t o w a n i a = m a c i e r z

j e d n o s t k o w a

g l L o a d I d e n t i t y

( ) ;

//

p a r a m e t r y

b r y ł y

o b c i n a n i a

i f

( A s p e c t == ASPECT 1 1 )

{

//

w y s o k o ś ć

o k n a

w i ę k s z a

od

w y s o k o ś c i

o k n a

i f

( w i d t h < h e i g h t && w i d t h > 0 )

g l O r t h o

( − 2 . 0 , 2 . 0 , − 2 . 0 ∗ h e i g h t / width , 2 . 0 ∗ h e i g h t / width , − 2 . 0 , 2 . 0 ) ;

e l s e

//

s z e r o k o ś ć

o k n a

w i ę k s z a

l u b

równa

w y s o k o ś c i

o k n a

i f

( w i d t h >= h e i g h t && h e i g h t > 0 )

g l O r t h o

( − 2 . 0 ∗ w i d t h / h e i g h t , 2 . 0 ∗ w i d t h / h e i g h t , − 2 . 0 , 2 . 0 , − 2 . 0 , 2 . 0 ) ;

}

e l s e

g l O r t h o

( − 2 . 0 , 2 . 0 , − 2 . 0 , 2 . 0 , − 2 . 0 , 2 . 0 ) ;

//

g e n e r o w a n i e

s c e n y

3D

D i s p l a y

( ) ;

}

//

o b s ł u g a

menu

p o d r ę c z n e g o

void Menu ( i n t

v a l u e )

{

switch

( v a l u e )

{

//

o b s z a r

r e n d e r i n g u c a ł e

o k n o

c a s e FULL WINDOW :

A s p e c t = FULL WINDOW ;
R esha pe

( g l u t G e t

(GLUT WINDOW WIDTH) , g l u t G e t

(GLUT WINDOW HEIGHT ) ) ;

break ;

//

o b s z a r

r e n d e r i n g u a s p e k t

1 : 1

c a s e ASPECT 1 1 :

A s p e c t = ASPECT 1 1 ;
R esha pe

( g l u t G e t

(GLUT WINDOW WIDTH) , g l u t G e t

(GLUT WINDOW HEIGHT ) ) ;

break ;

//

w y j ś c i e

c a s e EXIT :

e x i t

( 0 ) ;

}

}

i n t

main

( i n t

a r g c ,

char ∗ a r g v [ ] )

{

//

i n i c j a l i z a c j a

b i b l i o t e k i

GLUT

g l u t I n i t

(& a r g c , a r g v ) ;

//

i n i c j a l i z a c j a

b u f o r a

r a m k i

g l u t I n i t D i s p l a y M o d e

(GLUT DOUBLE | GLUT RGB ) ;

//

r o z m i a r y

g ł ó w n e g o

o k n a

p r o g r a m u

g l u t I n i t W i n d o w S i z e

( 4 0 0 , 4 0 0 ) ;

//

u t w o r z e n i e

g ł ó w n e g o

o k n a

p r o g r a m u

#i f d e f WIN32

g l u t C r e a t e W i n d o w

( ” S z e ś c i a n

1 ” ) ;

#e l s e

g l u t C r e a t e W i n d o w

( ” S z e s c i a n

1 ” ) ;

#e n d i f

//

d o ł ą c z e n i e

f u n k c j i

g e n e r u j ą c e j

s c e n ę

3D

g l u t D i s p l a y F u n c

( D i s p l a y ) ;

//

d o ł ą c z e n i e

f u n k c j i

w y w o ł y w a n e j

p r z y

z m i a n i e

r o z m i a r u

o k n a

g l u t R e s h a p e F u n c

( Re sha pe ) ;

//

u t w o r z e n i e

menu

p o d r ę c z n e g o

g l u t C r e a t e M e n u

( Menu ) ;

background image

1. Definiowanie sceny 3D

10

//

d o d a n i e

p o z y c j i

do menu

p o d r ę c z n e g o

#i f d e f WIN32

glutAddMenuEntry

( ” A s p e k t

o b r a z u − c a ł e

okno ” ,FULL WINDOW ) ;

glutAddMenuEntry

( ” A s p e k t

o b r a z u

1 : 1 ” , ASPECT 1 1 ) ;

glutAddMenuEntry

( ” W y j ś c i e ” , EXIT ) ;

#e l s e

glutAddMenuEntry

( ” A s p e k t

o b r a z u − c a l e

okno ” ,FULL WINDOW ) ;

glutAddMenuEntry

( ” A s p e k t

o b r a z u

1 : 1 ” , ASPECT 1 1 ) ;

glutAddMenuEntry

( ” W y j s c i e ” , EXIT ) ;

#e n d i f

//

o k r e ś l e n i e

p r z y c i s k u

m y s z k i

o b s ł u g u j ą c e j

menu

p o d r ę c z n e

g l u t A t t a c h M e n u

(GLUT RIGHT BUTTON ) ;

//

w p r o w a d z e n i e

p r o g r a m u

do

o b s ł u g i

p ę t l i

k o m u n i k a t ó w

g l u t M a i n L o o p

( ) ;

return

0 ;

}

1.3. Rzutowanie perspektywiczne

Rzutowanie perspektywiczne daje bardziej realistyczne efekty niż rzuto-

wanie prostokątne, stąd jest szeroko stosowane np. w grach. Parametry bryły
odcinania, która przy rzutowaniu perspektywicznym ma postać ostrosłupa
ściętego o wierzchołku znajdującym się w początku układu współrzędnych
(patrz rysunek 5), określa funkcja:

void glFrustum (GLdouble left, GLdouble right,

GLdouble bottom, GLdouble top,
GLdouble near, GLdouble far)

Parametry left, right, bottom i top wyznaczają rozmiary górnej pod-

stawy bryły odcinania (jest to obszar bezpośrednio odwzorowywany na ob-
szar renderingu), a near i far wyznaczają położenie odpowiednio górnej
i dolnej podstawy ostrosłupa (przedniej i tylnej płaszczyzny odcinania),
które zawierają się w płaszczyznach o równaniach: z = −near i z = −f ar.
Parametry near i far muszą mieć wartości dodatnie.

Macierz rzutowania perspektywicznego, tworzona przez funkcję glFrus-

tum i mnożona przez aktualnie wybraną macierz, ma postać:





2near

right−lef t

0

right+lef t
right−lef t

0

0

2near

top−bottom

top+bottom
top−bottom

0

0

0

f ar+near
f ar−near

2f ar·near
f ar−near

0

0

−1

0





Warto zauważyć, że precyzja działania jeszcze przez nas nieużywanego

z-bufora, zależy od wartości stosunku parametrów near i far:

r =

f ar

near

background image

1. Definiowanie sceny 3D

11

bottom

right

left

top

-near

-far

X

Y

Z

Rysunek 5. Położenie płaszczyzn bryły odcinania w rzutowaniu perspekty-

wicznym

Im większa wartość r, tym mniej efektywne jest działanie z-bufora. Oczy-
wiście near nigdy nie może przyjąć wartości równej 0, bowiem przednia
płaszczyzna odcinania przechodziła by wówczas przez środek perspektywy.

Alternatywny sposób określania rzutu perspektywicznego umożliwia funk-

cja z biblioteki GLU:

void gluPerspective (GLdouble fovy,

GLdouble aspect,
GLdouble zNear,
GLdouble zFar)

gdzie parametr fovy określa w stopniach kąt widzenia obserwatora zawar-
ty w płaszczyźnie YZ (

6

(top, 0, bottom)), a aspect jest stosunkiem szero-

kości do wysokości przedniej płaszczyzny odcinania, czyli górnej podstawy
ostrosłupa ograniczającego scenę 3D. Parametry zNear i zFar odpowiadają
parametrom near i far funkcji glFrustum.

background image

1. Definiowanie sceny 3D

12

Macierz rzutowania perspektywicznego, tworzona przez funkcję gluPer-

spective i mnożona przez aktualnie wybraną macierz, ma postać:





ctg

f ovy

2

aspect

0

0

0

0

ctg

f ovy

2

0

0

0

0

zF ar+zN ear
zN ear−zF ar

2·zF ar·zN ear

zN ear−zF ar

0

0

−1

0





Wewnętrznie funkcja gluPerspective wykorzystuje do ustawienia ma-

cierzy rzutowania perspektywicznego funkcję glFrustum. Oto wzory prze-
kształcenia parametrów funkcji gluPerspective na parametry glFrustum:

lef t = −aspect · zN ear · tg



π

f ovy

360



right = aspect · zN ear · tg



π

f ovy

360



bottom = −zN ear · tg



π

f ovy

360



top = zN ear · tg



π

f ovy

360



W kolejnym przykładowym programie (plik szescian2.cpp) do utworze-

nia macierzy rzutowania perspektywicznego wykorzystamy funkcję glFrus-
tum. Przednia płaszczyzna odcinania będzie miała takie same rozmiary jak
w poprzednim programie. Zmianie ulegną natomiast współrzędne przedniej
i tylnej płaszczyzny obcinania - poprzednio jedna z tych płaszczyzn miała
wartość ujemną, której nie akceptuje funkcja glFrustum.

Rysowanym obiektem ponownie będzie sześcian ale próba narysowania

go w tym samym miejscu jak w poprzednim programie spowoduje, że będzie
widoczna tylko jedna jego ściana. Wszystko dlatego, że pozostałe ściany
sześcianu znajdują się poza obszarem bryły odcinania. Możliwe są trzy spo-
soby rozwiązania tego problemu. Pierwszy polega na zmianie współrzędnych
wierzchołków sześcianu w taki sposób, aby sześcian zmieścił się w zmienio-
nej bryle obcinania. Rozwiązanie to ma jedną zasadniczą wadę - wierzchołki
sześcianu trzeba będzie modyfikować przy każdej zmianie parametrów sceny
3D. W przypadku jednego obiektu nie stanowi to specjalnego problemu, ale
czyni pomysł niewykonalnym przy każdej bardziej skomplikowanej scenie
3D.

Drugie, zastosowane w programie rozwiązanie, polega na przesunięciu

wierzchołków sześcianu o wektor [0, 0, −3], czyli o -3 jednostki wzdłuż osi
OZ. Realizuje to funkcja glTranslatef, która wywoływana jest bezpośred-
nio po zainicjowaniu macierzy modelowania macierzą jednostkową (patrz
funkcja Display). W efekcie otrzymamy sześcian przedstawiony na rysun-
ku 6. Należy dodać, że taka metoda jest często stosowaną praktyką. Obiekty
3D definiowane są z różnymi współrzędnymi, a następnie odpowiednio trans-
formowane do docelowego położenia w scenie 3D. Funkcje umożliwiające

background image

1. Definiowanie sceny 3D

13

takie przekształcenia poznamy bliżej w następnym odcinku kursu. Trzecią
metodą jest modyfikacja położenia obserwatora sceny 3D - zapoznamy się
z tą techniką jeszcze w tym odcinku.

Rysunek 6. Początkowe okno programu Sześcian 2

1.3.1. Plik szescian2.cpp

/

( c )

J a n u s z

G a n c z a r s k i

h t t p : / / www . j a n u s z g . h g . p l

J a n u s z G @ e n t e r . n e t . p l
/

#i n c l u d e <GL/ g l u t . h>
#i n c l u d e < s t d l i b . h>

//

s t a ł e

do

o b s ł u g i

menu

p o d r ę c z n e g o

enum

{

FULL WINDOW,

//

a s p e k t

o b r a z u c a ł e

o k n o

ASPECT 1 1 ,

//

a s p e k t

o b r a z u

1 : 1

EXIT

//

w y j ś c i e

} ;

//

a s p e k t

o b r a z u

i n t

A s p e c t = FULL WINDOW ;

//

f u n k c j a

g e n e r u j ą c a

s c e n ę

3D

void

D i s p l a y

( )

background image

1. Definiowanie sceny 3D

14

{

//

k o l o r

t ł a z a w a r t o ś ć

b u f o r a

k o l o r u

g l C l e a r C o l o r

( 1 . 0 , 1 . 0 , 1 . 0 , 1 . 0 ) ;

//

c z y s z c z e n i e

b u f o r a

k o l o r u

g l C l e a r

( GL COLOR BUFFER BIT ) ;

//

w y b ó r

m a c i e r z y

m o d e l o w a n i a

g l M a t r i x M o d e

(GL MODELVIEW ) ;

//

m a c i e r z

m o d e l o w a n i a = m a c i e r z

j e d n o s t k o w a

g l L o a d I d e n t i t y

( ) ;

//

p r z e s u n i ę c i e

o b i e k t u

o

w e k t o r

[ 0 , 0 , 3 ]

g l T r a n s l a t e f

( 0 , 0 , − 3 . 0 ) ;

//

k o l o r

k r a w ę d z i

s z e ś c i a n u

g l C o l o r 3 f

( 0 . 0 , 0 . 0 , 0 . 0 ) ;

//

p o c z ą t e k

d e f i n i c j i

k r a w ę d z i

s z e ś c i a n u

g l B e g i n

( GL LINES ) ;

//

w s p ó l r z ę d n e

k o l e j n y c h

k r a w ę d z i

s z e ś c i a n u

g l V e r t e x 3 f

( 1 . 0 ,

1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

− 1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

− 1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

− 1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

− 1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

− 1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

− 1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

− 1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

− 1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

− 1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

− 1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

− 1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

− 1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

1 . 0 ,

− 1 . 0 ) ;

//

k o n i e c

d e f i n i c j i

p r y m i t y w u

g l E n d

( ) ;

//

s k i e r o w a n i e

p o l e c e ń

do

w y k o n a n i a

g l F l u s h

( ) ;

//

z a m i a n a

b u f o r ó w

k o l o r u

g l u t S w a p B u f f e r s ( ) ;

}

//

z m i a n a

w i e l k o ś c i

o k n a

void

R esh ape

( i n t

width ,

i n t

h e i g h t )

{

//

o b s z a r

r e n d e r i n g u c a ł e

o k n o

g l V i e w p o r t

( 0 , 0 , width , h e i g h t ) ;

//

w y b ó r

m a c i e r z y

r z u t o w a n i a

g l M a t r i x M o d e

(GL PROJECTION ) ;

//

m a c i e r z

r z u t o w a n i a = m a c i e r z

j e d n o s t k o w a

background image

1. Definiowanie sceny 3D

15

g l L o a d I d e n t i t y

( ) ;

//

p a r a m e t r y

b r y ł y

o b c i n a n i a

i f

( A s p e c t == ASPECT 1 1 )

{

//

w y s o k o ś ć

o k n a

w i ę k s z a

od

w y s o k o ś c i

o k n a

i f

( w i d t h < h e i g h t && w i d t h > 0 )

g l F r u s t u m

( − 2 . 0 , 2 . 0 , − 2 . 0 ∗ h e i g h t / width , 2 . 0 ∗ h e i g h t / width , 1 . 0 , 5 . 0 ) ;

e l s e

//

s z e r o k o ś ć

o k n a

w i ę k s z a

l u b

równa

w y s o k o ś c i

o k n a

i f

( w i d t h >= h e i g h t && h e i g h t > 0 )

g l F r u s t u m

( − 2 . 0 ∗ w i d t h / h e i g h t , 2 . 0 ∗ w i d t h / h e i g h t , − 2 . 0 , 2 . 0 , 1 . 0 , 5 . 0 ) ;

}

e l s e

g l F r u s t u m

( − 2 . 0 , 2 . 0 , − 2 . 0 , 2 . 0 , 1 . 0 , 5 . 0 ) ;

//

g e n e r o w a n i e

s c e n y

3D

D i s p l a y

( ) ;

}

//

o b s ł u g a

menu

p o d r ę c z n e g o

void Menu ( i n t

v a l u e )

{

switch

( v a l u e )

{

//

o b s z a r

r e n d e r i n g u c a ł e

o k n o

c a s e FULL WINDOW :
A s p e c t = FULL WINDOW ;
R esha pe

( g l u t G e t

(GLUT WINDOW WIDTH) , g l u t G e t

(GLUT WINDOW HEIGHT ) ) ;

break ;

//

o b s z a r

r e n d e r i n g u a s p e k t

1 : 1

c a s e ASPECT 1 1 :
A s p e c t = ASPECT 1 1 ;
R esha pe

( g l u t G e t

(GLUT WINDOW WIDTH) , g l u t G e t

(GLUT WINDOW HEIGHT ) ) ;

break ;

//

w y j ś c i e

c a s e EXIT :

e x i t

( 0 ) ;

}

}

i n t

main

( i n t

a r g c ,

char ∗ a r g v [ ] )

{

//

i n i c j a l i z a c j a

b i b l i o t e k i

GLUT

g l u t I n i t

(& a r g c , a r g v ) ;

//

i n i c j a l i z a c j a

b u f o r a

r a m k i

g l u t I n i t D i s p l a y M o d e

(GLUT DOUBLE | GLUT RGB ) ;

//

r o z m i a r y

g ł ó w n e g o

o k n a

p r o g r a m u

g l u t I n i t W i n d o w S i z e

( 4 0 0 , 4 0 0 ) ;

//

u t w o r z e n i e

g ł ó w n e g o

o k n a

p r o g r a m u

#i f d e f WIN32

g l u t C r e a t e W i n d o w

( ” S z e ś c i a n

2 ” ) ;

#e l s e

g l u t C r e a t e W i n d o w

( ” S z e ś c i a n

2 ” ) ;

#e n d i f

//

d o ł ą c z e n i e

f u n k c j i

g e n e r u j ą c e j

s c e n ę

3D

g l u t D i s p l a y F u n c

( D i s p l a y ) ;

//

d o ł ą c z e n i e

f u n k c j i

w y w o ł y w a n e j

p r z y

z m i a n i e

r o z m i a r u

o k n a

g l u t R e s h a p e F u n c

( Re sha pe ) ;

//

u t w o r z e n i e

menu

p o d r ę c z n e g o

g l u t C r e a t e M e n u

( Menu ) ;

//

d o d a n i e

p o z y c j i

do menu

p o d r ę c z n e g o

#i f d e f WIN32

glutAddMenuEntry

( ” A s p e k t

o b r a z u − c a ł e

okno ” ,FULL WINDOW ) ;

glutAddMenuEntry

( ” A s p e k t

o b r a z u

1 : 1 ” , ASPECT 1 1 ) ;

glutAddMenuEntry

( ” W y j ś c i e ” , EXIT ) ;

background image

1. Definiowanie sceny 3D

16

#e l s e

glutAddMenuEntry

( ” A s p e k t

o b r a z u − c a l e

okno ” ,FULL WINDOW ) ;

glutAddMenuEntry

( ” A s p e k t

o b r a z u

1 : 1 ” , ASPECT 1 1 ) ;

glutAddMenuEntry

( ” W y j s c i e ” , EXIT ) ;

#e n d i f

//

o k r e ś l e n i e

p r z y c i s k u

m y s z k i

o b s ł u g u j ą c e j

menu

p o d r ę c z n e

g l u t A t t a c h M e n u

(GLUT RIGHT BUTTON ) ;

//

w p r o w a d z e n i e

p r o g r a m u

do

o b s ł u g i

p ę t l i

k o m u n i k a t ó w

g l u t M a i n L o o p

( ) ;

return

0 ;

}

Drugi program przedstawiający rzutowanie perspektywiczne (plik szes-

cian3.cpp) stosuje funkcję gluPerspective. Aby jednak nie powielać roz-
wiązań z poprzedniego programu dodamy mechanizm pokazujący jaki wpływ
na wygląd obiektów 3D ma zmiana położenie środka perspektywy, realizo-
wana poprzez zmianę kąta widzenia obserwatora (parametr fovy funkcji
gluPerspective). W tym celu potrzebna jest obsługa klawiatury. Podsta-
wowa funkcja obsługi klawiatury (w przykładowym programie jest to funkcja
Keyboard) ma trzy parametry:
— key - kod ASCII klawisza,
— x, y - współrzędne kursora myszki w chwili naciśnięcia przycisku klawia-

tury.
Aby obsługa klawiatury działała, w części głównej programu należy włą-

czyć funkcję obsługi klawiatury wywołując funkcję:

void glutKeyboardFunc (void (*func)(unsigned char key,

int x, int y))

Początkowe okno programu Sześcian 3 zawiera rysunek 7. Przyciskając

klawisze „+” i „-” można modyfikować kąt patrzenia obserwatora, który
początkowo wynosi 90

.

1.3.2. Plik szescian3.cpp

/

( c )

J a n u s z

G a n c z a r s k i

h t t p : / / www . j a n u s z g . h g . p l

J a n u s z G @ e n t e r . n e t . p l
/

#i n c l u d e <GL/ g l u t . h>
#i n c l u d e < s t d l i b . h>

//

s t a ł a

do

o b s ł u g i

menu

p o d r ę c z n e g o

enum

{

EXIT //

w y j ś c i e

} ;

//

p i o n o w y

k ą t

p o l a

w i d z e n i a

GLdouble

f o v y = 9 0 ;

//

f u n k c j a

g e n e r u j ą c a

s c e n ę

3D

void

D i s p l a y

( )

{

background image

1. Definiowanie sceny 3D

17

Rysunek 7. Początkowe okno programu Sześcian 3

//

k o l o r

t ł a z a w a r t o ś ć

b u f o r a

k o l o r u

g l C l e a r C o l o r

( 1 . 0 , 1 . 0 , 1 . 0 , 1 . 0 ) ;

//

c z y s z c z e n i e

b u f o r a

k o l o r u

g l C l e a r

( GL COLOR BUFFER BIT ) ;

//

w y b ó r

m a c i e r z y

m o d e l o w a n i a

g l M a t r i x M o d e

(GL MODELVIEW ) ;

//

m a c i e r z

m o d e l o w a n i a = m a c i e r z

j e d n o s t k o w a

g l L o a d I d e n t i t y

( ) ;

//

p r z e s u n i ę c i e

o b i e k t u

o

w e k t o r

[ 0 , 0 , 3 ]

g l T r a n s l a t e f

( 0 , 0 , − 3 . 0 ) ;

//

k o l o r

k r a w ę d z i

s z e ś c i a n u

g l C o l o r 3 f

( 0 . 0 , 0 . 0 , 0 . 0 ) ;

//

p o c z ą t e k

d e f i n i c j i

k r a w ę d z i

s z e ś c i a n u

g l B e g i n

( GL LINES ) ;

//

w s p ó l r z ę d n e

k o l e j n y c h

k r a w ę d z i

s z e ś c i a n u

g l V e r t e x 3 f

( 1 . 0 ,

1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

− 1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

− 1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

− 1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

− 1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

1 . 0 ,

1 . 0 ) ;

background image

1. Definiowanie sceny 3D

18

g l V e r t e x 3 f

( − 1 . 0 ,

− 1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

− 1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

− 1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

− 1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

− 1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

− 1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

− 1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

− 1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

1 . 0 ,

− 1 . 0 ) ;

//

k o n i e c

d e f i n i c j i

p r y m i t y w u

g l E n d

( ) ;

//

s k i e r o w a n i e

p o l e c e ń

do

w y k o n a n i a

g l F l u s h

( ) ;

//

z a m i a n a

b u f o r ó w

k o l o r u

g l u t S w a p B u f f e r s ( ) ;

}

//

z m i a n a

w i e l k o ś c i

o k n a

void

R esh ape

( i n t

width ,

i n t

h e i g h t )

{

//

o b s z a r

r e n d e r i n g u c a ł e

o k n o

g l V i e w p o r t

( 0 , 0 , width , h e i g h t ) ;

//

w y b ó r

m a c i e r z y

r z u t o w a n i a

g l M a t r i x M o d e

(GL PROJECTION ) ;

//

m a c i e r z

r z u t o w a n i a = m a c i e r z

j e d n o s t k o w a

g l L o a d I d e n t i t y

( ) ;

//

o b l i c z e n i e

a s p e k t u

o b r a z u

z

u w z g l ę d n i e n i e m

//

p r z y p a d k u ,

g d y

w y s o k o ś ć

o b r a z u

w y n o s i

0

GLdouble

a s p e c t = 1 ;

i f

( h e i g h t > 0 )

a s p e c t = w i d t h / ( GLdouble ) h e i g h t ;

//

r z u t o w a n i e

p e r s p e k t y w i c z n e

g l u P e r s p e c t i v e

( f o v y , a s p e c t , 1 . 0 , 5 . 0 ) ;

//

g e n e r o w a n i e

s c e n y

3D

D i s p l a y

( ) ;

}

//

o b s ł u g a

k l a w i a t u r y

void Keyboard

( unsigned char key ,

i n t x ,

i n t

y )

{

//

k l a w i s z +

i f

( k e y == ’+ ’ && f o v y < 1 8 0 )

f o v y ++;

e l s e

//

k l a w i s z

i f

( k e y == ’− ’ && f o v y > 0 )

f o v y −−;

//

o d r y s o w a n i e

o k n a

R esh ape

( g l u t G e t

(GLUT WINDOW WIDTH) , g l u t G e t

(GLUT WINDOW HEIGHT ) ) ;

}

//

o b s ł u g a

menu

p o d r ę c z n e g o

void Menu ( i n t

v a l u e )

{

background image

1. Definiowanie sceny 3D

19

switch

( v a l u e )

{

//

w y j ś c i e

c a s e EXIT :

e x i t

( 0 ) ;

}

}

i n t

main

( i n t

a r g c ,

char ∗ a r g v [ ] )

{

//

i n i c j a l i z a c j a

b i b l i o t e k i

GLUT

g l u t I n i t

(& a r g c , a r g v ) ;

//

i n i c j a l i z a c j a

b u f o r a

r a m k i

g l u t I n i t D i s p l a y M o d e

(GLUT DOUBLE | GLUT RGB ) ;

//

r o z m i a r y

g ł ó w n e g o

o k n a

p r o g r a m u

g l u t I n i t W i n d o w S i z e

( 4 0 0 , 4 0 0 ) ;

//

u t w o r z e n i e

g ł ó w n e g o

o k n a

p r o g r a m u

#i f d e f WIN32

g l u t C r e a t e W i n d o w

( ” S z e ś c i a n

3 ” ) ;

#e l s e

g l u t C r e a t e W i n d o w

( ” S z e s c i a n

3 ” ) ;

#e n d i f

//

d o ł ą c z e n i e

f u n k c j i

g e n e r u j ą c e j

s c e n ę

3D

g l u t D i s p l a y F u n c

( D i s p l a y ) ;

//

d o ł ą c z e n i e

f u n k c j i

w y w o ł y w a n e j

p r z y

z m i a n i e

r o z m i a r u

o k n a

g l u t R e s h a p e F u n c

( Re sha pe ) ;

//

d o ł ą c z e n i e

f u n k c j i

o b s ł u g i

k l a w i a t u r y

g l u t K e y b o a r d F u n c

( Keyboard ) ;

//

u t w o r z e n i e

menu

p o d r ę c z n e g o

g l u t C r e a t e M e n u

( Menu ) ;

//

d o d a n i e

p o z y c j i

do menu

p o d r ę c z n e g o

#i f d e f WIN32

glutAddMenuEntry

( ” W y j ś c i e ” , EXIT ) ;

#e l s e

glutAddMenuEntry

( ” W y j s c i e ” , EXIT ) ;

#e n d i f

//

o k r e ś l e n i e

p r z y c i s k u

m y s z k i

o b s ł u g u j ą c e j

menu

p o d r ę c z n e

g l u t A t t a c h M e n u

(GLUT RIGHT BUTTON ) ;

//

w p r o w a d z e n i e

p r o g r a m u

do

o b s ł u g i

p ę t l i

k o m u n i k a t ó w

g l u t M a i n L o o p

( ) ;

return

0 ;

}

1.4. Położenie obserwatora

Ostatnim z podstawowych elementów wymagających omówienia przy

tworzeniu sceny 3D jest położenie obserwatora, nazywane także położeniem
kamery lub „oka”. Domyślnie obserwator w OpenGL położony jest w po-
czątku układu współrzędnych i skierowany jest w stronę ujemnej półosi OZ.
Obserwator jest tak zorientowany w przestrzeni, że kierunek „do góry” po-
krywa się z kierunkiem osi OY.

Zasadniczo OpenGL nie umożliwia zmiany położenia obserwatora.

Wszystkie przekształcenia położenia obserwatora faktycznie realizowane są
jako odpowiednie przekształcenia układu współrzędnych. Aby jednak uła-

background image

1. Definiowanie sceny 3D

20

twić prace związane z definiowaniem tych przekształceń, biblioteka GLU
zawiera funkcję gluLookAt, która pozwala na jednorazowe zdefiniowanie
wszystkich parametrów opisujących obserwatora:

void gluLookAt (GLdouble eyex, GLdouble eyey, GLdouble eyez,

GLdouble centerx, GLdouble centery,
GLdouble centerz,
GLdouble upx, GLdouble upy, GLdouble upz)

Kolejne trójki parametrów funkcji gluLookAt oznaczają:

— eyex, eyey, eyez - współrzędne położenia obserwatora,
— centerx, centery, centerz - współrzędne punktu, w którego kierunku

jest zwrócony obserwator,

— upx, upy, upz - współrzędne wektora określającego kierunek „do góry”.
Domyślne położenie obserwatora odpowiada wywołaniu

gluLookat (0.0, 0.0, 0.0, 0.0, 0.0, -100.0, 0.0, 1.0, 0.0)

W kolejnym przykładowym programie (plik szescian4.cpp) będziemy

modyfikować tylko współrzędne położenia obserwatora. Przy niezmiennych
współrzędnych punktu, w którego kierunku patrzy obserwator, daje to cie-
kawy efekt obserwacji sceny z pewnej odległości.

Zmiana położenia obserwatora realizowana jest w funkcjach Keyboard

(przyciski „+” i „-”) oraz SpecialKeys (klawisze kursora). Warto zauważyć,
że zmiany współrzędnych obserwatora, które reprezentują zmienne eyex,
eyey i eyez, są odwrotne niż można by się spodziewać. Przykładowo na-
ciśnięcie strzałki w dół powoduje zwiększenie o 0,1 zmiennej eyey, która
określa współrzędną Y położenia obserwatora. Jest to spowodowane tym,
że macierz modelowania, modyfikowana przy wywołaniu funkcji gluLookAt,
odgrywa podwójną rolę. Z jednej strony umożliwia przekształcenia współ-
rzędnych obiektu (patrz poprzedni przykład), a z drugiej przekształcenia
współrzędnych obserwatora. Przykładowo, to co z punktu widzenia obiek-
tu jest przesunięciem o wektor [1, 0, 0], dla obserwatora jest przesunięciem
o wektor przeciwny tj. [−1, 0, 0]. Dobre poznanie opisanego mechanizmy wy-
maga eksperymentów, do których gorąco zachęcam Czytelników.

Do omówienia pozostała wprowadzona w ostatnim przykładzie obsługa

klawiszy kursora. Jest ona realizowana odrębnie od obsługi przycisków, któ-
re reprezentowane są bezpośrednio przez kody ASCII (funkcja Keyboard).
Funkcja obsługująca klawisze kursora oraz przyciski funkcyjne (w przykła-
dowym programie jest to funkcja SpecialKeys) ma trzy parametry:
— key - kod przycisku; zwracana jest jedna z poniższych wartości:

— GLUT KEY F1 - przycisk F1,
— GLUT KEY F2 - przycisk F2,
— GLUT KEY F3 - przycisk F3,

background image

1. Definiowanie sceny 3D

21

— GLUT KEY F4 - przycisk F4,
— GLUT KEY F5 - przycisk F5,
— GLUT KEY F6 - przycisk F6,
— GLUT KEY F7 - przycisk F7,
— GLUT KEY F8 - przycisk F8,
— GLUT KEY F9 - przycisk F9,
— GLUT KEY F10 - przycisk F10,
— GLUT KEY F11 - przycisk F11,
— GLUT KEY F12 - przycisk F12,
— GLUT KEY LEFT - kursor w lewo,
— GLUT KEY UP - kursor do góry,
— GLUT KEY RIGHT - kursor w prawo,
— GLUT KEY DOWN - kursor w dół,
— GLUT KEY PAGE UP - przycisk Page Up
— GLUT KEY PAGE DOWN - przycisk Page Down,
— GLUT KEY HOME - przycisk Home,
— GLUT KEY END - przycisk End,
— GLUT KEY INSERT - przycisk Insert.

— x, y - współrzędne kursora myszki w chwili naciśnięcia przycisku klawia-

tury.
Podobnie jak w przypadku poprzedniej funkcji obsługującej klawiaturę,

w głównym programie należy włączyć obsługę klawiszy kursora i klawiszy
funkcyjnych wywołując funkcję:

void glutSpecialFunc (void (*func)(int key, int x, int y))

Rysunek 8 przedstawia przykładowe okno programu Sześcian 4, którego

kod źródłowy znajduje się poniżej.

1.4.1. Plik szescian4.cpp

/

( c )

J a n u s z

G a n c z a r s k i

h t t p : / / www . j a n u s z g . h g . p l

J a n u s z G @ e n t e r . n e t . p l
/

#i n c l u d e <GL/ g l u t . h>
#i n c l u d e < s t d l i b . h>

//

s t a ł e

do

o b s ł u g i

menu

p o d r ę c z n e g o

enum

{

FULL WINDOW,

//

a s p e k t

o b r a z u c a ł e

o k n o

ASPECT 1 1 ,

//

a s p e k t

o b r a z u

1 : 1

EXIT

//

w y j ś c i e

} ;

//

a s p e k t

o b r a z u

i n t

A s p e c t = FULL WINDOW ;

//

w p ó ł r z ę d n e

p o ł o ż e n i a

o b s e r w a t o r a

background image

1. Definiowanie sceny 3D

22

Rysunek 8. Przykładowe okno programu Sześcian 4

GLdouble

e y e x = 0 ;

GLdouble

e y e y = 0 ;

GLdouble

e y e z = 3 ;

//

w s p ó ł r z ę d n e

p u n k t u w k t ó r e g o

k i e r u n k u

j e s t

z w r ó c o n y

o b s e r w a t o r ,

GLdouble

c e n t e r x = 0 ;

GLdouble

c e n t e r y = 0 ;

GLdouble

c e n t e r z = −100;

//

f u n k c j a

g e n e r u j ą c a

s c e n ę

3D

void

D i s p l a y

( )

{

//

k o l o r

t ł a z a w a r t o ś ć

b u f o r a

k o l o r u

g l C l e a r C o l o r

( 1 . 0 , 1 . 0 , 1 . 0 , 1 . 0 ) ;

//

c z y s z c z e n i e

b u f o r a

k o l o r u

g l C l e a r

( GL COLOR BUFFER BIT ) ;

//

w y b ó r

m a c i e r z y

m o d e l o w a n i a

g l M a t r i x M o d e

(GL MODELVIEW ) ;

//

m a c i e r z

m o d e l o w a n i a = m a c i e r z

j e d n o s t k o w a

g l L o a d I d e n t i t y

( ) ;

//

u s t a w i e n i e

o b s e r w a t o r a

g l u L o o k A t

( e y e x , e y e y , e y e z , c e n t e r x , c e n t e r y , c e n t e r z , 0 , 1 , 0 ) ;

//

k o l o r

k r a w ę d z i

s z e ś c i a n u

g l C o l o r 3 f

( 0 . 0 , 0 . 0 , 0 . 0 ) ;

//

p o c z ą t e k

d e f i n i c j i

k r a w ę d z i

s z e ś c i a n u

g l B e g i n

( GL LINES ) ;

background image

1. Definiowanie sceny 3D

23

//

w s p ó l r z ę d n e

k o l e j n y c h

k r a w ę d z i

s z e ś c i a n u

g l V e r t e x 3 f

( 1 . 0 ,

1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

− 1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

− 1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

− 1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

− 1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

− 1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

− 1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

− 1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

− 1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

− 1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

− 1 . 0 ,

1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

− 1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

− 1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( 1 . 0 ,

1 . 0 ,

− 1 . 0 ) ;

g l V e r t e x 3 f

( − 1 . 0 ,

1 . 0 ,

− 1 . 0 ) ;

//

k o n i e c

d e f i n i c j i

p r y m i t y w u

g l E n d

( ) ;

//

s k i e r o w a n i e

p o l e c e ń

do

w y k o n a n i a

g l F l u s h

( ) ;

//

z a m i a n a

b u f o r ó w

k o l o r u

g l u t S w a p B u f f e r s ( ) ;

}

//

z m i a n a

w i e l k o ś c i

o k n a

void

R esh ape

( i n t

width ,

i n t

h e i g h t )

{

//

o b s z a r

r e n d e r i n g u c a ł e

o k n o

g l V i e w p o r t

( 0 , 0 , width , h e i g h t ) ;

//

w y b ó r

m a c i e r z y

r z u t o w a n i a

g l M a t r i x M o d e

(GL PROJECTION ) ;

//

m a c i e r z

r z u t o w a n i a = m a c i e r z

j e d n o s t k o w a

g l L o a d I d e n t i t y

( ) ;

//

p a r a m e t r y

b r y ł y

o b c i n a n i a

i f

( A s p e c t == ASPECT 1 1 )

{

//

w y s o k o ś ć

o k n a

w i ę k s z a

od

w y s o k o ś c i

o k n a

i f

( w i d t h < h e i g h t && w i d t h > 0 )

g l F r u s t u m

( − 2 . 0 , 2 . 0 , − 2 . 0 ∗ h e i g h t / width , 2 . 0 ∗ h e i g h t / width , 1 . 0 , 5 . 0 ) ;

e l s e

//

s z e r o k o ś ć

o k n a

w i ę k s z a

l u b

równa

w y s o k o ś c i

o k n a

i f

( w i d t h >= h e i g h t && h e i g h t > 0 )

g l F r u s t u m

( − 2 . 0 ∗ w i d t h / h e i g h t , 2 . 0 ∗ w i d t h / h e i g h t , − 2 . 0 , 2 . 0 , 1 . 0 , 5 . 0 ) ;

}

e l s e

g l F r u s t u m

( − 2 . 0 , 2 . 0 , − 2 . 0 , 2 . 0 , 1 . 0 , 5 . 0 ) ;

//

g e n e r o w a n i e

s c e n y

3D

D i s p l a y

( ) ;

}

//

o b s ł u g a

k l a w i a t u r y

background image

1. Definiowanie sceny 3D

24

void Keyboard

( unsigned char key ,

i n t x ,

i n t

y )

{

//

k l a w i s z +

i f

( k e y == ’+ ’ )

e y e z −= 0 . 1 ;

e l s e

//

k l a w i s z

i f

( k e y == ’− ’ )

e y e z += 0 . 1 ;

//

o d r y s o w a n i e

o k n a

R esh ape

( g l u t G e t

(GLUT WINDOW WIDTH) , g l u t G e t

(GLUT WINDOW HEIGHT ) ) ;

}

//

o b s ł u g a

k l a w i s z y

f u n k c y j n y c h

i

k l a w i s z y

k u r s o r a

void

S p e c i a l K e y s

( i n t

key ,

i n t x ,

i n t

y )

{

switch

( k e y )

{

//

k u r s o r w l e w o

c a s e GLUT KEY LEFT :
e y e x += 0 . 1 ;
break ;

//

k u r s o r w g ó r ę

c a s e GLUT KEY UP :
e y e y −= 0 . 1 ;
break ;

//

k u r s o r w p r a w o

c a s e GLUT KEY RIGHT :
e y e x −= 0 . 1 ;
break ;

//

k u r s o r w d ó ł

c a s e GLUT KEY DOWN :
e y e y += 0 . 1 ;
break ;

}

//

o d r y s o w a n i e

o k n a

R esh ape

( g l u t G e t

(GLUT WINDOW WIDTH) , g l u t G e t

(GLUT WINDOW HEIGHT ) ) ;

}

//

o b s ł u g a

menu

p o d r ę c z n e g o

void Menu ( i n t

v a l u e )

{

switch

( v a l u e )

{

//

o b s z a r

r e n d e r i n g u c a ł e

o k n o

c a s e FULL WINDOW :
A s p e c t = FULL WINDOW ;
R esha pe

( g l u t G e t

(GLUT WINDOW WIDTH) , g l u t G e t

(GLUT WINDOW HEIGHT ) ) ;

break ;

//

o b s z a r

r e n d e r i n g u a s p e k t

1 : 1

c a s e ASPECT 1 1 :
A s p e c t = ASPECT 1 1 ;
R esha pe

( g l u t G e t

(GLUT WINDOW WIDTH) , g l u t G e t

(GLUT WINDOW HEIGHT ) ) ;

break ;

//

w y j ś c i e

c a s e EXIT :

e x i t

( 0 ) ;

}

}

i n t

main

( i n t

a r g c ,

char ∗ a r g v [ ] )

{

//

i n i c j a l i z a c j a

b i b l i o t e k i

GLUT

g l u t I n i t

(& a r g c , a r g v ) ;

//

i n i c j a l i z a c j a

b u f o r a

r a m k i

g l u t I n i t D i s p l a y M o d e

(GLUT DOUBLE | GLUT RGB ) ;

//

r o z m i a r y

g ł ó w n e g o

o k n a

p r o g r a m u

background image

1. Definiowanie sceny 3D

25

g l u t I n i t W i n d o w S i z e

( 4 0 0 , 4 0 0 ) ;

//

u t w o r z e n i e

g ł ó w n e g o

o k n a

p r o g r a m u

#i f d e f WIN32

g l u t C r e a t e W i n d o w

( ” S z e ś c i a n

4 ” ) ;

#e l s e

g l u t C r e a t e W i n d o w

( ” S z e s c i a n

4 ” ) ;

#e n d i f

//

d o ł ą c z e n i e

f u n k c j i

g e n e r u j ą c e j

s c e n ę

3D

g l u t D i s p l a y F u n c

( D i s p l a y ) ;

//

d o ł ą c z e n i e

f u n k c j i

w y w o ł y w a n e j

p r z y

z m i a n i e

r o z m i a r u

o k n a

g l u t R e s h a p e F u n c

( Re sha pe ) ;

//

d o ł ą c z e n i e

f u n k c j i

o b s ł u g i

k l a w i a t u r y

g l u t K e y b o a r d F u n c

( Keyboard ) ;

//

d o ł ą c z e n i e

f u n k c j i

o b s ł u g i

k l a w i s z y

f u n k c y j n y c h

i

k l a w i s z y

k u r s o r a

g l u t S p e c i a l F u n c

( S p e c i a l K e y s ) ;

//

u t w o r z e n i e

menu

p o d r ę c z n e g o

g l u t C r e a t e M e n u

( Menu ) ;

//

d o d a n i e

p o z y c j i

do menu

p o d r ę c z n e g o

#i f d e f WIN32

glutAddMenuEntry

( ” A s p e k t

o b r a z u − c a ł e

okno ” ,FULL WINDOW ) ;

glutAddMenuEntry

( ” A s p e k t

o b r a z u

1 : 1 ” , ASPECT 1 1 ) ;

glutAddMenuEntry

( ” W y j ś c i e ” , EXIT ) ;

#e l s e

glutAddMenuEntry

( ” A s p e k t

o b r a z u − c a l e

okno ” ,FULL WINDOW ) ;

glutAddMenuEntry

( ” A s p e k t

o b r a z u

1 : 1 ” , ASPECT 1 1 ) ;

glutAddMenuEntry

( ” W y j s c i e ” , EXIT ) ;

#e n d i f

//

o k r e ś l e n i e

p r z y c i s k u

m y s z k i

o b s ł u g u j ą c e j

menu

p o d r ę c z n e

g l u t A t t a c h M e n u

(GLUT RIGHT BUTTON ) ;

//

w p r o w a d z e n i e

p r o g r a m u

do

o b s ł u g i

p ę t l i

k o m u n i k a t ó w

g l u t M a i n L o o p

( ) ;

return

0 ;

}

background image

Literatura

26

Literatura

[1] Mark Segal, Kurt Akeley: The OpenGL Graphics System. A Specification

Version 2.0

[2] Jackie Neider, Tom Davis, Mason Woo: OpenGL Programming Guide „The

Red Book”

[3] Richard S. Wright jr, Michael Sweet: OpenGL Księga eksperta, Helion 1999
[4] Richard S. Wright jr, Michael Sweet: OpenGL Księga eksperta Wydanie III,

Helion 2005

[5] The official OpenGL web page,

http://www.opengl.org

[6] Piotr Andrzejewski, Jakub Kurzak: Wprowadzenie do OpenGL. Programowa-

nie zastosowań graficznych, Kwantum 2000

[7] Kevin Hawkins, Dave Astle: OpenGL. Programowanie gier, Helion 2003
[8] Mark J. Kilgard: The OpenGL Utility Toolkit (GLUT) Programming Interface

API Version 3. Silicon Graphics, Inc. 1996


Document Outline


Wyszukiwarka

Podobne podstrony:
OpenGL Podstawy programowania grafiki 3D opglwp
OpenGL Podstawy programowania grafiki 3D
OpenGL Podstawy programowania grafiki 3D
OpenGL Podstawy programowania grafiki 3D 2
Definicja i podzia skazy krwotocznej
Przestrzenie 3D
Ewolucja marketingu era produkcyjna, sprzedazowa, marketingowa Rynek definicja
INTER 1 DEFINICJA
DEFINICJA STRESU
Definicje położnicze
1 1 bezpiecz definicjeid 8843 ppt
2 Podstawowe definicje (2)id 19609 ppt
2 definicje i sprawozdawczośćid 19489 ppt
3d i holografia
Definicja zakażenia szpitalnego
2 bezp narod pojęcia definicje

więcej podobnych podstron