Z pogranicza

Kurs programowania GLUT

Kurs programowania w GLUT
Neuro 2004
Spis treści

     1 PRZEDMOWA
     2 WSTĘP
          2.1 Przegląd Funkcji
     3 START
          3.1 KOMPILACJA
               3.1.1 KOMPILACJA OS/2
               3.1.2 KOMPILACJA WINDOWS
          3.2 PIERWSZY PROGRAM
          3.3 INTERAKCJA
          3.4 OKNO
          3.5 WYŚWIETLANIE
          3.6 MENU
          3.7 TIMER
          3.8 MODELE
          3.9 PISANIE
          3.10 TRYB GRY
          3.11 INFORMACJE
          3.12 MAPY KOLORÓW
          3.13 WARSTWY
          3.14 VIDEO
          3.15 DODATKI

PRZEDMOWA


Art. Będzie miał sporo braków i wiele niedomówień, bo zamierzam pisać go tak jak to robiono na NeHe (polecam, ostatnio nawet powstaje polskie tłumaczenie). Będę opierał się na plikach nagłówkowych i dokumentacji. Części funkcji niestety nie przetestuje bo po prostu nie jest to możliwe na sprzęcie który posiadam. No to do dzieła...

WSTĘP


GLUT (ang. OpenGL Utility Toolkit) to API (interfejs programowania aplikacji) dla OpenGL (biblioteka graficzna, jak by ktoś nie wiedział ;) ). Ostatnia wersja to zdaje się 3.7 (wyszła gdzieś koło 98 roku, więc to niezły staroć, ale na szczęście projekt rozwijany jest pod innymi nazwami m.in. freeglut). Glut jest zaimplementowany na kilka platform sprzętowych (Windows,Linux,MacOS), i powstały pliki nagłówkowe dla C, Delphi, Ady i Fortrana (zwykle załączane tylko do C, ale pozostałe można znależć w Internecie). Jego zaletą jest przenośność tzn. np. program napisany na Linux'ie może bez większych przeróbek zostać skompilowany pod Windows, i łatwość obsługi - krótkie logicznie zbudowane funkcje.
GLUT służy do utworzenia okna, prostego GUI (graficzny interfejs użytkownika) i interakcji z użytkownikiem (mycha, klawiatura, joystick). Dzięki użyciu GLUT'a unikamy używania API przystosoanego do danego systemu operacyjnego (Windows - WGL z WinAPi, OWL, Linux - GLX z XWindow, GTK, QT).

Przegląd Funkcji


UWAGA ! Poniższa lista dotyczy freeglut i posiada pewne niezgodności z GLUT.
  1. Initialization Functions (Inicjalizajca)
    1. glutInit
    2. glutInitWindowPosition, glutInitWindowSize
    3. glutInitDisplayMode
    4. glutInitDisplayString
  2. Event Processing Functions (Zdarzenia)

    1. glutMainLoop
    2. glutMainLoopEvent
    3. glutLeaveMainLoop
  3. Window Functions (Funkcje dotyczące okien)

    1. glutCreateWindow
    2. glutCreateSubwindow
    3. glutDestroyWindow
    4. glutSetWindow, glutGetWindow
    5. glutSetWindowTitle, glutSetIconTitlew
    6. glutReshapeWindow
    7. glutPositionWindow
    8. glutShowWindow, glutHideWindow, glutIconifyWindow
    9. glutPushWindow, glutPopWindow
    10. glutFullScreen
  4. Display Functions (Wyświetlanie)

    1. glutPostRedisplay
    2. glutPostWindowRedisplay
    3. glutSwapBuffers
  5. Mouse Cursor Functions (Kursor myszy)

    1. glutSetCursor
    2. glutWarpPointer
  6. Overlay Functions (Warstwy)

    1. glutEstablishOverlay
    2. glutRemoveOverlay
    3. glutUseLayer
    4. glutPostOverlayRedisplay
    5. glutPostWindowOverlayRedisplay
    6. glutShowOverlay, glutHideOverlay
  7. Menu Functions (Menu)

    1. glutCreateMenu
    2. glutDestroyMenu
    3. glutGetMenu, glutSetMenu
    4. glutAddMenuEntry
    5. glutAddSubMenu
    6. glutChangeToMenuEntry
    7. glutChangeToSubMenu
    8. glutRemoveMenuItem
    9. glutAttachMenu, glutDetachMenu
  8. Global Callback Registration Functions (Globalne funkcje typu zwrotnego)

    1. glutTimerFunc
    2. glutIdleFunc
  9. Window-Specific Callback Registration Functions (Ustalane dla okna funkcje typu zwrotnego)

    1. glutDisplayFunc
    2. glutOverlayDisplayFunc
    3. glutReshapeFunc
    4. glutKeyboardFunc
    5. glutSpecialFunc
    6. glutKeyboardUpFunc
    7. glutSpecialUpFunc
    8. glutMotionFunc, glutPassiveMotionFunc
    9. glutVisibilityFunc
    10. glutEntryFunc
    11. glutJoystickFunc
    12. glutSpaceballMotionFunc
    13. glutSpaceballRotateFunc
    14. glutSpaceballButtonFunc
    15. glutButtonBoxFunc
    16. glutDialsFunc
    17. glutTabletMotionFunc
    18. glutTabletButtonFunc
    19. glutMenuStatusFunc
    20. glutWindowStatusFunc
  10. State Setting and Retrieval Functions (Pobranie stanu okna)

    1. glutSetOption
    2. glutGet
    3. glutDeviceGet
    4. glutGetModifiers
    5. glutLayerGet
    6. glutExtensionSupported
    7. glutGetProcAddress
  11. Font Rendering Functions (Wyświetlanie czcionek)

    1. glutBitmapCharacter
    2. glutBitmapString
    3. glutBitmapWidth
    4. glutBitmapLength
    5. glutBitmapHeight
    6. glutStrokeCharacter
    7. glutStrokeString
    8. glutStrokeWidth
    9. glutStrokeLength
    10. glutStrokeHeight
  12. Geometric Object Rendering Functions (Obiekty geometryczne)

    1. glutWireSphere, glutSolidSphere
    2. glutWireTorus, glutSolidTorus
    3. glutWireCone, glutSolidCone
    4. glutWireCube, glutSolidCube
    5. glutWireTetrahedron, glutSolidTetrahedron
    6. glutWireOctahedron, glutSolidOctahedron
    7. glutWireDodecahedron, glutSolidDodecahedron
    8. glutWireIcosahedron, glutSolidIcosahedron
    9. glutWireRhombicDodecahedron, glutSolidRhombicDodecahedron
    10. glutWireTeapot, glutSolidTeapot
  13. Game Mode Functions (Tryb gry)

    1. glutGameModeString
    2. glutEnterGameMode, glutLeaveGameMode
    3. glutGameModeGet
  14. Video Resize Functions (Zmiana Video)

    1. glutVideoResizeGet
    2. glutSetupVideoResizing, glutStopVideoResizing
    3. glutVideoResize
    4. glutVideoPan
  15. Color Map Functions (Mapy kolorów)

    1. glutSetColor, glutGetColor
    2. glutCopyColormap
  16. Miscellaneous Functions (Pozostałe)

    1. glutIgnoreKeyRepeat, glutSetKeyRepeat
    2. glutForceJoystickFunc
    3. glutReportErrors

START


Dobra, zaczynamy. Ja będę pisał pod Linux'a (Mandrake 9.2) i kompilował przy użyciu gcc (więc jak się można było domyślić będę używał C). Co jest wymagane? Znajomość C i OpenGL ofcourse. Jeśli idzie o soft to: jakiś Linux z gcc, OpenGL i GLUT, albo Windows + odpowiedni kompilator + biblioteki. Potem może napiszę uzupełnienie na Windows, ale jeszcze zobaczę.
UWAGA ! W niektórych dystrybucjach Linux'a GLUT nie jest standardowo instalowany (u mnie trzeba było wybrać samodzielnie pakiety, przełączyć widok na listę i dopiero znaleĽć coś w stylu libMESA-GLUT (z "devel" to pliki nagłówkowe) czy coć takiego [MESA - to taka wersja OpenGL]).
Powinieneś obsługiwać jako tako Linux'a więc:
xterm, aterm, gnome-terminal, kterm - terminale (tu się pisze komendy):
cd - polecenie zmień katalog (.. aby przejsc do gory, / aby przejsc na szczyt drzewa)
np.
cd /root/glut - przechodzi do katalogu /root/glut
mc - najlepszy tekstowy menedżer plików
kwrite, gedit itp. - edytory textu (w tym będziemy pisać)

KOMPILACJA


Do kompilacji będzie nam potrzebny plik "makefile" (oczywiście bez cudzysłowiu). Nie znam się na tworzeniu makefile więc po prostu otwórz jakiś edytor i wpisz (skopiuj):

INCLUDE = -I/usr/include/ LIBDIR = -L/usr/X11R6/lib
COMPILERFLAGS = -Wall CC = gcc CFLAGS = $(COMPILERFLAGS) $(INCLUDE) LIBRARIES = -lX11 -lXi -lXmu -lglut -lGL -lGLU -lm
# for all, set the targets to be every lesson1.c-lesson13.c # file, removing the .c extension. That is, at this point, # it would produce lesson1, lesson2, lesson3,...,lesson13 targets. # all: $(basename $(wildcard lesson[1-9].c lesson1[0-3].c))
# same as for all, except set the targets to be # lessonX.tar.gz from lessonX.c. This is really # only used to build smaller tutorial .tar.gz files # to send to nehe. # dist: $(foreach file,$(basename $(wildcard lesson[1-9].c lesson1[0-3].c)),$(file).tar.gz)
# to produce, say, lesson1.tar.gz: # # 1. remove lesson1.tar.gz # 2. build lesson1.tar containing README, makefile, lesson1.c, Data/lesson1/*. # 3. gzip lesson1.tar. # lesson%.tar.gz : tar cvf $(subst .tar.gz,.tar,$@) README makefile $(subst .tar.gz,.c,$@) $(wildcard Data/$(subst .tar.gz,,$@)/*); \ gzip $(subst .tar.gz,.tar,$@);
# to produce, say, lesson1: # # 1. compile the thing. uses the variables defined above. # lesson% : lesson%.o $(CC) $(CFLAGS) -o $@ $(LIBDIR) $< $(LIBRARIES)
# to clean up: # delete all of the lessonX files. clean: rm $(wildcard lesson[1-9] lesson1[0-3])
# to clean up the distributions: # delete all of the lessonX.tar.gz files. distclean: rm $(wildcard lesson[1-9].tar.gz lesson1[0-3].tar.gz)

Pierwsze linijki określają katalog plików nagłówkowych i bibliotek (trzeba dodać glut, GLU, GL), dalej ustawienia kompilatora i co ma być wykonywane.

Ok. teraz zapisz to w jakimś katalogu (np. /_glut).

Dzięki temu plikowi ("makefile"), aby skompilować jakiś kod wystarczy, że zapiszemy go w tym samym katalogu (co zapisany został makefile), nazwiemy "lesson1.c" i po wpisaniu w terminalu (po przejściu do odpowiedniego katalogu poleceniem cd) "make" (ewentualnie z parametrem "makefile"), otrzymamy skompilowany plik wykonywalny, który możemy uruchomić poleceniem "./lesson1" lub klikając w jakiejś przeglądarce plików (np. nautilus, konqueror ew. mc).

KOMPILACJA OS/2


Zamieszczam metodę kompilacji pod zapomniany nieco system OS/2. Może się to komuś przyda... Nie testowałem bo go nie mam.
1. W programie dopisujemy standardowe nagłówki:
#include <GL/gl.h>
#include <GL/glut.h>

2. I kompilujemy z wiersza poleceń:
cc -fullwarn -O2 -s -o crisscross crisscross.c -lc -lglut -lGL -lGLU -lX11 -lXmu -lXi -lXext -lm
Gdzie:
  1. fullwarn- extra sprawdzanie
  2. O2- optymalizacja
  3. s - stripped of debug info
  4. c - biblioteka C
  5. glut- biblioteka I/O glut (zastąpić "-lglut" z "libglut.a" jeśli skopiowane lokalnie)
  6. GL - biblioteka OpenGL
  7. GLU - biblioteka OpenGL Utility
  8. X11, Xmu, Xext, Xi - biblioteka X window
  9. m - matematyka

KOMPILACJA WINDOWS


Aby korzystać z GLUT pod Windows najpierw należy ściagnąć odpowiednie biblioteki z Internetu. Wystarczy wpsiać w dowolnej wyszukiwarce "download GLUT" i wybrać pierwszą stronę z brzegu. Zwykle wszytsko jest w postaci pliku zip. Należy go wypakować, a następnie skopiować odpowiednie pliki. Na windows aby uruchomić program korzystający z GLUT należy załączać zawsze do programu bibliotekę GLUT32.dll. Jednak na swoje potrzeby wystarczy przekopiować dll'a do folderu systemowego (C:\Windows czy C:\Windows\System32). Plik glut32.lib należy przekopiować do folderu lib w katalogu z kompilatorem, a plik glut.h do folderu GL w include. I to tyle (dla Dev-Cpp i MSVC) Na Borlandzie sprawa wygląda inaczej - aby skompilować program należy dodać oczywiście GLUT do używanych bibliotek. Możemy to zrobić np. dopisując w kodzie programu wiersz:
#pragma comment(lib,"glut32.LIB")

