Janusz Ganczarski
OpenGL
Selekcja obiektów
Spis treści
Spis treści . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
1. Selekcja obiektów . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
Zmiana trybu renderowania . . . . . . . . . . . . . . . . . . . . . . .
1
Stos nazw obiektów . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
Przetwarzanie rekordu trafień . . . . . . . . . . . . . . . . . . . . . .
2
Program przykładowy . . . . . . . . . . . . . . . . . . . . . . . . . .
3
Plik selekcja obiektow.cpp . . . . . . . . . . . . . . . . . . .
5
Literatura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
13
1. Selekcja obiektów
Tryb selekcji jest jednym z trzech trybów renderingu dostępnym w bi-
bliotece OpenGL. W trybie tym piksele nie są kopiowane do bufora ramki
obrazu. W zamian za to w buforze selekcji tworzona jest lista prymitywów,
których wierzchołki przecinają bryłę widzenia. Swoją budową bufor selekcji
nie przypomina żadnego innego opisywanego bufora OpenGL - jest to po
prostu jednowymiarowa tablica liczb całkowitych.
1.1. Zmiana trybu renderowania
Aby korzystać z selekcji obiektów w bibliotece OpenGL trzeba zmienić
tryb renderingu. Służy do tego funkcja:
GLint glRenderMode (GLenum mode)
której parametr mode przyjmuje następujące wartości:
— GL RENDER - tryb renderowania; jest to domyślny tryb renderingu,
— GL SELECT - tryb selekcji,
— GL FEEDBACK - tryb sprzężenia zwrotnego.
Wartość zwracana przez funkcję glRenderMode zależy od trybu renderin-
gu. W przypadku trybu renderowania funkcja zwraca wartość 0. W trybie
selekcji funkcja zwraca ilość rekordów trafień znajdujących się w buforze
selekcji. Jeżeli zabraknie miejsca w buforze selekcji funkcja zwróci wartość
-1. W ostatnim trybie sprzężenia zwrotnego funkcja zwraca ilość wartości
zapisanych w buforze sprzężenia zwrotnego.
Tryb sprzężenia zwrotnego zostanie omówiony oddzielnie. W tym miejscu
wspomnijmy jedynie, że w tym trybie piksele także nie są kopiowane do
bufora ramki obrazu.
1.2. Stos nazw obiektów
Nazwy obiektów, które mogą zostać wybrane w trakcie selekcji, biblio-
teka OpenGL przechowuje na stosie. Jedną nazwą można opisać zarówno
pojedynczy prymityw graficzny jak i dowolnie wybrana grupa obiektów.
Inicjalizację pustego stosu nazw obiektów wykonuje funkcja:
void glInitNames ()
Nazwy poszczególnym obiektom nadaje się wywołując funkcję:
void glLoadName (GLuint name)
gdzie parametr name jest unikatowym identyfikatorem obiektu. Funkcja ta
jednocześnie zastępuje nazwę znajdującą się aktualnie na szczycie stosu
nazw.
1. Selekcja obiektów
2
Jeżeli chcemy wykrywać selekcję obiektów o hierarchicznej strukturze
(np. elementy składowe złożonego obiektu) trzeba umieszczać kolejne nazwy
obiektów na bieżącym stosie. Realizuje to funkcja:
void glPushName (GLuint name)
której parametr name jest unikatowym identyfikatorem obiektu. Po zdefinio-
waniu obiektu podrzędnego trzeba zdjąć nazwę obiektu ze stosu, co wymaga
wywołania funkcji:
void glPopName ()
Wielkość stosu nazw jest określana przez implementację biblioteki, ale
nie może być mniejsza niż 64. Niedomiar i przepełnienie stosu powodu-
je zgłoszenie błędów: GL STACK UNDERFLOW i GL STACK OVERFLOW. Aktual-
ną głębokość stosu zwraca wywołanie funkcji z grupy glGet z parametrem
GL NAME STACK DEPTH, a ustalenie maksymalnej głębokości stosu wymaga
użycie funkcji z tej samej grupy z parametrm GL MAX NAME STACK DEPTH.
Wszystkie powyższe operacje na stosie nazw są ignorowane, gdy biblio-
teka OpenGL znajduje się w innym trybie renderingu niż tryb selekcji.
1.3. Przetwarzanie rekordu trafień
Ostatnią operacją, którą trzeba wykonać przy korzystaniu z selekcji obiek-
tów jest ustawienie bufora selekcji przechowującego dane obiektów wybra-
nych w trakcie selekcji. Wymaga to wywołania funkcji:
void glSelectBuffer (GLsizei size, GLuint *buffer)
gdzie parametr size określa wielkość bufora, do którego wskaźnik zawiera
parametr buffer. Bufor powinien być na tyle duży, aby zmieścić informa-
cje o wszystkich obiektach wybranych w wyniku selekcji, przy czym samo
ustawienie bufora selekcji musi zostać wykonane przed przełączeniem biblio-
teki OpenGL w tryb selekcji. Przypomnijmy, że ilość wybranych obiektów
zwraca funkcja glRenderMode w momencie powrotu do domyślnego trybu
renderowania, czyli już po zakończeniu pracy w trybie selekcji.
Informacje o obiektach wybranych w trakcie selekcji zawarte są w tzw.
rekordach trafień. Każdy rekord zawiera co najmniej cztery elementy (liczby
całkowite ułożone kolejno w buforze selekcji) i ma następującą budowę:
— [0] - ilość nazw na stosie nazw w momencie trafienia,
— [1] - minimalna wartość współrzędnych z prymitywów graficznych wcho-
dzących w skład wybranego obiektu; wartość ta jest pomnożona przez
2
32
− 1 i zaokrąglone do najbliższej liczby całkowitej,
— [2] - maksymalna wartość współrzędnych z prymitywów graficznych wcho-
dzących w skład wybranego obiektu; wartość ta jest pomnożona przez
2
32
− 1 i zaokrąglone do najbliższej liczby całkowitej,
1. Selekcja obiektów
3
— [3] - najniższy element stosu nazw obiektów (pierwszy odłożony na stos),
..
.
— [n] - najwyższy element stosu nazw obiektów (ostatni odłożony na stos),
Bezpośrednio po ostatnim elemencie pierwszego rekordu trafień znajduje
się drugi, a po nim kolejne rekordy.
1.4. Program przykładowy
W programie przykładowym (plikselekcja obiektow.cpp) tworzymy
cztery obiekty. Trzy z nich to sześciany, które należą do grupy CUBE. Każdy
z sześcianów posiada swój własny identyfikator o nazwie odpowiadającej ko-
lorowi (RED CUBE, GREEN CUBE i BLUE CUBE). Czwartym obiektem jest kula
identyfikowana stałą o nazwie SPHERE.
Typowym przypadku, który został także zaimplementowany w prezen-
towanym programie, selekcję obiektów wykonuje się na podstawie położenia
wskaźnika myszki, w chwili, gdy przycisk myszki został przyciśnięty. Aby
uzyskać pożądany efekt trzeba ograniczyć bryłę odcinania tak aby obej-
mowała „najbliższą okolicę” punktu, w którym został przyciśnięty przycisk
myszki. Najłatwiej jest to uzyskać korzystając z funkcji biblioteki GLU:
void gluPickMatrix (GLdouble x, GLdouble y,
GLdouble deltax, GLdouble deltay,
const GLint viewport[4])
Parametry x i y określają współrzędne środka nowej bryły odcinania
(oczywiście we współrzędnych okienkowych). Kolejne parametry deltax
i deltay określają szerokość i wysokość bryły odcinania w pikselach. Ostat-
ni parametr viewport zawiera dane o rozmiarach bieżącego obszaru ren-
deringu. Dane te najłatwiej jest pobrać wywołując funkcję glGetIntegerv
z parametrem GL VIEWPORT.
Jak ciekawostkę można podać w jaki sposób zaimplementowana została
funkcja gluPickMatrix w bibliotece GLU autorstwa firmy SGI:
glTranslatef ((viewport[2]-2*(x-viewport[0]))/deltax,
(viewport[3]-2*(y-viewport[1]))/deltay,0);
glScalef (viewport[2]/deltax,viewport[3]/deltay,1.0);
Zanim jednak, korzystając z funkcji gluPickMatrix, zmodyfikujemy bry-
łę odcinania trzeba odłożyć oryginalną macierz modelowania na stos. Po
zmodyfikowaniu bryły odcinania wykonujemy wszystkie etapy normalnego
renderingu sceny, włączając w to przekształcenia macierzy modelowania,
przy czym samo renderowanie sceny wykonywane jest już po włączeniu try-
bu selekcji. Po zakończeniu renderingu w trybie selekcji i ustaleniu ilości
rekordów trafień trzeba dokonać analizy zawartości bufora selekcji.
1. Selekcja obiektów
4
Analiza bufora selekcji jest ściśle związana z ilością i układem hierarchii
obiektów rysowanych na scenie. W przykładowym programie obiekty są tak
zdefiniowane i ułożone, że w buforze selekcji mogą znaleźć się maksymalnie
dwa rekordy trafień, stąd ich analiza jest stosunkowo prosta. Przyśpieszenie
analizy ułatwia hierarchia obiektów sceny. Przykładowo wiedząc, że w pierw-
szym rekordzie trafień znajduje się kula, mamy pewność, że drugi rekord
może zawierać wyłącznie sześcian.
Efekt działania przykładowego programu przedstawiają rysunki 1 i 2.
W obu przypadkach komunikaty na dole okna pokazują ilość rekordów tra-
fień oraz obiekt, który w miejscu trafienia znajdował się najbliżej położenia
obserwatora.
Rysunek 1. Program Selekcja obiektów - wybrane dwa trafienia
1. Selekcja obiektów
5
Rysunek 2. Program Selekcja obiektów - wybrane jedno trafienie
1.4.1. Plik selekcja obiektow.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>
#i n c l u d e < s t d i o . h>
#i n c l u d e < s t r i n g . h>
#i n c l u d e
” c o l o r s . 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 ;
1. Selekcja obiektów
6
//
r o z m i a r y
b r y ł y
o b c i n a n i a
const GLdouble
l e f t = − 2 . 0 ;
const GLdouble
r i g h t = 2 . 0 ;
const GLdouble bottom = − 2 . 0 ;
const GLdouble
t o p = 2 . 0 ;
const GLdouble
n e a r = 3 . 0 ;
const GLdouble
f a r = 7 . 0 ;
//
k ą t y
o b r o t u
G L f l o a t
r o t a t e x = 0 . 0 ;
G L f l o a t
r o t a t e y = 0 . 0 ;
//
w s k a ź n i k
n a c i ś n i ę c i a
l e w e g o
p r z y c i s k u
m y s z k i
i n t
b u t t o n s t a t e = GLUT UP ;
//
p o ł o ż e n i e
k u r s o r a
m y s z k i
i n t
b u t t o n x , b u t t o n y ;
//
w s p ó ł c z y n n i k
s k a l o w a n i a
G L f l o a t
s c a l e = 1 . 0 ;
//
i d e n t y f i k a t o r y
w y ś w i e t l a n y c h
o b i e k t ó w
enum
{
NONE,
CUBE,
RED CUBE,
GREEN CUBE,
BLUE CUBE,
SPHERE
} ;
//
n a zw a
w y b r a n e g o
o b i e k t u
char
s e l e c t o b j e c t
[ 3 0 ] = ” T r a f i e n i a :
0 ” ;
//
f u n k c j a
r y s u j ą c a
n a p i s w wybranym
m i e j s c u
void
D r a w S t r i n g
( G L f l o a t
x ,
G L f l o a t
y ,
char ∗ s t r i n g )
{
//
p o ł o ż e n i e
n a p i s u
g l R a s t e r P o s 2 f
( x , y ) ;
//
w y ś w i e t l e n i e
n a p i s u
i n t
l e n = s t r l e n
( s t r i n g ) ;
f o r
( i n t
i = 0 ;
i < l e n ;
i ++)
g l u t B i t m a p C h a r a c t e r
( GLUT BITMAP 9 BY 15 , s t r i n g
[ i ] ) ;
}
//
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
i
b u f o r a
g ł ę b o k o ś c i
g l C l e a r
( GL COLOR BUFFER BIT | GL DEPTH 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
u k ł a d u
w s p ó ł r z ę d n y c h
o b i e k t u
do
ś r o d k a
b r y ł y
o d c i n a n i a
g l T r a n s l a t e f
( 0 , 0 , − ( n e a r+f a r ) / 2 ) ;
//
o b r o t y
o b i e k t u
g l R o t a t e f
( r o t a t e x , 1 . 0 , 0 . 0 , 0 . 0 ) ;
g l R o t a t e f
( r o t a t e y , 0 . 0 , 1 . 0 , 0 . 0 ) ;
//
s k a l o w a n i e
o b i e k t u − k l a w i s z e
”+”
i
”−”
1. Selekcja obiektów
7
g l S c a l e f
( s c a l e , s c a l e , s c a l e ) ;
//
w ł ą c z e n i e
t e s t u
b u f o r a
g ł ę b o k o ś c i
g l E n a b l e
(GL DEPTH TEST ) ;
//
w ł ą c z e n i e
o ś w i e t l e n i a
g l E n a b l e
( GL LIGHTING ) ;
//
w ł ą c z e n i e
ś w i a t ł a
GL LIGHT0 z
p a r a m e t r a m i
d o m y ś l n y m i
g l E n a b l e
( GL LIGHT0 ) ;
//
w ł ą c z e n i e
a u t o m a t y c z n e j
n o r m a l i z a c j i
w e k t o r ó w
n o r m a l n y c h
g l E n a b l e
(GL NORMALIZE ) ;
//
w ł ą c z e n i e
o b s ł u g i
w ł a ś c i w o ś c i
m a t e r i a ł ó w
g l E n a b l e
(GL COLOR MATERIAL ) ;
//
i n i c j a l i z a c j a
s t o s u
nazw
o b i e k t ó w
g l I n i t N a m e s
( ) ;
//
u m i e s z c z e n i e
n a z w y
na
s t o s i e
nazw ,
a b y
n i e
b y ł
on
p u s t y
glPushName
(NONE ) ;
//
o b i e k t RED CUBE z
g r u p y CUBE
glLoadName
(CUBE ) ;
glPushName
(RED CUBE ) ;
g l C o l o r 4 f v
( Red ) ;
g l T r a n s l a t e f
( 0 . 0 , 1 . 0 , 0 . 0 ) ;
g l u t S o l i d C u b e
( 0 . 5 ) ;
glPopName
( ) ;
//
o b i e k t GREEN CUBE z
g r u p y CUBE
glPushName
(GREEN CUBE ) ;
g l C o l o r 4 f v
( Green ) ;
g l T r a n s l a t e f
( 1 . 0 , − 1 . 0 , 0 . 0 ) ;
g l u t S o l i d C u b e
( 0 . 5 ) ;
glPopName
( ) ;
//
o b i e k t
BLUE CUBE z
g r u p y CUBE
glPushName
(BLUE CUBE ) ;
g l C o l o r 4 f v
( B l u e ) ;
g l T r a n s l a t e f
( − 1 . 0 , − 1 . 0 , 0 . 0 ) ;
g l u t S o l i d C u b e
( 0 . 5 ) ;
glPopName
( ) ;
//
o b i e k t SPHERE ,
n i e
n a l e ż ą c y
do
g r u p y CUBE
glLoadName
(SPHERE ) ;
g l C o l o r 4 f v
( Orange ) ;
g l T r a n s l a t e f
( − 1 . 0 , 1 . 0 , 0 . 0 ) ;
g l u t S o l i d S p h e r e
( 0 . 4 , 2 0 , 2 0 ) ;
//
w y ł ą c z e n i e
o ś w i e t l e n i a
g l D i s a b l e
( GL LIGHTING ) ;
//
w y ł ą c z e n i e
t e s t u
b u f o r a
g ł ę b o k o ś c i
g l D i s a b l e
(GL DEPTH TEST ) ;
//
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 ) ;
//
t r z e b a
o d p o w i e d n i o
p r z e k s z t a ł c i ć
u k ł a d
w s p ó ł r z ę d n y c h
//
a b y
n a p i s
z n a j d o w a ł
s i ę
na
s a m e j
” g ó r z e ”
b r y ł y
o b c i n a n i a
g l L o a d I d e n t i t y
( ) ;
g l T r a n s l a t e f
( 0 , 0 , − n e a r ) ;
//
n a r y s o w a n i e
n a p i s u
o wybranym
o b i e k c i e
g l C o l o r 4 f v
( B l a c k ) ;
D r a w S t r i n g
( l e f t + 0 . 0 2 , bottom + 0 . 0 3 , s e l e c t o b j e c t ) ;
//
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 )
{
1. Selekcja obiektów
8
//
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
( l e f t , r i g h t , bottom ∗ h e i g h t / width , t o p ∗ h e i g h t / width , n e a r , f a r ) ;
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
( l e f t ∗ w i d t h / h e i g h t , r i g h t ∗ w i d t h / h e i g h t , bottom , top , n e a r , f a r ) ;
}
e l s e
g l F r u s t u m
( l e f t , r i g h t , bottom , top , n e a r , f a r ) ;
//
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
s e l e k c j i
o b i e t k ó w
void
S e l e c t i o n
( i n t x ,
i n t
y )
{
//
w i e l k o ś ć
b u f o r a
s e l e k c j i
const
i n t BUFFER LENGTH = 6 4 ;
//
b u f o r
s e l e k c j i
GLuint
s e l e c t b u f f e r
[ BUFFER LENGTH ] ;
//
p r z y g o t o w a n i e
b u f o r a
s e l e k c j i
g l S e l e c t B u f f e r
(BUFFER LENGTH, s e l e c t b u f f e r ) ;
//
p o b r a n i e
o b s z a r u
r o z m i a r u
r e n d e r i n g u
i n t
v i e w p o r t [ 4 ] ;
g l G e t I n t e g e r v
(GL VIEWPORT, v i e w p o r t ) ;
//
s z e r o k o ś ć
i
w y s o k o ś ć
o b s z a r u
r e n d e r i n g u
i n t
w i d t h = v i e w p o r t
[ 2 ] ;
i n t
h e i g h t = v i e w p o r t
[ 3 ] ;
//
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 ) ;
//
o d ł o ż e n i e
m a c i e r z y
r z u t o w a n i a
na
s t o s
g l P u s h M a t r i x
( ) ;
//
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 − j e d n o s t k o w a
k o s t k a
d o o k o ł a
p u n k t u
w s k a ź n i k a
//
m y s z y
( x , y )
r o z c i ą g a j ą c e j
s i ę
na dwa
p i k s e l e
w p o z i o m i e
i
w
p i o n i e
g l u P i c k M a t r i x
( x , h e i g h t −y , 2 , 2 , v i e w p o r t ) ;
//
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
( l e f t , r i g h t , bottom ∗ h e i g h t / width , t o p ∗ h e i g h t / width , n e a r , f a r ) ;
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
( l e f t ∗ w i d t h / h e i g h t , r i g h t ∗ w i d t h / h e i g h t , bottom , top , n e a r , f a r ) ;
}
e l s e
g l F r u s t u m
( l e f t , r i g h t , bottom , top , n e a r , f a r ) ;
//
w ł ą c z e n i e
t r y b u
s e l e k c j i
glRenderMode
( GL SELECT ) ;
1. Selekcja obiektów
9
//
g e n e r o w a n i e
s c e n y
3D
D i s p l a y
( ) ;
//
z l i c z e n i e
i l o ś c i
r e k o r d ó w
t r a f i e ń ,
p o w r ó t
do
d o m y ś l n e g o
t r y b u
r e n d e r i n g u
GLint
h i t s = glRenderMode
(GL RENDER ) ;
//
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 ) ;
//
z d j ę c i e
m a c i e r z y
r z u t o w a n i a
z e
s t o s u
g l P o p M a t r i x
( ) ;
// w w y n i k u
s l e k c j i
n i e
w y b r a n o
ż a d n e g o
o b i e k t u
i f
( h i t s == 0 )
s t r c p y
( s e l e c t o b j e c t , ” T r a f i e n i a :
0 ” ) ;
// w w y n i k u
s e l e k c j i
w y b r a n o
j e d e n
o b i e k t
i f
( h i t s == 1 )
{
//
p o j e d y n c z a
n a zw a
na
s t o s i e − k u l a
//
s p r a w d z e n i e
d r u g i e g o
w a r u n k u
n i e
j e s t
k o n i e c z n e
i f
( s e l e c t b u f f e r
[ 0 ] == 1 && s e l e c t b u f f e r
[ 3 ] == SPHERE)
{
s t r c p y
( s e l e c t o b j e c t , ” T r a f i e n i a :
1 ,
o b i e k t : SPHERE” ) ;
}
e l s e
//
d w i e
n a z w y
na
s t o s i e − j e d e n
z
t r z e c h
s z e ś c i a n ó w
//
s p r a w d z e n i e
d r u g i e g o
w a r u n k u
n i e
j e s t
k o n i e c z n e
i f
( s e l e c t b u f f e r
[ 0 ] == 2 && s e l e c t b u f f e r
[ 3 ] == CUBE)
//
s p r a w d z e n i e
w i e r z c h o ł k a
s t o s u
nazw
switch
( s e l e c t b u f f e r
[ 4 ] )
{
//
c z e r w o n y
s z e ś c a n
c a s e RED CUBE :
s t r c p y
( s e l e c t o b j e c t , ” T r a f i e n i a :
1 ,
o b i e k t : RED CUBE” ) ;
break ;
//
z i e l o n y
s z e ś c a n
c a s e GREEN CUBE :
s t r c p y
( s e l e c t o b j e c t , ” T r a f i e n i a :
1 ,
o b i e k t : GREEN CUBE” ) ;
break ;
//
n i e b i e s k i
s z e ś c a n
c a s e BLUE CUBE :
s t r c p y
( s e l e c t o b j e c t , ” T r a f i e n i a :
1 ,
o b i e k t : BLUE CUBE” ) ;
break ;
}
}
// w w y n i k u
s e l e k c j i
w y b r a n o
dwa
o b i e k t y
i f
( h i t s == 2 )
{
//
p i e r w s z y
o b i e k t − s z e ś c i a n ,
d r u g i
o b i e k t
k u l a
i f
( s e l e c t b u f f e r
[ 0 ] == 2 && s e l e c t b u f f e r
[ 8 ] == SPHERE)
{
//
s p r a w d z e n i e ,
k t ó r y
z
o b i e k t ó w
j e s t
b l i ż e j
o b s e r w a t o r a
i f
( s e l e c t b u f f e r
[ 2 ] > s e l e c t b u f f e r
[ 7 ] )
s t r c p y
( s e l e c t o b j e c t , ” T r a f i e n i a :
2 ,
p i e r w s z y
o b i e k t : SPHERE” ) ;
e l s e
//
s p r a w d z e n i e ,
k t ó r y
s z e ś c i a n
j e s t
b l i ż e j
o b s e r w a t o r a
switch
( s e l e c t b u f f e r
[ 4 ] )
{
//
c z e r w o n y
s z e ś c a n
c a s e RED CUBE :
s t r c p y
( s e l e c t o b j e c t , ” T r a f i e n i a :
2 ,
p i e r w s z y
o b i e k t : RED CUBE” ) ;
break ;
//
z i e l o n y
s z e ś c a n
c a s e GREEN CUBE :
s t r c p y
( s e l e c t o b j e c t , ” T r a f i e n i a :
2 ,
p i e r w s z y
o b i e k t : GREEN CUBE” ) ;
break ;
//
n i e b i e s k i
s z e ś c a n
c a s e BLUE CUBE :
s t r c p y
( s e l e c t o b j e c t , ” T r a f i e n i a :
2 ,
p i e r w s z y
o b i e k t : BLUE CUBE” ) ;
break ;
}
}
e l s e
1. Selekcja obiektów
10
//
p i e r w s z y
o b i e k t − s z e ś c i a n ,
d r u g i
o b i e k t
t a k ż e
s z e ś c i a n
//
z
u w a g i
na
k o l e j n o ś ć
d e f i n i o w a n i a
o b i e k t ó w
p r z y p a d e k ,
//
g d y
p i e r w s z y m
o b i e k t e m
j e s t
k u l a
a
d r u g i m
s z e ś c i a n
n i e
w y s t ą p i
i f
( s e l e c t b u f f e r
[ 0 ] == 2 && s e l e c t b u f f e r
[ 8 ] == CUBE)
{
//
s p r a w d z e n i e ,
k t ó r y
z
s z e ś c i a n ó w
j e s t
b l i ż e j
o b s e r w a t o r a
i f
( s e l e c t b u f f e r
[ 2 ] > s e l e c t b u f f e r
[ 7 ] )
//
d r u g i
s z e ś c i a n
j e s t
b l i ż e j
switch
( s e l e c t b u f f e r
[ 9 ] )
{
//
c z e r w o n y
s z e ś c a n
c a s e RED CUBE :
s t r c p y
( s e l e c t o b j e c t , ” T r a f i e n i a :
2 ,
p i e r w s z y
o b i e k t : RED CUBE” ) ;
break ;
//
z i e l o n y
s z e ś c a n
c a s e GREEN CUBE :
s t r c p y
( s e l e c t o b j e c t , ” T r a f i e n i a :
2 ,
p i e r w s z y
o b i e k t : GREEN CUBE” ) ;
break ;
//
n i e b i e s k i
s z e ś c a n
c a s e BLUE CUBE :
s t r c p y
( s e l e c t o b j e c t , ” T r a f i e n i a :
2 ,
p i e r w s z y
o b i e k t : BLUE CUBE” ) ;
break ;
}
e l s e
//
p i e r w s z y
s z e ś c i a n
j e s t
b l i ż e j
switch
( s e l e c t b u f f e r
[ 4 ] )
{
//
c z e r w o n y
s z e ś c a n
c a s e RED CUBE :
s t r c p y
( s e l e c t o b j e c t , ” T r a f i e n i a :
2 ,
p i e r w s z y
o b i e k t : RED CUBE” ) ;
break ;
//
z i e l o n y
s z e ś c a n
c a s e GREEN CUBE :
s t r c p y
( s e l e c t o b j e c t , ” T r a f i e n i a :
2 ,
p i e r w s z y
o b i e k t : GREEN CUBE” ) ;
break ;
//
n i e b i e s k i
s z e ś c a n
c a s e BLUE CUBE :
s t r c p y
( s e l e c t o b j e c t , ” T r a f i e n i a :
2 ,
p i e r w s z y
o b i e k t : BLUE CUBE” ) ;
break ;
}
}
}
}
//
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 == ’+ ’ )
s c a l e += 0 . 0 5 ;
e l s e
//
k l a w i s z −
i f
( k e y == ’− ’ && s c a l e > 0 . 0 5 )
s c a l e −= 0 . 0 5 ;
//
n a r y s o w a n i e
s c e n y
D i s p l a y
( ) ;
}
//
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 :
r o t a t e y −= 1 ;
break ;
//
k u r s o r w g ó r ę
c a s e GLUT KEY UP :
1. Selekcja obiektów
11
r o t a t e x −= 1 ;
break ;
//
k u r s o r w p r a w o
c a s e GLUT KEY RIGHT :
r o t a t e y += 1 ;
break ;
//
k u r s o r w d ó ł
c a s e GLUT KEY DOWN :
r o t a t e x += 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
p r z y c i s k ó w
m y s z k i
void MouseButton
( i n t
b u t t o n ,
i n t
s t a t e ,
i n t x ,
i n t
y )
{
i f
( b u t t o n == GLUT LEFT BUTTON)
{
//
o b s ł u g a
s e l e k c j i
o b i e k t ó w
S e l e c t i o n
( x , y ) ;
g l u t P o s t R e d i s p l a y
( ) ;
//
z a p a m i ę t a n i e
s t a n u
l e w e g o
p r z y c i s k u
m y s z k i
b u t t o n s t a t e = s t a t e ;
//
z a p a m i ę t a n i e
p o ł o ż e n i a
k u r s o r a
m y s z k i
i f
( s t a t e == GLUT DOWN)
{
b u t t o n x = x ;
b u t t o n y = y ;
}
}
}
//
o b s ł u g a
r u c h u
k u r s o r a
m y s z k i
void MouseMotion
( i n t x ,
i n t
y )
{
i f
( b u t t o n s t a t e == GLUT DOWN)
{
r o t a t e y += 30
∗ ( r i g h t − l e f t ) / g l u t G e t
(GLUT WINDOW WIDTH)
∗ ( x − b u t t o n x ) ;
b u t t o n x = x ;
r o t a t e x −= 30
∗ ( t o p − bottom ) / g l u t G e t
(GLUT WINDOW HEIGHT)
∗ ( b u t t o n y − y ) ;
b u t t o n y = y ;
g l u t P o s t R e d i s p l a y
( ) ;
//
o b s ł u g a
s e l e k c j i
o b i e k t ó w
S e l e c t i o n
( x , 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 ) ;
}
}
1. Selekcja obiektów
12
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 | GLUT DEPTH ) ;
//
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
( 5 0 0 , 5 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 e l e k c j a
o b i e k t ó w ” ) ;
#e l s e
g l u t C r e a t e W i n d o w
( ” S e l e k c j a
o b i e k t o w ” ) ;
#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 ) ;
//
o b s ł u g a
p r z y c i s k ó w
m y s z k i
g l u t M o u s e F u n c
( MouseButton ) ;
//
o b s ł u g a
r u c h u
k u r s o r a
m y s z k i
g l u t M o t i o n F u n c
( MouseMotion ) ;
//
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 ) ;
//
u t w o r z e n i e
podmenu − a s p e k t
o b r a z u
i n t
MenuAspect = g l u t C r e a t e M e n u
( Menu ) ;
#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 ) ;
#e l s e
glutAddMenuEntry
( ” A s p e k t
o b r a z u − c a l e
okno ” ,FULL WINDOW ) ;
#e n d i f
glutAddMenuEntry
( ” A s p e k t
o b r a z u
1 : 1 ” , ASPECT 1 1 ) ;
// menu g ł ó w n e
g l u t C r e a t e M e n u
( Menu ) ;
glutAddSubMenu
( ” A s p e k t
o b r a z u ” , MenuAspect ) ;
#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 ;
}
Literatura
13
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,
[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
[9] Mark J. Kilgard: All About OpenGL Extensions,
resources/features/OGLextensions/
[10] Jon Leech: How to Create OpenGL Extensions,
projects/ogl-sample/registry/doc/rules.html
[11] Silicon Graphics, Inc: OpenGL
R
Extension Registry,