PIERWSZY PROGRAM


//Cóż, nie jest to "Hello world !", ale coś bardzo zbliżonego ;)
#include <GL/glut.h>    // Header File For The GLUT Library
//#include <GL/gl.h>        // Header File For The OpenGL32 Library
//#include <GL/glu.h>        // Header File For The GLu32 Library
/* The number of our GLUT window */
int window;
/* A general OpenGL initialization function.  Sets all of the initial parameters. */
void InitGL(int Width, int Height)                // We call this right after our OpenGL window is created.
{
  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);                // This Will Clear The Background Color To Black
  glClearDepth(1.0);                                // Enables Clearing Of The Depth Buffer
  glDepthFunc(GL_LESS);                                // The Type Of Depth Test To Do
  glEnable(GL_DEPTH_TEST);                        // Enables Depth Testing
  glShadeModel(GL_SMOOTH);                        // Enables Smooth Color Shading
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();                                // Reset The Projection Matrix
 
  gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);        // Calculate The Aspect Ratio Of The Window
  glMatrixMode(GL_MODELVIEW);
}
 
 
/* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */
void ReSizeGLScene(int Width, int Height)
{
  if (Height==0)                                // Prevent A Divide By Zero If The Window Is Too Small
    Height=1;
 
  glViewport(0, 0, Width, Height);                // Reset The Current Viewport And Perspective Transformation
 
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
 
  gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);
  glMatrixMode(GL_MODELVIEW);
}
 
/* The main drawing function. */
void DrawGLScene()
{
glutSetWindow(window);                                        //Set active window
 
  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);        // Clear The Screen And The Depth Buffer
  glLoadIdentity();                                // Reset The View
  //OpenGL scene goes here///////////////////////////////////////
  //Tutaj wstawiamy kod rysujący scenę
  ///////////////////////////////////////////////////////////////
  // swap the buffers to display, since double buffering is used.
  glutSwapBuffers();
}
 
int main(int argc, char **argv)
{
  /* Initialize GLUT state - glut will take any command line arguments that pertain to it or
     X Windows - look at its documentation at http://reality.sgi.com/mjk/spec3/spec3.html */
  glutInit(&argc, argv);
 
  /* Select type of Display mode:
     Double buffer
     RGBA color
     Alpha components supported
     Depth buffered for automatic clipping */
  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
//W przypadku błędów po odpaleniu usunąć  GLUT_ALPHA | 
 
  /* get a 640 x 480 window */
  glutInitWindowSize(640, 480);
 
  /* the window starts at the upper left corner of the screen */
  glutInitWindowPosition(0, 0);
 
  /* Open a window */
  window = glutCreateWindow("GLUT TUTORIAL #1");
 
  /* Register the function to do all our OpenGL drawing. */
  glutDisplayFunc(&DrawGLScene);
 
  /* Go fullscreen.  This is as soon as possible. */
  glutFullScreen();
 
  /* Even if there are no events, redraw our gl scene. */
  glutIdleFunc(&DrawGLScene);
 
  /* Register the function called when our window is resized. */
  glutReshapeFunc(&ReSizeGLScene);
 
  /* Initialize our window. */
  InitGL(640, 480);
 
  /* Start Event Processing Engine */
  glutMainLoop();
 
  /* shut down our window */
  glutDestroyWindow(window);
 
  return 1;
}

Sporo tego prawda... Ale chwila popatrzmy:
#include <GL/glut.h>    // Header File For The GLUT Library
#include <GL/gl.h>        // Header File For The OpenGL32 Library
#include <GL/glu.h>        // Header File For The GLu32 Library

to tylko dołączenie plików nagłówkowych kolejno: GLUT, OpenGL, GL utilities (rozszerzenie OpenGL). Te dwa ostatnie nie są konieczne bo są już dołączone w nagłówkach GLUT.
Deklaracja "int window" potrzebna jest do zapamiętania numeru okna glut na którym potem będziemy wykonywać operacje. Procedury InitGL i ReSizeGLScene zawierają jedynie procedury, które należą do OpenGL i nie będę ich tutaj opisywał.
Wystarczy, że powiem, iż InitGL zawiera inicjalizację wyświetlania grafiki, a ReSizeGLScene zmianę perspektywy i obszaru rysowania po zmianie rozmiaru okna. Ich parametry to szerokość i wysokość okna.
Procedura DrawGLScene() służy do wyświetlania sceny. Jedyną nową procedurą jest glutSwapBuffers(); która służy do opróżnienia buffor'ów, czyli po ludzku do wyświetlenia sceny OpenGL w oknie GLUT'a.
OK. Teraz główna funkcja (main):
glutInit(&argc, argv); // inicjalizuje GLUT z parametrami podanymi dla programu (zaimplementowane są wszystkie parametry systemu XWindow [czytać w dokumentacji])
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH); //Ustala tryb wyświetlania GLUT, jako sumę logiczną podanych parametrów:
możliwe opcje:
GLUT_RGB                //Kolor RGB<
GLUT_RGBA                //Kolor RGBa
GLUT_INDEX                //Tryb indexowania
GLUT_SINGLE                //Pojedynczy buffer
GLUT_DOUBLE                //Podwójny<
GLUT_ACCUM                //?
GLUT_ALPHA                //Kolor alpha (przezroczystość)
GLUT_DEPTH                //Bufor automatycznego przycinania
GLUT_STENCIL                //Stencil buffer (czytaj w OpenGL)
GLUT_MULTISAMPLE        //?
GLUT_STEREO                //?
GLUT_LUMINANCE                //?
glutInitWindowSize(640, 480); //Ustawia rozmiar okna na 640x480

glutInitWindowPosition(0, 0); //Ustawia pozycję okna na 0x0 (lewy górny róg)

window = glutCreateWindow("GLUT TUTORIAL");        //Tworzy okno z tytułem "GLUT TUTORIAL" i zwraca jego numer do zmiennej window
glutDisplayFunc(&DrawGLScene);                        //Ustala funkcję wyświetlania - podajemy adres do dowolnej funkcji, tutaj mamy wswskaĽniko DrawGLScene UWAGA ! Funkcja przypisuje wyświetlanie okna aktywnego (tutaj: to które zostało utworzone ostatnio)

glutFullScreen();                                //Ustala tryb pełnoekranowy - można spokojne wyłączyć

glutIdleFunc(&DrawGLScene);                        //Gdy nic się nie dzieje to uruchamia funkcję podaną w parametrze, tutaj znowu mamy DrawGLScene - (dzięki temu można przesuwać, zmieniać rozmiar itd. okna).

glutReshapeFunc(&ReSizeGLScene);                //Ustala funkcję zmiany rozmiaru okna, która powinna mieć dwa parametry typu int do których zostaną przekazane szerokość i wysokość okna  - tutaj podaliśmy funkcję ReSizeGLScene

Dalej mamy wywołanie funkcji InitGL(); której działanie opisałem wyżej.

I przedostatnia nowa funkcja:
glutMainLoop(); //Główna pętla programu, wyświetla i obsługuje okno oraz odpowiada za interakcję z użytkownikiem.

Funkcja:
glutDestroyWindow(window);
niszczy okno GLUT, którego numer podajemy w parametrze (coś jak uchwyt w WinApi).

Nooo. Jakoś przeszło.

INTERAKCJA


OK. Teraz zajmiemy się komunikacją z użytkownikiem:

glutKeyboardFunc(&keyPressed); //Ustala jaka funkcję zostanie wywołana po wciśnięciu klawisza (tutaj keyPressed). Jej parametry to jedna zmienna typu unsigned char, która zawiera klawisz jaki został wciśnięty oraz dwa parametry typu int które zawierają współrzędne myszki po wciąnięiciu klawisza. Przykładowa funkcja:

void keyPressed(unsigned char key, int x, int y)
{
 
    /* If 'x' is pressed, kill everything. */
    if (key == 'x')
    {
      /* shut down our window */
      glutDestroyWindow(window);
 
      /* exit the program...normal termination. */
      exit(0);
    }
}


Analogiczną do powyższej jest funkcja:

glutKeyboardUpFunc(&keyUp);

Różni się ona od tamtej tylko tym, że wywołuje funkcję daną w parametrze dopiero po puszczeniu klawisza

Kolejną podobną funkcją jest:

glutSpecialUpFunc(&specialKeyUp);

której parametr zostanie wywołany po puszczeniu klawisza specjalnego. Parametry identyczne jak wyżej za wyjątkiem pierwszego, który jest typu int.

I dalej:

glutSpecialFunc(&specialKeyPressed); //analogicznie jak w glutKeyboardFunc, z poprawką na pierwszy parametr ;) .

UWAGA ! Niektóre omawiane funkcje mogą nie działać w starszych wersjach API.

Istnieją predefiniowane klawisze, których znaczenia nie trudno się domyślić:
klawisz:                        jego numer:
 GLUT_KEY_F1                        1
 GLUT_KEY_F2                        2
 GLUT_KEY_F3                        3
 GLUT_KEY_F4                        4
 GLUT_KEY_F5                        5
 GLUT_KEY_F6                        6
 GLUT_KEY_F7                        7
 GLUT_KEY_F8                        8
 GLUT_KEY_F9                        9
 GLUT_KEY_F10                        10
 GLUT_KEY_F11                        11
 GLUT_KEY_F12                        12

 GLUT_KEY_LEFT                        100
 GLUT_KEY_UP                        101
 GLUT_KEY_RIGHT                        102
 GLUT_KEY_DOWN                        103
 GLUT_KEY_PAGE_UP                104
 GLUT_KEY_PAGE_DOWN                105
 GLUT_KEY_HOME                        106
 GLUT_KEY_END                        107
 GLUT_KEY_INSERT                108


Za obsługę myszy odpowiedzialna jest funkcja:

glutMouseFunc(&mButtonPressed);

która przyjmuje za parametr funkcję  która powinna mieć cztery parametry (wszystkie typu int):
1. klawisz myszki

przedefinowane klawisze mychy:
 GLUT_LEFT_BUTTON        //lewy
 GLUT_MIDDLE_BUTTON        //środkowy
 GLUT_RIGHT_BUTTON        //prawy

2. stan klawisza myszki

przedefinowane stany klawiszy mychy:
 GLUT_DOWN                        //wciśnięty
 GLUT_UP                        //puszczony

3/4. współrzędne myszki.

Przykładowa funkcja (wymaga dodania nagłówka stdio.h):

void mButtonPressed(int button, int state, int x, int y)
{
 switch(button)
 {
  case GLUT_LEFT_BUTTON:
   printf("Lewy");
  break;
  case GLUT_MIDDLE_BUTTON:
   printf("Srodkowy");
  break;
  case GLUT_RIGHT_BUTTON:
   printf("Prawy");
  break;
 }
 
 switch(state)
 {
  case GLUT_DOWN:
   printf(" w dol\n");
  break;
  case GLUT_UP:
   printf(" w gore\n");
  break;
 }
 
 printf("X: %i  Y: %i\n",x,y);
}


Do zmiany położenia kursora myszki służy funkcja:

glutWarpPointer(100,50); //której parametry to dwa int'y oznaczające położenie do którego przesunćć kuror (x i y)

Uzupełniającymi działanie mychy są funkcje:

glutMotionFunc(&ruchMychyP);
glutPassiveMotionFunc(&ruchMychyBez);

które ustalają funkcje wywoływane po wykonaniu ruchu myszki:
glutMotionFunc - gdy wciśnięty jest jakiś klawisz
glutPassiveMotionFunc - gdy żaden nie jest wciśnięty

Przykładowe funkcje podane w parametrze (ich parametry to współrzędne myszki):

void ruchMychyP(int x,int y)
{
 printf("Przesunieto myche z wcisnietym przyciskiem (%i,%i)\n",x,y);
}
 
void ruchMychyBez(int x,int y)
{
 printf("Przesunieto myche (%i,%i)\n",x,y);
}


Za wejcie i wyjscie myszki z obszaru [aktywnego] okna odpowiedzialna jest funkcja:

glutEntryFunc(&mouseEntry);

która przyporządkowuje funkcję wywoływaną w momencie wejścia i wyjścia myszki z obszaru okna. Funkcja ta ma w parametrze zmienną typu int, której przypisanay jest stan:

GLUT_LEFT        //Mycha opuściła obszar okna
GLUT_ENTERED        //Mycha "wlazła" w okno

void mouseEntry(int state)
{
 if (state==GLUT_LEFT) printf("Wejscie mychy: %i tj. mycha out \n",state);
 else printf("Wejscie mychy: %i tj. mycha in\n",state);
}


Inne urządzenia

GLUT pozwala też na obsługę innych niekonwencjonalnych urządzeń. Niestety niektóre nie są obsługiwane przez Windows. Funkcje do ich obsługi to:

(wszystkie są typu callback, czyli wymagają podania w parametrze adresu do funkcji która będzie wywoływana po określonym zdarzeniu, tak jak niektóre z wyżej wymienionych):

-Spaceball (cokolwiek to jest)
GLUTAPI void GLUTAPIENTRY glutSpaceballMotionFunc(void (GLUTCALLBACK *func)(int x, int y, int z)); //Wywołane po ruchu
GLUTAPI void GLUTAPIENTRY glutSpaceballRotateFunc(void (GLUTCALLBACK *func)(int x, int y, int z)); //Wywołane po obrocie
GLUTAPI void GLUTAPIENTRY glutSpaceballButtonFunc(void (GLUTCALLBACK *func)(int button, int state)); //Wywołane po wciśnięciu przycisku

-ButtonBox (??)
GLUTAPI void GLUTAPIENTRY glutButtonBoxFunc(void (GLUTCALLBACK *func)(int button, int state)); //Przycisk
GLUTAPI void GLUTAPIENTRY glutDialsFunc(void (GLUTCALLBACK *func)(int dial, int value));        Zmienia podłączenia do aktywnego okna (tak napisali na http:pyopengl.sourceforge.net/ - co to znaczy? nie wiem !)

-Tablet
GLUTAPI void GLUTAPIENTRY glutTabletMotionFunc(void (GLUTCALLBACK *func)(int x, int y)); //Ruch
GLUTAPI void GLUTAPIENTRY glutTabletButtonFunc(void (GLUTCALLBACK *func)(int button, int state, int x, int y)); //Przycisk

Przykład:

ustawienie (w main):

glutSpaceballMotionFunc(&ruchSpaceball);

funkcja:

void ruchSpaceball(int posx, int posy, int posz)
{
 printf("Polozenie spaceball: x: %i  y: %i  z: %i",posx,posy,posz);
}


Noooo. wreszcie zostało jeszcze ostatnie urządzonko. Ostatnie nie znaczy najmniej istotne. Joystick. Niestety obsługa tego kontrolera w wersji 3.7 nie jest jeszcze dopracowana (braki na Linuxie i korzystanie z MMApi na Windowsie) to jednak warto zapoznać się z jego obsługą. Zwłaszcza, że jest łatwa i krótka:

GLUTAPI void GLUTAPIENTRY glutJoystickFunc(void (GLUTCALLBACK *func)(unsigned int buttonMask, int x, int y, int z), int pollInterval);

Funkcja glutJoystickFunc przyjmuje dwa parametry: adres funkcji do której zwracany będzie stan urządzenia i czas co jaki będzie to następowało (w milisekundach). Funkcja do której będzie zwracany stan ma z kolei cztery parametry: wciśnięte przyciski (jako suma ich wartości) i wychylenie w każdą stronę. Wychylenie może mieć wartość od -1000 do 1000, a w stanie normalnym wynosi 0. Predefiniowane przyciski to:

Przycisk:                        Wartość:
GLUT_JOYSTICK_BUTTON_A                1
GLUT_JOYSTICK_BUTTON_B                2
GLUT_JOYSTICK_BUTTON_C                4
GLUT_JOYSTICK_BUTTON_D                8

Przykładowe wywołanie (UWAGA ! Nie testowane):

glutJoystickFunc(&joyFunc,100);

Przykładowa funkcja:

void joyFunc(unsigned int btn,int x,int y, int z)
{
 if (GLUT_JOYSTICK_BUTTON_A || GLUT_JOYSTICK_BUTTON_B) printf("przyciski A i B\n");
 printf("X: %i  Y: %i  Z: %i\n",x,y,z);
}


Do wymuszenia zwracania stanu joysticka służy funkcja (nie testowane !):

glutForceJoystickFunc();

I to tyle...

UZUPEŁNIENIE&nbsp;

Do obsługi klawiatury służą dwie dodatkowe funkcje:

void glutIgnoreKeyRepeat  (int ignore  );
int glutSetKeyRepeat  (int repeatMode );

Służą one do obsługi powtarzalności klawiszy. Ich działanie niestety jest determinowane przez system i różnie funkcjonuje na różnych platformach.

Funkcja glutIgnoreKeyRepeat określa czy powtróki wciśnięcia klawisza są relacjonowane do aktualnego okna. Jest jeden parametr, który przyjmuje jedynie dwie wartości 0 (auto-powtórki będą reportowane) i 1 (powtórki nie będą reportowane).

Druga funkcja (glutSetKeyRepeat) zmienia tryb powtarzania klawiszy.  W parametrze podajemy tryb. Możliwe są wartości:
GLUT_KEY_REPEAT_OFF        //wyłącza powtarzanie klawiszy (jeśli tylko jest to możliwe)
GLUT_KEY_REPEAT_ON         //włącza
GLUT_KEY_REPEAT_DEFAULT        //resetuje do domyślnego stanu&nbsp;

Funkcja zwraca stan GLUT jako liczbę typu int.
UWAGA ! Na Win32 powyższe funkcje nie działają. No cóż, nie można mieć wszystkiego :(.

Podsumowujący kod:
 o pozwala obracać myszką figurę
 o zmieniać kolor kwadratu przy użyciu klawiszy '+' i '-'

#include <GL/glut.h>    // Header File For The GLUT Library
//#include <GL/gl.h>        // Header File For The OpenGL32 Library
//#include <GL/glu.h>        // Header File For The GLu32 Library
 
/* The number of our GLUT window */
int window;
 
//Zmienne przechowujące
float r=0,g=0,b=0.7;        //kolor "tła"
int ox,oy;                //współrzędne myszki
float rx,ry;                //obroty obiektu
 
 
/* A general OpenGL initialization function.  Sets all of the initial parameters. */
void InitGL(int Width, int Height)                // We call this right after our OpenGL window is created.
{
  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);                // This Will Clear The Background Color To Black
  glClearDepth(1.0);                                // Enables Clearing Of The Depth Buffer
  glDepthFunc(GL_LESS);                                // The Type Of Depth Test To Do
  glEnable(GL_DEPTH_TEST);                        // Enables Depth Testing
  glShadeModel(GL_FLAT);                        // Enables Smooth Color Shading
 
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();                                // Reset The Projection Matrix
 
  gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);        // Calculate The Aspect Ratio Of The Window
 
  glMatrixMode(GL_MODELVIEW);
}
 
 
/* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */
void ReSizeGLScene(int Width, int Height)
{
  if (Height==0)                                // Prevent A Divide By Zero If The Window Is Too Small
    Height=1;
 
  glViewport(0, 0, Width, Height);                // Reset The Current Viewport And Perspective Transformation
 
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
 
  gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);
  glMatrixMode(GL_MODELVIEW);
}
 
/* The main drawing function. */
void DrawGLScene()
{
glutSetWindow(window);        //Ustala aktywne okno
 
  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);        // Clear The Screen And The Depth Buffer
  glLoadIdentity();                                // Reset The View
  //OpenGL scene goes here///////////////////////////////////////
  //Tutaj wstawiamy kod rysujący scenę
 
        glTranslatef(0,0,-5);
 
        glPushMatrix();
        //quasi-tło
        glTranslatef(0,0,-3);
        glColor3f(r,g,b);
        glBegin(GL_QUADS);
         glVertex3f(-10,-10,0);
         glVertex3f(-10, 10,0);
         glVertex3f( 10, 10,0);
         glVertex3f( 10,-10,0);
        glEnd();
 
        glPopMatrix();
 
 
        //Figura
        glRotatef(ry,1,0,0);
        glRotatef(rx,0,1,0);
        glBegin(GL_TRIANGLES);
 
        glColor3f(1,1,0);
         glVertex3f(0,1,0);
         glVertex3f(-1,-1,1);
         glVertex3f( 1,-1,1);
 
        glColor3f(1,0,0);
         glVertex3f(0,1,0);
         glVertex3f( 1,-1,1);
         glVertex3f( 1,-1,-1);
 
        glColor3f(0,1,0);
         glVertex3f(0,1,0);
         glVertex3f( 1,-1,-1);
         glVertex3f(-1,-1,-1);
 
        glColor3f(0,0,1);
         glVertex3f(0,1,0);
         glVertex3f(-1,-1,1);
         glVertex3f(-1,-1,-1);
 
        glEnd();
 
 
 
  ///////////////////////////////////////////////////////////////
  // swap the buffers to display, since double buffering is used.
  glutSwapBuffers();
}
 
 
//Funkcja wywoływana po wciśnięciu klawisza
void keyPressed(unsigned char key, int x, int y)
{
        switch (key)&nbsp;
        {
          case '-':                //Używamy klawisza '-' do przyciemnienia "tła"
           if(r<1)r+=0.1;
           if(g<1)g+=0.1;
           if(b<1)b+=0.1;
         break;
         case '+':                //Używamy klawisza '+' do rozjaśnienia "tła"
          if(r>0)r-=0.1;
          if(g>0)g-=0.1;
          if(b>0)b-=0.1;
         break;
        }
 
    /* If 'x' is pressed, kill everything. */
    if (key == 'x')
    {
      /* shut down our window */
      glutDestroyWindow(window);
 
      /* exit the program...normal termination. */
      exit(0);
    }
}
 
//Funkcja wykonywana gdy przesunięto mychę z wciśniętym przyciskiem
void ruchMychyP(int x,int y)
{
 rx+=(x-ox)*0.25;
 ry+=(oy-y)*0.25;
 ox=x;
 oy=y;
}
 
//Funckja wywołana po wciśnięciu klawisza&nbsp;
void mButtonPressed(int button, int state, int x, int y)
{
 ox=x;
 oy=y;
}
 
int main(int argc, char **argv)
{
  /* Initialize GLUT state - glut will take any command line arguments that pertain to it or
     X Windows - look at its documentation at http://reality.sgi.com/mjk/spec3/spec3.html */
  glutInit(&argc, argv);
 
  /* Select type of Display mode:
     Double buffer
     RGBA color
     Alpha components supported
     Depth buffered for automatic clipping */
  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
 
  /* get a 640 x 480 window */
  glutInitWindowSize(640, 480);
 
  /* the window starts at the upper left corner of the screen */
  glutInitWindowPosition(0, 0);
 
  /* Open a window */
  window = glutCreateWindow("GLUT TUTORIAL #2");
 
  /* Register the function to do all our OpenGL drawing. */
  glutDisplayFunc(&DrawGLScene);
 
 
  /* Register the function called when our window is resized. */
  glutReshapeFunc(&ReSizeGLScene);
 
  //Ustalenie funkcji
  glutKeyboardFunc(&keyPressed);        // która zostanie wywołana po wciśnięciu klawisza
  glutMotionFunc(&ruchMychyP);                // po ruchu myszki z przyciskiem
  glutMouseFunc(&mButtonPressed);        // po wciśnięciu przycisku
 
  //Inicjalizacja OpenGL
  InitGL(640, 480);
 
  /* Even if there are no events, redraw our gl scene. */
  glutIdleFunc(&DrawGLScene);
 
 
  /* Start Event Processing Engine */
  glutMainLoop();
 
  /* shut down our window */
  glutDestroyWindow(window);
 
  return 1;
}


OKNO


Podstawowe funkcje obsługi okien (oddziałowują na aktualnie aktywne):

glutSetWindowTitle("TYTUL");        //Zmienia tytuł okna. Jeden parametr typu const char*.
glutPositionWindow(10, 10);        //Zmienia pozycję okna. Dwa parametry typu int (określają lewy górny róg okna)
glutReshapeWindow(int width, int height);        //Zmienia rozmiar okna. Pierwszy parametr to szerokość, drugi to wysokość

GLUT umożliwia tworzenie "pod-okien" służy do tego funkcja:

int glutCreateSubWindow(window,10,10,100,100); //Zwraca uchwyt do nowo utworzonego pod-okna. Pierwszy parametr to numer (uchwyt) do okna-"rodzica" czyli tego w którym będzie zawarte nowo utworzone. Dwa kolejne parametry to położenie, dwa ostatnie to szerokość i wysokość. Wszystkie są typu int. UWAGA ! Do każdego nowo utworzonego okna należy przypisać funkcje jakie będą używane. Najważniejszą i konieczną jest glutDispayFunc.

przykład:

int subwindow;

subwindow=glutCreateSubWindow(window,10,10,100,100);
glutDisplayFunc(&DrawSubWindowGLScene);

Do pobrania aktywnego okna służy funkcja:

int glutGetWindow(void); //która zwraca uchwyt (nr) bieżącego okna

Do zmiany aktywnego okna służy funkcja:

glutSetWindow(int win); // w parametrze podajemy uchwyt okna które ma być aktywne

Do sterowania oknem służą funkcje:

glutIconifyWindow(void);                //Minimalizuje okno (aktywne)
glutShowWindow(void);                        //Pokazuje okno (aktywne)
glutHideWindow(void);                        //Ukrywa okno (aktywne)

glutPopWindow(void);                        //Funkcja pobiera okno ze stosu
glutPushWindow(void);                        //Funkcja kładzie okno na stos

Działanie dwóch powyższych funkcji jest analogiczne jak działanie funkcji
glPopMatrix();
glPuchMatrix();
w OpenGL. Najlepiej spróbować samemu.

Dodatkową funkcję pozwalającą kontrolować stan okna (ustala się jak wszystkie dla bieżącego aktywnego okna) jest:

glutVisibilityFunc

która ustala funckję wywoływaną po ukryciu (ew. minimalizacji) i po ukazaniu (ew. przywróceniu) okna.
Możliwe wartości parametru w wywołanej funkcji to :

GLUT_NOT_VISIBLE        //Okno niewidoczne
GLUT_VISIBLE                //Okno widoczne

Przykład:

wywołanie (w main() ):

glutVisibilityFunc(&oknoWidok)

funkcja:

void oknoWidok(int state)
{
 if (state==GLUT_VISIBLE) printf(" okno widoczne \n"); else printf("okno niewidoczne \n");
}


Do pobrania aktualnego stanu okna służy funkcja:
glutWindowStatusFunc
która przyjmuje jeden parametr - adres do funkcji która zostanie uruchomiona w przypadku zmiany stanu okna. Możliwe warto?ci parametru funkcji to:

nazwa:                                wartość:
 GLUT_HIDDEN                        0
 GLUT_FULLY_RETAINED                1
 GLUT_PARTIALLY_RETAINED        2
 GLUT_FULLY_COVERED                3


Przykład:

glutWindowStatusFunc(&winStatus);

i funkcja:

void winStatus(int state)
{
 printf("Nastąpiła zmiana stanu na:");
 switch (state)
 {
  case GLUT_HIDDEN:
   printf("HIDDEN\n");
  break;
  case GLUT_FULLY_RETAINED:
   printf("FULLY_RETAINED\n");
  break;
  case GLUT_PARTIALLY_RETAINED:
   printf("PARTIALLY_RETAINED\n");
  break;
  case GLUT_FULLY_COVERED:
   printf("FULLY_COVERED\n");
  break;
 }
}




No i na koniec mały przykładzik. Generuje okno z przesuwającym się napisem na belce, które można przesuwać klikając w jego dowolnym miejscu i pod okno o tej samej właściwości. UWAGA! Zastosowałem procedurkę glutGet która jest opisana w dalszej części tekstu.

#include <GL/glut.h>    // Nagłówek do GLUT
//#include <GL/gl.h>         //Pozostałe nagłówki (nie konieczne gdyż zawarte już w GLUT)
//#include <GL/glu.h>
 
//Główne okno
int window;
 
//Pod-okno
int subwindow;
 
 
//Współrzędne myszki
int mx,my;
 
 
//Inicjalizacja OpenGL
void InitGL(int Width, int Height)                // We call this right after our OpenGL window is created.
{
  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);                // This Will Clear The Background Color To Black
  glClearDepth(1.0);                                // Enables Clearing Of The Depth Buffer
  glDepthFunc(GL_LESS);                                // The Type Of Depth Test To Do
  glEnable(GL_DEPTH_TEST);                        // Enables Depth Testing
  glShadeModel(GL_SMOOTH);                        // Enables Smooth Color Shading
 
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();                                // Reset The Projection Matrix
 
  gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,10.0f);        // Calculate The Aspect Ratio Of The Window
 
  glMatrixMode(GL_MODELVIEW);
}
 
 
//Zmiana rozmiaru
void ReSizeGLScene(int Width, int Height)
{
  if (Height==0)                                // Prevent A Divide By Zero If The Window Is Too Small
    Height=1;
 
  glViewport(0, 0, Width, Height);                // Reset The Current Viewport And Perspective Transformation
 
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
 
  gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,10.0f);
  glMatrixMode(GL_MODELVIEW);
}
 
//Zmienne do przewijania napisu na pasku&nbsp;
char txt[]="GLUT TUTORIAL #3 ";        //Text
char txtlen=17;                        //Długość textu
char snap[20];                        //Pomocnicza
 
//Funkcja, powiązana z timer'em, odpowiedzialna za przesuwanie napisu na pasku
void scrollBar(int scroll)
{
unsigned short int i;        //Zmienna pomocnicza
 
 //Wygenerowanie napisu na pasek
 for (i=0; i<txtlen; i++)
 if (i+scroll<txtlen)
 snap[i]=txt[i+scroll]; else
 snap[i]=txt[i+scroll-txtlen];
 
 snap[txtlen]='\0';
 
 glutSetWindow(window);                        //Zmiana aktywnego okna
 glutSetWindowTitle(snap);                //Zmiana napisu na pasku tytułowym
 
 //Utrzymanie timer'a w ruchu
 if (scroll>=txtlen)
   glutTimerFunc (1000,&scrollBar,0); else
   glutTimerFunc (1000,&scrollBar,scroll+1);
}
 
 
 
 
int rot=0;
 
//Główna funkcja rysująca
void DrawGLScene()
{
 
  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);        // Clear The Screen And The Depth Buffer
  glLoadIdentity();                                // Reset The View
  //OpenGL scene goes here///////////////////////////////////////
  glTranslatef(0,0,-1);
      glRotatef(rot++,0,0,1);
        glBegin(GL_TRIANGLES);
        glColor3f(1,0,0);
         glVertex3f(0,0.4,0);
        glColor3f(0,1,0);
         glVertex3f(-0.4,-0.25,0);
        glColor3f(0,0,1);
         glVertex3f( 0.4,-0.25,0);
        glEnd();
 
  ///////////////////////////////////////////////////////////////
  // swap the buffers to display, since double buffering is used.
  glutSwapBuffers();
}
 
 
//Rysuje scenę z pod-okna
void DrawSubWindowGLScene()
{
  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);        // Clear The Screen And The Depth Buffer
  glLoadIdentity();                                // Reset The View
  //Scena OpenGL
  glTranslatef(0,0,-1);
      glRotatef(rot,1,0,1);
        glBegin(GL_QUADS);
                glColor3f(1,0,0);
         glVertex3f(-0.4,-0.4,0);
                glColor3f(0,1,0);
         glVertex3f( 0.4,-0.4,0);
                glColor3f(0,0,1);
         glVertex3f( 0.4, 0.4,0);
                glColor3f(0,1,1);
         glVertex3f(-0.4, 0.4,0);
        glEnd();
 
  glutSwapBuffers();
 
}
 
//Funkcja rysująca sceny w obu oknach
void DrawAll()
{
 
 glutSetWindow(window);                                //Zmiana aktywnego okna
 DrawGLScene();
 
 glutSetWindow(subwindow);                        //Zmiana aktywnego okna
 DrawSubWindowGLScene();
}
 
//Funckja wywołana po przesunięciu myszki z wciśniętym klawiszem
void mBtnMove(int x,int y)
{
 int lx,ly;
  lx=glutGet(GLUT_WINDOW_X);        //pobiera położenie x aktywnego okna
  ly=glutGet(GLUT_WINDOW_Y);        //pobiera położenie y aktywnego okna
  glutPositionWindow(x-mx+lx,y-my+ly);        //Zmienie położenie okna
}
 
//Funckja wywołana po wciśnięciu klawisza
void mButtonPressed(int button, int state, int x, int y)
{
 mx=x;
 my=y;
}
 
 
//Funckja wywołana po przesunięciu myszki z wciśniętym klawiszem dla pod-okna
void mSBtnMove(int x,int y)
{&nbsp;
int ax,ay,kx,ky;
 
  kx=glutGet(GLUT_WINDOW_X);        //pobiera położenie x aktywnego pod-okna
  ky=glutGet(GLUT_WINDOW_Y);        //pobiera położenie y aktywnego pod-okna
        glutSetWindow(window);        //Zmienia aktywne okno
  ax=glutGet(GLUT_WINDOW_X);        //pobiera położenie x aktywnego okna
  ay=glutGet(GLUT_WINDOW_Y);        //pobiera położenie y aktywnego okna
        glutSetWindow(subwindow);//Zmienia aktywne okno
         glutPositionWindow(kx+x-mx-ax,ky+y-my-ay);        //Zmienie położenie pod-okna
}
 
//Funckja wywołana po wciśnięciu klawisza dla pod-okna
void mSButtonPressed(int button, int state, int x, int y)
{
 mx=x;
 my=y;
}
 
 
//Podstawowa funkcja każdego programu
int main(int argc, char **argv)
{
  glutInit(&argc, argv);        //Inicjalizacja GLUT
  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);        //Ustalenie trybu wyświetlania
 
  //Inicjalizacja i ustawienia dla okna renderingu
  glutInitWindowSize(640, 480);                //rozmiar
  glutInitWindowPosition(0, 0);         //położenie
  window = glutCreateWindow("GLUT TUTORIAL #3");//utworzenie okna
  glutDisplayFunc(&DrawGLScene);         //funkcja wyświetlania
  glutReshapeFunc(&ReSizeGLScene);        //zmiana rozmiaru
  InitGL(640, 480);                        //Inicjalizacja OpenGL
 
  //Funkcje callback dla okna głównego
  glutTimerFunc (500,&scrollBar,0);        //Przesuwanie napisu na pasku
  glutMotionFunc(&mBtnMove);                // po ruchu myszki z przyciskiem
  glutMouseFunc(&mButtonPressed);        // po wciśnięciu przycisku
 
  subwindow=glutCreateSubWindow(window,270,190,100,100);        //Utworzenie pod-okna
  glutDisplayFunc(&DrawSubWindowGLScene);                        //Ustalenie funkcji wyświetlania
  InitGL(100, 100);                        //Inicjalizacja OpenGL dla pod-okna (może być zupełnie inna)
 
  //Funkcje callback dla pod-okna
  glutMotionFunc(&mSBtnMove);                // po ruchu myszki z przyciskiem
  glutMouseFunc(&mSButtonPressed);        // po wciśnięciu przycisku
 
 
  glutIdleFunc(&DrawAll);                //Funkcja wywołana w przypadku braku żadnych zdarzeń
 
 
  glutMainLoop();                        //Główna pętla
 
  glutDestroyWindow(window);                //Usunięcie okna
  return 1;
}


WYŚWIETLANIE


Oprócz wyżej wymienionej funkcji: glutDisplayFunc związane z wyświetlaniem są:

glutPostRedisplay();

i

glutPostWindowRedisplay(int win);

służą one do niezależnego od pętli wyświetlenia zawartości okna. Pierwsza działa na aktywne okno, druga na to do którego uchwyt (którego numer) podaliśmy w parametrze.

oraz funkcja:

glutInitDisplayString&nbsp;

której działanie opisane jest dalej (czyt. dodatki).


MENU


GLUT umożliwia utworzenie menu tekstowego typu pop-up, czyli takiego, które zostanie ukazane po wciśnięciu klawisza myszki.
Do utworzenia menu lub pod-menu służy funkcja:

glutCreateMenu(&selectMessage); //za parametr przyjmuje ona adres do funkcji (z parametrem int) i zwraca numer utworzonego menu (jego uchwyt)

Przykład użycia:

int submenu1 = glutCreateMenu(&selectMessage);

gdzie funkcja selectMessage ma postać np.

void selectMessage(int i)
{
 printf("Pozycja z menu: %i\n",i);
}

do dodania pozycji do menu służy funkcja:

glutAddMenuEntry("abc", 1); //przyjmuje ona dwa parametry: typu const char * który zawiera opis pozycji menu i drugi który jest jej numerem (gdy wciśniemy tę pozycję to zostanie wywołana funkcja ustalona przy utworzeniu menu, której parametrem będzie właśnie ten numer)

UWAGA ! GLUT jest maszyną stanu (podobnie jak OpenGL). W uproszczeniu znaczy to, że to co zrobiliśmy ostatnio (i nie tylko) jest zapisane. Tak więc używając funkcji glutAddMenuEntry dodamy pozycję do ostatnio utworzonego menu (lub tego które zmieniliśmy ostatnio na aktywne).
Do zmiany aktywnego menu służy funkcja:

glutSetMenu(submenu1); //gdzie podajemy jeden parametr typu int i jest to numer (uchwyt) menu, które ustawiamy na aktywne


Podobnie do funkcji glutAddMenuEntry działa funkcja:

glutAddSubMenu("Color", submenu2); //która służy do dodania do aktywnego menu, pod-menu, pierwszy parametr (const char *) to opis jaki zostanie nadany menu, drugi to numer/uchwyt menu, które dodajemy.

Do ustalenia klawisza myszki po wciśnięciu którego uruchomi się menu służy funkcja:

glutAttachMenu(GLUT_LEFT_BUTTON); //której parametrem jest przycisk mychy, jeden z trzech:

 GLUT_LEFT_BUTTON                //lewy
 GLUT_MIDDLE_BUTTON                //środkowy
 GLUT_RIGHT_BUTTON                //prawy

i która ustawia aktywne menu do pokazania po wciśnięciu klawisza.

Przykładowy kod:

 tworzy menu z pozycjami: 9 by 15 , Times Roman 10 , Times Roman 24 i dwoma pod-menu:
 Messages (pozycje: abc i ABC) i Color (pozycje: Green, Red, White), które zostanie wywołane po wciśnięciu lewego przycisku  myszki

//Do main
int submenu1, submenu2;
 
submenu1 = glutCreateMenu(selectMessage);
 
submenu2 = glutCreateMenu(selectColor);
glutAddMenuEntry("Green", 1);
glutAddMenuEntry("Red", 2);
glutAddMenuEntry("White", 3);
 
glutSetMenu(submenu1);
glutAddMenuEntry("abc", 1);
glutAddMenuEntry("ABC", 2);
 
glutCreateMenu(selectFont);
glutAddMenuEntry("9 by 15", 0);
glutAddMenuEntry("Times Roman 10", 1);
glutAddMenuEntry("Times Roman 24", 2);
glutAddSubMenu("Messages", submenu1);
glutAddSubMenu("Color", submenu2);
 
glutAttachMenu(GLUT_LEFT_BUTTON);


//luzem
 
void selectMessage(int i)
{
 printf("msg nr %i\n",i);
}
 
void selectColor(int i)
{
 printf("color nr %i\n",i);
}
 
void selectFont(int i)
{
 printf("font nr %i\n",i);
}



OK. Kolejna funkcja:

int glutGetMenu();

nie ma parametrów i służy do pobrania uchwytu aktywnego okna, który to zwraca.

Przykład

int aktywne_menu;
aktywne_menu=glutGetMenu();

Do usunięcia menu służy funkcja:
glutDestroyMenu(int menu);
której parametrem jest uchwyt do menu, które chcemy usunąć.

Aby rozkojarzyć przycisk myszki z menu służy funkcja:

glutDetachMenu(GLUT_LEFT_BUTTON);

której parametr jest analogiczny jak w glutAttachMenu.

Do usunięcia pozycji z menu służy funkcja:
glutRemoveMenuItem(int); //która ma jeden parametr, za który podajemy numer pozycji z aktywnego menu, którą chcemy usunąć.
Funkcja działa zarówno na pozycje jak i pod-menu.

Do zmiany pozycji menu służy funkcja:

glutChangeToMenuEntry(int item, const char *label, int value);

Pierwszy parametr to nr pozycji, którą zmieniamy, drugi to opis na jaki zmieniamy bieżący opis pozycji. Ostatni to wartość jaka zostanie przekazana do funkcji ustalonej przy tworzeniu menu (ofcourse po wybraniu pozycji z menu przez użytkownika).

Analogiczną do powyższej, ale odpowiadającą za zmianę pod-menu jest funkcja:

glutChangeToSubMenu(int item, const char *label, int submenu);

Zmienia się jedynie ostatni parametr. Podajemy numer (uchwyt) utworzonego menu, które zastąpi pod-menu lub pozycję na pozycji podanej w pierwszym parametrze.

Ufff. Do podstawowych funkcji obsługi menu służą jeszcze dwa polecenia:

glutMenuStateFunc(void (GLUTCALLBACK *func)(int state));
glutMenuStatusFunc(void (GLUTCALLBACK *func)(int status, int x, int y));

Pierwsza służy do przypisania (wybrania, analogicznie jak np. po wciśnięciu klawisza) funkcji która zostanie wywołana po zmianie stanu przez menu. Funkcja do której adres podamy powinna mieć jeden parametr typu int, do którego zostanie przekazany obecny stan menu. Możliwe wartości:

0 czyli GLUT_MENU_NOT_IN_USE
i
1 czyli GLUT_MENU_IN_USE

Przykładowa funkcja

void menuState(int state)
{
 printf("stan menu: %i\n",state);
}

i przykładowe przypisanie

glutMenuStateFunc(&menuState);

Druga czyli glutMenuStatusFunc różni się od pierwszej tym jedynie, że zwraca do funkcji oprócz stanu współrzędne (x i y) myszki, co jest praktycznie równoznaczne położeniu menu.


No i oczywiście na koniec mały przykład. Pozwala sterować tym co jest pokazywane na ekranie za pomocą menu.

#include <GL/glut.h>    // Nagłówek do GLUT
//#include <GL/gl.h>         //Pozostałe nagłówki (nie konieczne gdyż zawarte już w GLUT)
//#include <GL/glu.h>
 
//Główne okno
int window;
 
//Zmienne służące przy wyświetlanie
#define triangle 1
#define quad 2
int color=4,figure=triangle,showing=1;
 
//Uchwyty menu
int submenu1, submenu2;
 
//Inicjalizacja OpenGL
void InitGL(int Width, int Height)                // We call this right after our OpenGL window is created.
{
  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);                // This Will Clear The Background Color To Black
  glClearDepth(1.0);                                // Enables Clearing Of The Depth Buffer
  glDepthFunc(GL_LESS);                                // The Type Of Depth Test To Do
  glEnable(GL_DEPTH_TEST);                        // Enables Depth Testing
  glShadeModel(GL_SMOOTH);                        // Enables Smooth Color Shading
 
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();                                // Reset The Projection Matrix
 
  gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,500.0f);        // Calculate The Aspect Ratio Of The Window
 
  glMatrixMode(GL_MODELVIEW);
  glEnable(GL_COLOR_MATERIAL);
}
 
 
//Zmiana rozmiaru
void ReSizeGLScene(int Width, int Height)
{
  if (Height==0)                                // Prevent A Divide By Zero If The Window Is Too Small
    Height=1;
 
  glViewport(0, 0, Width, Height);                // Reset The Current Viewport And Perspective Transformation
 
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
 
  gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,500.0f);
  glMatrixMode(GL_MODELVIEW);
}
 
 
//Główna funkcja rysująca
void DrawGLScene()
{
glutSetWindow(window);
  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);        // Clear The Screen And The Depth Buffer
  glLoadIdentity();                                // Reset The View
  //OpenGL scene goes here///////////////////////////////////////
if (showing)
{
 glTranslatef(0,0,-1);
   switch (color)
   {
    case 1:
                glColor3f(1,0,0);
        break;
    case 2:
                glColor3f(0,1,0);
        break;
    case 3:
                glColor3f(0,0,1);
        break;
    case 4:
                glColor3f(1,1,1);
        break;
   }
 
 if (figure==triangle)
 {&nbsp;
  glBegin(GL_TRIANGLES);
        glVertex3f(0,0.2,0);
        glVertex3f(0.2,-0.2,0);
        glVertex3f(-0.2,-0.2,0);
  glEnd();
 } else
 {&nbsp;
  glBegin(GL_QUADS);
        glVertex3f(-0.1,-0.1,0);
        glVertex3f(0.1,-0.1,0);
        glVertex3f(0.1,0.1,0);
        glVertex3f(-0.1,0.1,0);
  glEnd();
 }
}
  ///////////////////////////////////////////////////////////////
  // swap the buffers to display, since double buffering is used.
  glutSwapBuffers();
}
 
//Funkcje wywoływane po wybraniu pozycji z menu:
 
void selectShowing(int i)
{
 showing=i;
 if (i==0)
 glutChangeToMenuEntry(2,"Rysuj", 1); else
 glutChangeToMenuEntry(2,"Ukryj", 0);
}
 
 
void selectFigure(int i)
{
 switch (i)
 {
  case 1:
   figure=triangle;
  break;
  case 2:
   figure=quad;
  break;
 }
}
 
 
void selectColor(int i)
{
 color=i;
}
 
 
//Podstawowa funkcja każdego programu
int main(int argc, char **argv)
{
  glutInit(&argc, argv);        //Inicjalizacja GLUT
  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);        //Ustalenie trybu wyświetlania
 
  //Inicjalizacja i ustawienia dla okna renderingu;
  glutInitWindowSize(480, 480);                //rozmiar
  glutInitWindowPosition(0, 0);         //położenie
  window = glutCreateWindow("GLUT TUTORIAL #4");//utworzenie okna
  glutDisplayFunc(&DrawGLScene);         //funkcja wyświetlania
  glutReshapeFunc(&ReSizeGLScene);        //zmiana rozmiaru
  InitGL(480, 480);                        //Inicjalizacja OpenGL
 
 
        //Tworzymy menu i pod-menu'a oraz przy tym ustalamy wywoływane po wybraniu pozycji funkcje
        submenu1 = glutCreateMenu(selectFigure);
 
        submenu2 = glutCreateMenu(selectColor);
        glutAddMenuEntry("Czerwony", 1);
        glutAddMenuEntry("Zielony", 2);
        glutAddMenuEntry("Niebieski", 3);
        glutAddMenuEntry("Biały", 4);
 
        glutSetMenu(submenu1);                //przykładowe użycie funkcji setmenu do przełączenia się na początkowe pod-menu
        glutAddMenuEntry("Trójkąt", 1);
        glutAddMenuEntry("Kwadrat", 2);
;
        glutCreateMenu(selectShowing);
        glutAddSubMenu("Figura", submenu1);
        glutAddMenuEntry("Ukryj", 0);
        glutAddSubMenu("Kolor", submenu2);
 
        //Kojarzymy lewy przycisk z menu
        glutAttachMenu(GLUT_LEFT_BUTTON);
        glutAttachMenu(GLUT_RIGHT_BUTTON);        //prawy zresztą też...
 
  glutIdleFunc(&DrawGLScene);                //Funkcja wywołana w przypadku braku żadnych zdarzeń
 
  glutMainLoop();                        //Główna pętla
 
  glutDestroyWindow(window);                //Usunięcie okna
  return 1;
}



TIMER


Timer jest to zegarek który za określony czas wywołuje pewną funkcję.
Do obsługi timera w GLUT służy funkcja:

glutTimerFunc(unsigned int millis, void (GLUTCALLBACK *func)(int value), int value);

przyjmuje ona trzy parametry:
millis - czas za który zostanie wywołana funkcja (w milisekundach)
funkcja (która musi mieć parametr int)
wartość jaka zostanie przekazana do parametru powyższej funkcji.

Przykład:

 glutTimerFunc (1000,&timerFunc,22); //Co sekundę wywołuje funkcję timerFunc z parametrem 22

Aby powtórzyć lub wywoływać działanie timer'a należy procedurę ponownie uruchomić.

Przykładowy kod: mierzy liczbę klatek na sekundę i pokazuje na wykresie (czerwone trójkąty oznaczają setki , skala jest od 0 do 500).
#include <GL/glut.h>    // Nagłówek do GLUT
//#include <GL/gl.h>         //Pozostałe nagłówki (nie konieczne gdyż zawarte już w GLUT)
//#include <GL/glu.h>
 
//Główne okno
int window;
 
//Liczba klatek na sek. i aktualna
int fps=0,sfps=0;
 
//Inicjalizacja OpenGL
void InitGL(int Width, int Height)                // We call this right after our OpenGL window is created.
{
  glClearColor(0.7f, 0.7f, 0.7f, 0.0f);                // This Will Clear The Background Color To Black
  glClearDepth(1.0);                                // Enables Clearing Of The Depth Buffer
  glDepthFunc(GL_LESS);                                // The Type Of Depth Test To Do
  //glEnable(GL_DEPTH_TEST);                        // Enables Depth Testing
  glShadeModel(GL_FLAT);                        // Enables Smooth Color Shading
 
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();                                // Reset The Projection Matrix
 
  gluPerspective(45.0f,6.4,0.1f,500.0f);        // Calculate The Aspect Ratio Of The Window
 
  glMatrixMode(GL_MODELVIEW);
  glEnable(GL_COLOR_MATERIAL);
}
 
 
//Zmiana rozmiaru
void ReSizeGLScene(int Width, int Height)
{
  if (Height==0)                                // Prevent A Divide By Zero If The Window Is Too Small
    Height=1;
 
  glViewport(0, 0, Width, Height);                // Reset The Current Viewport And Perspective Transformation
 
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
 
  gluPerspective(45.0f,6.4,0.1f,500.0f);
  glMatrixMode(GL_MODELVIEW);
}
 
 
 //Rysuje trójkąt (przy podziałce)
 void DrawTri(float fx)
 {&nbsp;
  glVertex3f(fx,0.16,0);
  glVertex3f(fx+0.04,0.36,0);
  glVertex3f(fx-0.04,0.36,0);
 }
 
//Główna funkcja rysująca
void DrawGLScene()
{
fps++;                //Zliczaj fps
 
glutSetWindow(window);
  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);        // Clear The Screen And The Depth Buffer
  glLoadIdentity();                                // Reset The View
  //OpenGL scene goes here///////////////////////////////////////
  glTranslatef(0,0,-1);
        //Tło
        glColor3f(1,1,1);
        glBegin(GL_QUADS);
         glVertex3f(-2.55,-0.15,0);
         glVertex3f(-2.55, 0.15,0);
         glVertex3f( 2.55, 0.15,0);
         glVertex3f( 2.55,-0.15,0);
        glEnd();
 
        //Skala
        glTranslatef(0,0,0.005);
        glColor3f(0,1,0);
        glBegin(GL_QUADS);
         glVertex3f(-2.5,-0.1,0);
         glVertex3f(-2.5, 0.1,0);
         glVertex3f(-2.5+sfps*0.01, 0.1,0);
         glVertex3f(-2.5+sfps*0.01,-0.1,0);
        glEnd();
 
        //Podziałka
        glBegin(GL_TRIANGLES);
          glColor3f(1,0,0);
         DrawTri(-2.5);        //0
         DrawTri(-1.5);        //100
         DrawTri(-0.5); //200
         DrawTri(0.5); //300
         DrawTri(1.5); //400
         DrawTri(2.5); //500
           glColor3f(1,1,1);
         DrawTri(-2);//50 = 0.25
         DrawTri(-1);//150
         DrawTri(0);//250
         DrawTri(1); //350
         DrawTri(2);   //450
         glEnd();
 
  ///////////////////////////////////////////////////////////////
  // swap the buffers to display, since double buffering is used.
  glutSwapBuffers();
}
 
//Funkcja wywoływana przez timer
void timerFunc(int i)
{
 sfps=fps;
 fps=0;
 //powtórz wywoływanie
 glutTimerFunc (1000,&timerFunc,0);    //Co sekundę wywołuje funkcję timerFunc
}
 
//Podstawowa funkcja każdego programu
int main(int argc, char **argv)
{
  glutInit(&argc, argv);        //Inicjalizacja GLUT
  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);        //Ustalenie trybu wyświetlania
 
  //Inicjalizacja i ustawienia dla okna renderingu
  glutInitWindowSize(640, 100);                //rozmiar
  glutInitWindowPosition(0, 0);         //położenie
  window = glutCreateWindow("GLUT TUTORIAL #5");//utworzenie okna
  glutDisplayFunc(&DrawGLScene);         //funkcja wyświetlania
  glutReshapeFunc(&ReSizeGLScene);        //zmiana rozmiaru
  InitGL(640, 100);                        //Inicjalizacja OpenGL
 
 
  glutTimerFunc (1000,&timerFunc,0);    //Co sekundę wywołuje funkcję timerFunc
 
  glutIdleFunc(&DrawGLScene);                //Funkcja wywołana w przypadku braku żadnych zdarzeń
 
 
  glutMainLoop();                        //Główna pętla
 
  glutDestroyWindow(window);                //Usunięcie okna
  return 1;
}


MODELE


GLUT zawiera też funkcje do rysowania prostych modeli:

 - glutWireSphere(GLdouble radius, GLint slices, GLint stacks);                //siatka kuli
 - glutSolidSphere(GLdouble radius, GLint slices, GLint stacks);        //kula

 - glutWireCone(GLdouble base, GLdouble height, GLint slices, GLint stacks);        //stożek - siatka
 - glutSolidCone(GLdouble base, GLdouble height, GLint slices, GLint stacks);        //stożek

 - glutWireCube(GLdouble size);                                                //siatka sześcianu
 - glutSolidCube(GLdouble size);                                        //sześcian

 - glutWireTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings);                //siatka torusa
 - glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings);        //torus

 - glutWireDodecahedron(void);                        //siatka dwunastościanu
 - glutSolidDodecahedron(void);                        //dwunastościan

 - glutWireTeapot(GLdouble size);                //siatka czajnika
 - glutSolidTeapot(GLdouble size);                //czajnik

 - glutWireOctahedron(void);                        //siatka ośmioboku
 - glutSolidOctahedron(void);                        //ośmiobok

 - glutWireTetrahedron(void);                        //czworościan - siatka
 - glutSolidTetrahedron(void);                        //czworościan

 - glutWireIcosahedron(void);                        //znowu wielościan - siatka
 - glutSolidIcosahedron(void);                        //wielościan

Przykładowo:

glutSolidTorus(0.5,3,20,20);

rysuje torus (taki pączek ;) ). Tym razem nie będzie przykładziku, bo całość jest zbyt oczywista. Wystarczy wstawić funkcję do DrawGLScene i tyle.

PISANIE


GLUT udostępnia możliwość pisania bitmapowymi czcionkami. Niestety umożliwia pisanie tylko jednego znaku na raz. służy do tego funkcja:

glutBitmapCharacter(void *font, int character);

Możliwe typy czcionki (pierwszy parametr):

GLUT_BITMAP_9_BY_15
GLUT_BITMAP_8_BY_13
GLUT_BITMAP_TIMES_ROMAN_10
GLUT_BITMAP_TIMES_ROMAN_24
GLUT_BITMAP_HELVETICA_10
GLUT_BITMAP_HELVETICA_12
GLUT_BITMAP_HELVETICA_18

Drugi parametr umożliwia podanie jednego znaku (np. 'a','1' lub '@').

Funkcja:

int glutBitmapWidth(void *font, int character);

umożliwia pobranie (zwraca wartość) szerokości znaku w danej czcionce. Parametry identyczne jak wyżej.

Przykładowe wykorzystanie, wypisuje określony tekst na ekranie w określonej pozycji (wymaga dodania modułu string.h:
"#include <string.h>" na początku do obsługi strlen)

float glutPrint(float x,float y,void *font,char *txt,float scale)
{ int i;
  int len=strlen(txt);
 for (i=0; i<len; i++)
 {
  glRasterPos2f(x,y);
  glutBitmapCharacter(font, txt[i]);
  x+=glutBitmapWidth(font,txt[i])*scale;
 }
}



Podobne działanie do powyższych mają funkcje (różni się to, że nie używają czcionek bitmapowych):

glutStrokeCharacter(void *font, int character)
int glutStrokeWidth(void *font, int character);

Możliwe typy czcionki dla powyższych funkcji to:

GLUT_STROKE_ROMAN
GLUT_STROKE_MONO_ROMAN

Ostatnimi funkcjami z tej grupy są:

int glutBitmapLength(void *font, const unsigned char *string);
int glutStrokeLength(void *font, const unsigned char *string);

które podają "długość" (zwracana jako int) ciągu znaków (podanego w drugim parametrze) w określonej czcionce (pierwszy parametr). Z nazwy można wywnioskować, które dotyczą czcionek bitmapowych, a które nie ;) .

Prosty przykład na zakończenie:
 * przewijająca się lista autorów
 * obliczanie fps
Oczywiście poniższy kod jest strasznie nie-efektywny i wymaga zooptymalizowania (nawet na podstawowym poziomie), ale przecież ma być jedynie demonstracją...

#include <GL/glut.h>    // Nagłówek do GLUT
//#include <GL/gl.h>         //Pozostałe nagłówki (nie konieczne gdyż zawarte już w GLUT)
//#include <GL/glu.h>
 
#include <stdio.h>        //Standardowa obsługa we/wy
 
//Główne okno
int window;
 
//Liczba klatek na sek. i aktualna
int fps=0,sfps=0;
 
//Przewijane napisu
char* txt[]={"      ABOUT","____________","","","Program ten","jest czescia","kursu","programowania","GLUT","(GL Utility Toolkit)","       by","Neuromancer","      2004","____________"};
#define txtcount 14//liczba pozycji w tekście
float starty=-1;         //startowa pozycja przewijanego text'u
 
//Inicjalizacja OpenGL
void InitGL(int Width, int Height)                // We call this right after our OpenGL window is created.
{
  glClearColor(1, 1, 1, 0.0f);                // This Will Clear The Background Color To Black
  glClearDepth(1.0);                                // Enables Clearing Of The Depth Buffer
  glDepthFunc(GL_LESS);                                // The Type Of Depth Test To Do
  glEnable(GL_DEPTH_TEST);                        // Enables Depth Testing
  glShadeModel(GL_FLAT);                        // Enables Smooth Color Shading
 
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();                                // Reset The Projection Matrix
 
  gluPerspective(45.0f,64/48,0.1f,500.0f);        // Calculate The Aspect Ratio Of The Window
 
  glMatrixMode(GL_MODELVIEW);
  glEnable(GL_COLOR_MATERIAL);
}
 
 
//Zmiana rozmiaru
void ReSizeGLScene(int Width, int Height)
{
  if (Height==0)                                // Prevent A Divide By Zero If The Window Is Too Small
    Height=1;
 
  glViewport(0, 0, Width, Height);                // Reset The Current Viewport And Perspective Transformation
 
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
 
  gluPerspective(45.0f,64/48,0.1f,500.0f);
  glMatrixMode(GL_MODELVIEW);
}
 
//Konwersja
char ascii[25];
FILE*f;
 
void itoa(int i)
{
 
 f=fopen("tmp.tmp","w");
  fprintf(f,"%i\n",i);
 fclose(f);
 
 f=fopen("tmp.tmp","r");
  fscanf(f,"%s\n",&ascii);
 fclose(f);
}
 
//Wartość bezwzględna
float abstract(float f)
{
 if (f>=0) return f; else return -f;
}
 
//Pisze czcionką bitmapową
float glutPrint(float x,float y,void *font,char *txt,float scale)
{ int i;
  int len=strlen(txt);
 for (i=0; i<len; i++)
 {
  glRasterPos2f(x,y);
  glutBitmapCharacter(font, txt[i]);
  x+=glutBitmapWidth(font,txt[i])*scale;
 }
}
 
//Główna funkcja rysująca
void DrawGLScene()
{
int i;
float y;
 
fps++;                //Zliczaj fps
 
glutSetWindow(window);
  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);        // Clear The Screen And The Depth Buffer
  glLoadIdentity();                                // Reset The View
  //OpenGL scene goes here///////////////////////////////////////
  glTranslatef(0,0,-2.5);
  glColor3f(0,0,0);
 
   //FPS
   itoa(sfps);
   strcat(ascii," fps");
   glutPrint(-0.8,-0.8,GLUT_BITMAP_9_BY_15,ascii,0.005);
 
   y=starty;
   for (i=0; i<txtcount; i++)
   {&nbsp;
    if (y<1) //Jeśli napis jest widoczny (w strefie 1>y>-1) to&nbsp;
    {
     glColor3f(0+abstract(y),0+abstract(y),0+abstract(y)); //Ustal kolor
     glutPrint(-0.4,y,GLUT_BITMAP_TIMES_ROMAN_24,txt[i],0.004);        //Napisz go
    }
    y-=0.3;                //PrzejdĽ niżej ("następny wiersz")
    if (y<-1) break;        //Jeśli już nic więcej nie widać to przerwij rysowanie
   }
 
   starty+=0.005;                //Przewijaj całość
   if (starty>6) starty=-1;        //Zresetuj po pewnym czasie
 
  ///////////////////////////////////////////////////////////////
  // swap the buffers to display, since double buffering is used.
  glutSwapBuffers();
}
 
//Funkcja wywoływana przez timer
void timerFunc(int i)
{
 sfps=fps;
 fps=0;
 //powtórz wywoływanie
 glutTimerFunc (1000,&timerFunc,0);    //Co sekundę wywołuje funkcję timerFunc
}
 
//Podstawowa funkcja każdego programu
int main(int argc, char **argv)
{
  glutInit(&argc, argv);        //Inicjalizacja GLUT
  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);        //Ustalenie trybu wyświetlania
 
  //Inicjalizacja i ustawienia dla okna renderingu
  glutInitWindowSize(640, 480);                //rozmiar
  glutInitWindowPosition(0, 0);         //położenie
  window = glutCreateWindow("GLUT TUTORIAL #6");//utworzenie okna
  glutDisplayFunc(&DrawGLScene);         //funkcja wyświetlania
  glutReshapeFunc(&ReSizeGLScene);        //zmiana rozmiaru
  InitGL(640, 480);                        //Inicjalizacja OpenGL
 
 
  glutTimerFunc (1000,&timerFunc,0);    //Co sekundę wywołuje funkcję timerFunc
 
  glutIdleFunc(&DrawGLScene);                //Funkcja wywołana w przypadku braku żadnych zdarzeń
 
 
  glutMainLoop();                        //Główna pętla
 
  glutDestroyWindow(window);                //Usunięcie okna
  return 1;
}



TRYB GRY


GLUT posiada coś takiego jak tryb gry (GAME MODE). Obsługują go funkcje:


void  glutGameModeString(const char *string);        //Ustala ciąg znaków game mode (?), prawdopodobnie parametry
int  glutEnterGameMode(void);                        //Włącza tryb game mode. Zwraca wartość int.
void  glutLeaveGameMode(void);                        //Wyłącza
int  glutGameModeGet(GLenum mode);                //Pobiera ustawienia trybu. Zwraca int. Możliwe wartości to:

GLUT_GAME_MODE_ACTIVE           0
GLUT_GAME_MODE_POSSIBLE         1
GLUT_GAME_MODE_WIDTH            2
GLUT_GAME_MODE_HEIGHT           3
GLUT_GAME_MODE_PIXEL_DEPTH      4
GLUT_GAME_MODE_REFRESH_RATE     5
GLUT_GAME_MODE_DISPLAY_CHANGED  6

Przyznam się szczerze, że nie wiem cóż ów tajemniczy tryb powoduje. Jest on innowacją.

INFORMACJE


GLUT zawiera tez funkcje pozwalajace nie tylko pobrac biezacy stan jego komponentow, ale takze rozszezenia systemu i inne.&nbsp;

Pierwszą tego typu funkcją jest:
int glutGet(GLenum type);&nbsp;
Jak widać zwraca wartość typu int, a w parametrze pobiera to czego wartość będzie zwracać. Możliwe wartości parametru:

//predefiniowana nazwa                wartość                zwraca
 GLUT_WINDOW_X                        100                x aktywnego okna
 GLUT_WINDOW_Y                        101                y aktywnego okna
 GLUT_WINDOW_WIDTH                102                szerokość -"-
 GLUT_WINDOW_HEIGHT                103                wysokość  -"-
 GLUT_WINDOW_BUFFER_SIZE        104                rozmiar bufora renderowania
 GLUT_WINDOW_STENCIL_SIZE        105                rozmiar bufora Stencil (patrz. OpenGl)
 GLUT_WINDOW_DEPTH_SIZE                106                rozmiar bufora głębi
 GLUT_WINDOW_RED_SIZE                107                rozmiary buforów poszczególnych kolorów (?)
 GLUT_WINDOW_GREEN_SIZE                108
 GLUT_WINDOW_BLUE_SIZE                109
 GLUT_WINDOW_ALPHA_SIZE                110
 GLUT_WINDOW_ACCUM_RED_SIZE        111
 GLUT_WINDOW_ACCUM_GREEN_SIZE        112
 GLUT_WINDOW_ACCUM_BLUE_SIZE        113
 GLUT_WINDOW_ACCUM_ALPHA_SIZE        114
 GLUT_WINDOW_DOUBLEBUFFER        115                rozmiar podwójnego bufora render
 GLUT_WINDOW_RGBA                116                rgba okna (?)
 GLUT_WINDOW_PARENT                117                rodzic bieżącego okna
 GLUT_WINDOW_NUM_CHILDREN        118                numer dziecka (?)
 GLUT_WINDOW_COLORMAP_SIZE        119                ?
 GLUT_WINDOW_NUM_SAMPLES        120                ?
 GLUT_WINDOW_STEREO                121                ?
 GLUT_WINDOW_CURSOR                122                bieżący kursor
 GLUT_SCREEN_WIDTH                200                szerokość ekranu
 GLUT_SCREEN_HEIGHT                201                wysokość ekranu
 GLUT_SCREEN_WIDTH_MM                202                ?
 GLUT_SCREEN_HEIGHT_MM                203                ?
 GLUT__NUM_ITEMS                300                ?
 GLUT_DISPLAY_MODE_POSSIBLE        400                możliwy tryb wyświetlania
 GLUT_INIT_WINDOW_X                500                zainicjowane x okna
 GLUT_INIT_WINDOW_Y                501                zainicjowane y okna
 GLUT_INIT_WINDOW_WIDTH                502                zainicjowana szerokość okna
 GLUT_INIT_WINDOW_HEIGHT        503                zainicjowana wysokość okna
 GLUT_INIT_DISPLAY_MODE                504                zainicjowany tryb wyświetlania okna
 GLUT_ELAPSED_TIME                700                czas jaki pozostał (?)
 GLUT_WINDOW_FORMAT_ID                123                format id okna (?)


Drugą funkcją jest:
int glutDeviceGet(GLenum type); //której działanie i wykorzystanie jest identyczne jak powyższej, a służy do pobrania informacji o urządzeniu.
Możliwe wartości parametru to:

//predefinowana wartość                wartość                zwraca
 GLUT_HAS_KEYBOARD                600                czy jest klawiatura
 GLUT_HAS_MOUSE                        601                -"- myszka
 GLUT_HAS_SPACEBALL                602                -"- spaceball (cokolwiek to jest ;) )
 GLUT_HAS_DIAL_AND_BUTTON_BOX        603                -"- button box
 GLUT_HAS_TABLET                604                -"- tablet
 GLUT_NUM_MOUSE_BUTTONS                605                ile mycha ma przycisków
 GLUT_NUM_SPACEBALL_BUTTONS        606                ile spaceball -"-
 GLUT_NUM_BUTTON_BOX_BUTTONS        607                ile button box -"-&nbsp;
 GLUT_NUM_DIALS                        608                ?
 GLUT_NUM_TABLET_BUTTONS        609                -"- tablet -"-
 GLUT_DEVICE_IGNORE_KEY_REPEAT  610                czy urządzenie ignoruje powtarzanie klawiszy
 GLUT_DEVICE_KEY_REPEAT         611                czy urządzenie nie ignoruje powtarzania klawiszy
 GLUT_HAS_JOYSTICK                612                czy jest joy&nbsp;
 GLUT_OWNS_JOYSTICK                613                ?
 GLUT_JOYSTICK_BUTTONS                614                info o przyciskach joy'a (?)
 GLUT_JOYSTICK_AXES                615                ?
 GLUT_JOYSTICK_POLL_RATE        616                ?


Do pobrania obsługiwanych rozszerzeń służy funkcja:

int glutExtensionSupported(const char *name);

w której rozszerzenia podajemy w parametrze jako ciągi znakowe.

Kolejną funkcją jest:

int glutGetModifiers(void);

która zwraca wartość typu int, będącą sumą logiczną następujących wartości:

//predefiniowana                wartość
 GLUT_ACTIVE_SHIFT               1
 GLUT_ACTIVE_CTRL                2
 GLUT_ACTIVE_ALT                 4

Dzięki tej funkcji, możemy pobrać w dowolnym momencie stan klawiszy specjalnych. Brak przykładziku jedynie z powodu oczywistości przedstawionych funkcji.

MAPY KOLORÓW


Do obsługi tego służą trzy funkcje:

glutCopyColormap
glutSetColor
glutGetColor


Funkcja&nbsp;
void glutCopyColormap (int win);
kopiuje mapę kolorów z okna podanego w paramerze (warstwy) do aktualnego.

Funkcja&nbsp;
void glutSetColor(int cell, GLfloat red, GLfloat green, GLfloat blue);
zmienia składowe koloru. Pierwszy parametr to index (typ int), kolejne trzy to już float, które są składowymi RGB (każda może mieć wartość od 0 do 1).

Przykładowy kod (do main):

int win1, win2;                                //Deklaracja okien
 
glutInitDisplayMode(GLUT_INDEX);        //Inicjalizacja trybu indexowania ISTOTNE ! aby pamiętać o jego ustaleniu
win1 = glutCreateWindow("first color index win");        //Utworzenie pierwszego okna
glutSetColor(0, 0.0, 0.0, 0.0); /* black */                //Modyfikacje kolorów z mapy kolorów z pierwszego okna
glutSetColor(1, 0.5, 0.5, 0.5); /* gray */
glutSetColor(2, 1.0, 1.0, 1.0); /* black */
glutSetColor(3, 1.0, 0.0, 0.0); /* red */
win2 = glutCreateWindow("second color index win");        //Utworzenie drugiego okna
glutCopyColormap(win1);                                        //Skopiowanie mapy kolorów dla drugiego okna

Ostatni funkcja służy (jak nietrudno się domyślić) służy do pobrania składowych danego koloru, z bieżącej mapy kolorów.
Jej deklaracja to:

GLfloat glutGetColor(int cell, int component);

jak widać zwraca ona wartość float, która jest właśnie wartością składowej. W parametrach podejmy index (liczony od zera) koloru, a następnie którą składową chcemy pobrać:
 GLUT_RED                //czerwona&nbsp;
 GLUT_GREEN                //zielona
 GLUT_BLUE                //niebieska

W przypadku przezroczystości koloru (lub innej modyfikacji) funkcja zwraca wartość -1.

WARSTWY


Czyli: wracamy do rozmów o cebuli ;).

Niestety jestem z nich marny. Zwyczajnie się na nich nie znam. Ale jak mus to mus.

OK. Pierwsza funkcja to:

glutEstablishOverlay();

nie przyjmuje parametrów i nic też nie zwraca. Służy do "ustalania" warstwowości dla okna (o ile to możliwe). Tryb wyświetlania ustalamy przez "initial display mode". Po wywołaniu funkcji pierwsza istniejąca warstwa jest usuwana, a pokazywana jest kolejna.

Funkcja:
glutRemoveOverlay(); //bez parametrów
służy do usuwania jednej warstwy z aktywnego okna.

Funkcja:
void glutUseLayer(GLenum layer);
ustawia tryb warstwowania dla okna.

Możliwe wartości parametru layer:
GLUT_NORMAL - normalny plan
GLUT_OVERLAY - kolejna warstwa

Funkcja:
void glutPostOverlayRedisplay(void);&nbsp;
ma działanie jak glutPostRedisplay, tyle, że odnosi się do warstw.

Do ukrywania i pokazywania warstw służą funkcje:

void glutShowOverlay(void);
void glutHideOverlay(void);

Funkcja:

void glutOverlayDisplayFunc(void (*func)(void));

jest typu callback i w parametrze podajemy funkcję, która będzie używana do wyświetlania sceny na warstwie (działanie jak w glutDisplayFunc).

Funkcje:

void glutPostOverlayRedisplay(void);
void glutPostWindowOverlayRedisplay(int win);

są już zupełnie oczywiste. Pierwsza powoduje niezależne od DisplayFunc wyświetlenie scenki. Druga robi to samo tyle, że w parametrze podajemy dla którego okna to zrobimy (warstwa bieżąca dla danego).

Do pobrania ustawień warst służy funkcja:

int glutLayerGet(int); //która jak widać ma w parametrze int, możliwe wartości to:

//Predefiniowana wartość znaczenie
GLUT_OVERLAY_POSSIBLE 800 //możliwe użycie warstw
GLUT_LAYER_IN_USE 801 //czy używane są warstwy
GLUT_HAS_OVERLAY 802 //czy są warstwy
GLUT_TRANSPARENT_INDEX 803 //index przezrczystości (?)
GLUT_NORMAL_DAMAGED 804 //?
GLUT_OVERLAY_DAMAGED 805 //?

i zwraca int'a.

Może i nie jest to wszystko zbyt zrozumiałe, ale może kod ułatwi zrozumienie:

Zmienne:
int overlaySupport; //Zmienna użyta do sprawdzenia obsługi warstw
int transparent, red, white; //Przezroczystość, czerwony, biały

Do main:
glutInitDisplayMode(GLUT_SINGLE | GLUT_INDEX); //Inicjalizacja wyświetlania<
overlaySupport = glutLayerGet(GLUT_OVERLAY_POSSIBLE); //Sprawdzenie czy warstwy są obsługiwane
if (overlaySupport) //Jeśli tak to
{
glutEstablishOverlay();&nbsp;
glutHideOverlay();
 
transparent = glutLayerGet(GLUT_TRANSPARENT_INDEX); //Pobranie index'u przezroczystości
glClearIndex(transparent);&nbsp;
red = (transparent + 1) % glutGet(GLUT_WINDOW_COLORMAP_SIZE);&nbsp;
white = (transparent + 2) % glutGet(GLUT_WINDOW_COLORMAP_SIZE);
glutSetColor(red, 1.0, 0.0, 0.0); /* Red. */
glutSetColor(white, 1.0, 1.0, 1.0); /* White. */
 
glutOverlayDisplayFunc(redrawOverlay); //Ustalenie funkcji wyświetlającej
glutReshapeFunc(reshape); //Ustalenie funkcji przy zmianie rozmiaru okna
} else //Jeśli warstwy nie chodzą to
{
printf("Sorry, no nifty overlay (try an SGI workstation)!\n"); //wyświetl komunikat
}


Funkcja zmiany rozmiaru okna:

void reshape(int w, int h)
{
if (overlaySupport) //Jeśli obsługiwane są warstwy
{
glutUseLayer(GLUT_OVERLAY); /* Setup overlay to have X style coordinate system. */
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, w, 0, h);
glScalef(1, -1, 1);
glTranslatef(0, -h, 0);
glMatrixMode(GL_MODELVIEW);
glutUseLayer(GLUT_NORMAL);
}
glViewport(0, 0, w, h);
}


UWAGA ! Niestety, u mnie wstawka do programu powyższego kodu, daje niemiły efekt:

"Sorry, no nifty overlay (try an SGI workstation)!"

więc (jak się pewnie domyśliłeś), żadna z powyższych funkcji nie była testowana i upewnienie się co do ich działania pozostaje w kompetencji czytającego :( .

VIDEO


Pierwszą omówioną funkcją z tej grupy jest:

int glutVideoResizeGet         ( GLenum param );

jak widać przyjumuje ona jeden parametr. Możliwe wartości dla parametru to:

// Predefiniowane:                wartość:         działanie:
 GLUT_VIDEO_RESIZE_POSSIBLE        900                //Parametr,przy którym funkcja zwraca 0 gdy zmiana vid. nie jest obsługiwana (i wtedy pozostałe parametry są bezużyteczne), lub 1 gdy jest obsługiwane

 GLUT_VIDEO_RESIZE_IN_USE        901                //Zwracają pozostałe informacje o vid.
 GLUT_VIDEO_RESIZE_X_DELTA        902
 GLUT_VIDEO_RESIZE_Y_DELTA        903
 GLUT_VIDEO_RESIZE_WIDTH_DELTA        904
 GLUT_VIDEO_RESIZE_HEIGHT_DELTA        905
 GLUT_VIDEO_RESIZE_X                906
 GLUT_VIDEO_RESIZE_Y                907
 GLUT_VIDEO_RESIZE_WIDTH        908
 GLUT_VIDEO_RESIZE_HEIGHT        909

 void  glutSetupVideoResizing(void);                //Uruchamia ustalanie rozmiaru vid.
 void  glutStopVideoResizing(void);                //Kończy owoż
 void  glutVideoResize(int x, int y, int width, int height);        //Zmienia rozmiar vid.
 void  glutVideoPan(int x, int y, int width, int height);        //?

Nie to, żeby mi się nie chciało, ale cóż, nie sądzę aby to było istotne, a nie czuję się najlepiej w tym temacie.

DODATKI


No i na koniec kilka uzupełniających całość funkcji:

glutSetCursor(2); //Funkcja pozwala na zmianę kursora mychy, w parametrze podajemy numer oznaczający jaki kursor z systemu (różne dla Windows'a, Linux'a, Mac'a)

Predefiniowane kursory:

//predefiniowane                wartość                wygląd
 GLUT_CURSOR_RIGHT_ARROW        0                strzałka w prawo
 GLUT_CURSOR_LEFT_ARROW                1                strzałka w lewo
 GLUT_CURSOR_INFO                2                informacja
 GLUT_CURSOR_DESTROY                3                zniszcz
 GLUT_CURSOR_HELP                4                pomoc
 GLUT_CURSOR_CYCLE                5                kółko
 GLUT_CURSOR_SPRAY                6                spray
 GLUT_CURSOR_WAIT                7                czekaj
 GLUT_CURSOR_TEXT                8                text
 GLUT_CURSOR_CROSSHAIR                9                krzyżyk
 GLUT_CURSOR_UP_DOWN                10                góra, dół //zmiana rozmiaru
 GLUT_CURSOR_LEFT_RIGHT                11                prawo, lewo  //zmiana rozmiaru
 GLUT_CURSOR_TOP_SIDE                12                góra  //zmiana rozmiaru
 GLUT_CURSOR_BOTTOM_SIDE        13                dół  //zmiana rozmiaru
 GLUT_CURSOR_LEFT_SIDE                14                lewo  //zmiana rozmiaru
 GLUT_CURSOR_RIGHT_SIDE                15                prawo  //zmiana rozmiaru
 GLUT_CURSOR_TOP_LEFT_CORNER        16                górny lewy róg  //zmiana rozmiaru
 GLUT_CURSOR_TOP_RIGHT_CORNER        17                górny prawy róg  //zmiana rozmiaru
 GLUT_CURSOR_BOTTOM_RIGHT_CORNER 18                dolny prawy róg  //zmiana rozmiaru
 GLUT_CURSOR_BOTTOM_LEFT_CORNER        19                dolny lewy róg  //zmiana rozmiaru
 GLUT_CURSOR_INHERIT                100                ?
 GLUT_CURSOR_NONE                101                brak kursora
 GLUT_CURSOR_FULL_CROSSHAIR        102                wypełniony krzyżyk


glutSetIconTitle("Napis na pasku");        //Pozwala na zmianę napisu na belce okna na pasku. Przyjmuje jeden parametr typu const char*


glutReportErrors();                        //GLUT wyświetla raporty o błędach (w oknie konsoli)


W GLUT istnieje funkcja:

void* glutGetProcAddress ( const char * procName );

której działanie jest identyczne jak funkcji:

glXGetProcAddress();        //Na systemie X-Window (Linux)
wglGetProcAddress();        //Na Windows-GL (Windows)

Służy ona do pobrania wskaĽnika (zwraca go) do adresu funkcji, której nazwę podajemy w parametrze.


Funkcja:

glutInitDisplayString

służu do ustawienia trybu wyświetlania przez string'a podanego w parametrze. Specyfikacja funkcji w C wygląda następująco:

void glutInitDisplayString(char *string);

Opis działania (kopia z dokumentacji):

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
The initial display mode description string is used when creating top-level windows, subwindows, and overlays to determine the OpenGL display mode for the to-be-created window or overlay.

The string is a list of zero or more capability descriptions separated by spaces and tabs. Each capability description
is a capability name that is optionally followed by a comparator and a numeric value. For example, "double"
and "depth>=12" are both valid criteria.

The capability descriptions are translated into a set of criteria used to select the appropriate frame buffer
configuration.


The criteria are matched in strict left to right order of precdence. That is, the first specified criteria (leftmost)
takes precedence over the later criteria for non-exact criteria (greater than, less than, etc. comparators). Exact
criteria (equal, not equal compartors) must match exactly so precedence is not relevant.



The numeric value is an integer that is parsed according to ANSI C's strtol(str, strptr,
0) behavior. This means that decimal, octal (leading 0), and hexidecimal values (leading 0x) are accepeted.



The valid compartors are:
[Dozwolonymi symbolami są:]&nbsp;


=


Equal. [równe]


!=


Not equal. [nie równe]


<


Less than and preferring larger difference (the least is best). [mniejsze]


>


Greater than and preferring larger differences (the most is best). [większe]


<=


Less than or equal and preferring larger difference (the least is best). [mniejsze lub równe]


>= [większe lub równe]


Greater than or equal and preferring more instead of less. This comparator is useful for allocating
resources like color precsion or depth buffer precision where the maximum precison is generally preferred.
Contrast with the tilde (~) comprator.

~

Greater than or equal but preferring less instead of more. This compartor is useful for allocating
resources such as stencil bits or auxillary color buffers where you would rather not over allocate. When
the compartor and numeric value are not specified, each capability name has a different default (one
default is to require a a compartor and numeric value).



The valid capability names are:
[Dozwolonymi typami nazw są:]

alpha


Alpha color buffer precision in bits. Default is ">=1".


acca


Red, green, blue, and alpha accumulation buffer precision in bits. Default is ">=1" for red,
green, blue, and alpha capabilities.


acc


Red, green, and green accumulation buffer precision in bits and zero bits of alpha accumulation buffer
precision. Default is ">=1" for red, green, and blue capabilities, and "~0" for the
alpha capability.


blue


Blue color buffer precision in bits. Default is ">=1".


buffer


Number of bits in the color index color buffer. Default is ">=1".


conformant


Boolean indicating if the frame buffer configuration is conformant or not. Conformance information is based
on GLX's EXT_visual_rating extension if supported. If the extension is not supported, all visuals are
assumed conformat. Default is "=1".


depth


Number of bits of precsion in the depth buffer. Default is ">=12".


double


Boolean indicating if the color buffer is double buffered. Default is "=1".


green


Green color buffer precision in bits. Default is ">=1".


index


Boolean if the color model is color index or not. True is color index. Default is ">=1".


num


A special capability name indicating where the value represents the Nth frame buffer configuration matching
the description string. When not specified, glutInitDisplayString also returns the first (best matching)
configuration. num requires a compartor and numeric value.


red


Red color buffer precision in bits. Default is ">=1".


rgba


Number of bits of red, green, blue, and alpha in the RGBA color buffer. Default is ">=1" for
red, green, blue, and alpha capabilities, and "=1" for the RGBA color model capability.


rgb


Number of bits of red, green, and blue in the RGBA color buffer and zero bits of alpha color buffer
precision. Default is ">=1" for the red, green, and blue capabilities, and "~0" for
alpha capability, and "=1" for the RGBA color model capability.


luminance



Number of bits of red in the RGBA and zero bits of green, blue (alpha not specified) of color buffer
precision. Default is ">=1" for the red capabilitis, and "=0" for the green and blue
capabilities, and "=1" for the RGBA color model capability, and, for X11, "=1" for the
StaticGray ("xstaticgray") capability.



SGI InfiniteReality (and other future machines) support a 16-bit luminance (single channel) display mode
(an additional 16-bit alpha channel can also be requested). The red channel maps to gray scale and green
and blue channels are not available. A 16-bit precision luminance display mode is often appropriate for
medical imaging applications. Do not expect many machines to support extended precision luminance display
modes.


stencil


Number of bits in the stencil buffer.


single


Boolean indicate the color buffer is single buffered. Double buffer capability "=1".


stereo


Boolean indicating the color buffer is supports OpenGL-style stereo. Default is "=1".


samples


Indicates the number of multisamples to use based on GLX's SGIS_multisample extension (for antialiasing).
Default is "<=4". This default means that a GLUT application can request multipsampling if
available by simply specifying "samples".


slow


Boolean indicating if the frame buffer configuration is slow or not. For the X11 implementation of GLUT,
slowness information is based on GLX's EXT_visual_rating extension if supported. If the EXT_visual_rating
extension is not supported, all visuals are assumed fast. For the Win32 implementation of GLUT, slowness is
based on if the underlying Pixel Format Descriptor (PFD) is marked "generic" and not
"accelerated". This implies that Microsoft's relatively slow software OpenGL implementation is
used by this PFD. Note that slowness is a relative designation relative to other frame buffer
configurations available. The intent of the slow capability is to help programs avoid frame buffer
configurations that are slower (but perhaps higher precision) for the current machine. Default is
">=0" if not comparator and numeric value are provided. This default means that slow visuals
are used in preference to fast visuals, but fast visuals will still be allowed.


win32pfd


Only recognized on GLUT implementations for Win32, this capability name matches the Win32 Pixel Format
Descriptor by numer. win32pfd requires a compartor and numeric value.


xvisual


Only recongized on GLUT implementations for the X Window System, this capability name matches the X visual
ID by number. xvisual requires a compartor and numeric value.


xstaticgray


Only recongized on GLUT implementations for the X Window System, boolean indicating if the frame buffer
configuration's X visual is of type StaticGray. Default is "=1".


xgrayscale


Only recongized on GLUT implementations for the X Window System, boolean indicating if the frame buffer
configuration's X visual is of type GrayScale. Default is "=1".


xstaticcolor


Only recongized on GLUT implementations for the X Window System, boolean indicating if the frame buffer
configuration's X visual is of type StaticColor. Default is "=1".


xpseudocolor


Only recongized on GLUT implementations for the X Window System, boolean indicating if the frame buffer
configuration's X visual is of type PsuedoColor. Default is "=1".


xtruecolor


Only recongized on GLUT implementations for the X Window System, boolean indicating if the frame buffer
configuration's X visual is of type TrueColor. Default is "=1".


xdirectcolor


Only recongized on GLUT implementations for the X Window System, boolean indicating if the frame buffer
configuration's X visual is of type DirectColor. Default is "=1".



Unspecifed capability descriptions will result in unspecified criteria being generated. These unspecified criteria help
glutInitDisplayString behave sensibly with terse display mode description strings. For example, if
no "slow" capability description is provided, fast frame buffer configurations will be choosen in preference
to slow frame buffer configurations, but slow frame buffer configurations will still be choosen if no better fast frame
buffer configuration is available.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


Przykładowe użycie:
glutInitDisplayString("stencil~2 rgb double depth>=16 samples");
//ustala okno w trybie RGBA, z głębią 16 lub więcej bitów, z czymś zwanym "mutlisampling" i 2 bitami na stencil buffer.



No to by było na tyle. Zdaje się, że opisałem (jako-tako) wszystkie istotne funkcje w wersji 3.7, więc jeśli traficie na jakieś inne to prawdopodobnie będą należały już do nowszych implementacji lub (co bardziej prawdopodobne) do innego wydania biblioteki GLUT. Standardowa formułka: czytajcie Ľródła i arty oraz piszcie ile się tylko da. W przypadku niejasności najlepiej (o ile na przeszkodzie nie stoi język) poszukać na stronach angielskojęzycznych, bo tam jest sporo materiałów, czego niestety nie można powiedzieć o polskiej sieci (mnie nie udało się znaleĽć żadnego opracowania tematu w naszym ojczystym języku, co nawiasem mówiąc było jednym z powodów napisania tego art'a).&nbsp;

Zdaję sobie sprawę, że w tekście jest dużo błędów i dlatego proszę o ocenę i "konstruktywne" uzupełnienia na mój e-mail.</p>
 
W temacie mam zamiar jeszcze napisać podsumowujący kod. Ale chwilowo są pewne problemy...

No i coś na co wszyscy niezadowoleni czekali:
wersja wejściowa tego art'a

12 komentarzy

Stogu 2007-07-07 16:50

Dodane formatowanie, menu, usunąłem większość niepotrzebnych odstępów itp, poprawiłem znaki. Od razu lepiej :P

neuromancer 2005-01-11 07:48

UWAGA !!!
jak by były problemy z uruchomieniem (freeglut) to usunąć
GLUT_ALPHA
z
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);

AklimX 2004-08-20 22:13

ciekawe czy oryginał też tak beznadziejnei wyglądał ;>

mcbury 2004-08-16 19:39

weś sformatuj to koles %*(%*$$%$ !

AklimX 2004-08-11 10:00

Masz to poprawić, bo beznadziejnie to wygląda. Wyrzuć chociaż te białe dziury

neuromancer 2004-08-10 20:15

Fakt. Formatowanie by się przydało.  Ale pisałem w gedit'cie i potem z odsyłaczami byłoby kupę roboty, chociaż może się postaram i poprawię :). Co do tego angielskiego to jeszcze pomyślę. A co do kodowania to... to nie wiem coo .. :)

kagn_danas 2004-08-10 11:37

podoba sie bardzo

Marooned 2004-08-10 04:38

i polskie literki poszły w las... - dodaj do tego jakiś spis treści (jako linki) i zdecyduj się na jeden język w artykule

xeryph 2004-08-09 21:57

nom :\ do formatowania mozna sie doczepic...
(duzo bialych miejsc)

WeeR 2004-08-09 20:35

Tak, tylko że połowa tekstu jest po angielsku ... mogłeś chociaż troche przetłumaczyć...

AklimX 2004-08-09 17:22

Napracowałeś się i to sporo. Moja uwaga: rozumiem, że chciałeś napisać czarno na białym, ale kto to będzie czytał (żadnych odnośników, spisu treści, tylko tekst i tekst przez ponad 80 stron)

neuromancer 2004-08-09 17:06

Mam nadzieję, że sie spodoba ...