Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?
Autor: Janusz Ganczarski
Biblioteki C++

Elementarne obiekty geometryczne

[lekcja] Rozdział 6. Prymitywy graficzne: punkty, linie, łamane, łamane zamknięte, trójkąty, wstęgi trójkątów, wachlarze trójkątów, czworokąty, wachlarze czworokątów, wielokąty, prostokąty; definiowane współrzędnych wierzchołków prymitywów; wielkość punktów; grubość i wzory linii, a ponadto trzy przykładowe programy.

Biblioteka OpenGL oferuje kilka podstawowych prymitywów graficznych, które słuza do modelowania dowolnych obiektów. Projektanci biblioteki celowo nie umiescili w niej bardziej skomplikowanych obiektów (wybrane powierzchnie 3D zawiera biblioteka GLU). Decyzja o stopniu złozonosci stosowanych obiektów została pozostawiona uzytkownikom i mozliwosciom konkretnych implementacji OpenGL.

Wybór rodzaju prymitywu

Definiowanie współrzednych wierzchołków figur podstawowych musi zawierac sie pomiedzy wywołaniami funkcji:

C/C++
void glBegin( GLenum mode )
void glEnd( void )

Parametr mode okresla rodzaj prymitywu, którego wierzchołki beda definiowane. Parametr przyjmuje jedna z ponizszych wartosci:
  • GL_POINTS - punkty: {p1}, {p2}, {p3}, {p4}, ...,
  • GL_LINES - odcinki: {p1, p2}, {p3, p4}, {p5, p6}, ...,
  • GL_LINE_STRIP - łamana: {p1, p2}, {p2, p3}, {p3, p4}, ...,
  • GL_LINE_LOOP - łamana zamknieta: {p1, p2}, {p2, p3}, {p3, p4}, ... {pn,p1},
  • GL_TRIANGLES - trójkaty: {p1, p2, p3}, {p4, p5, p6}, ...,
  • GL_TRIANGLE_STRIP - wstega trójkatów: {p1, p2, p3}, {p3, p2, p4}, {p3, p4, p5}, {p5, p4, p6}, ...,
  • GL_TRIANGLE_FAN - wachlarz trójkatów: {p1, p2, p3}, {p1, p3, p4}, {p1, p4, p5}, ...,
  • GL_QUADS - czworokaty,
  • GL_QUAD_STRIP - wstega czworokatów,
  • GL_POLYGON - wielokat.
Szczególne znaczenie w grafice 3D ma trójkat. Zasadnicza zaleta trójkąta jest jego ... płaskosc, co w geometrycznym ujeciu oznacza, ze trzy niewspółliniowe punkty wyznaczaja dokładnie jedna płaszczyzne w przestrzeni trójwymiarowej.
Przy budowie skomplikowanych obiektów 3D składajacych sie z trójkątów proporcjonalnie rosnie ilosc wierzchołków, czyli ilosc danych przetwarzanych przez procesor komputera i karty graficznej. Stad duze znaczenie ma mozliwosc definiowania wsteg (patrz rysunek 1) i wachlarzy trójkatów (rysunek 2). Prymitywy te bowiem umozliwiaja definiowanie kolejnych trójkątów tylko przy pomocy jednego wierzchołka. Oczywiscie nie w każdym przypadku bedzie mozliwe wykorzystanie wstegi lub wachlarza trójkatów, ale wykorzystywac te prymitywy zawsze, gdy jest to mozliwe.
Rysunek 1. Program Prymitywy graficzne - wstega trójkatów
Rysunek 1. Program Prymitywy graficzne - wstega trójkatów

Rysunek 2. Program Prymitywy graficzne - wachlarz trójkatów
Rysunek 2. Program Prymitywy graficzne - wachlarz trójkatów
Nieco bardziej skomplikowana grupa prymitywów graficznych obsługiwanych przez biblioteke OpenGL sa czworokaty i wstegi czworokatów (patrz rysunki 3 i 4). Zastosowanie tych prymitywów moze byc wygodne w wielu sytuacjach, ale trzeba liczyc sie z nastepujacymi ograniczeniami:
  • wierzchołki czworokata musza znajdowac sie w jednej płaszczyznie,
  • rysowanie czworokata zawierajacego samoprzeciecie krawedzi (czwarty czworokat na rysunku 3) moze byc nieprawidłowe w niektórych sytuacjach.

Ponadto nalezy dodac, ze wiele implementacji biblioteki OpenGL w procesie przetwarzania wierzchołków dzieli czworokaty na trójkaty, co takze może powodowac nieoczekiwane efekty.
Rysunek 3. Program Prymitywy graficzne - czworokąty
Rysunek 3. Program Prymitywy graficzne - czworokąty

Rysunek 4. Program Prymitywy graficzne - wstega czworokątów
Rysunek 4. Program Prymitywy graficzne - wstega czworokątów
Ostatnim prymitywem graficznym jest wielokat. Wielokaty podlegaja takim samym ograniczeniom jak czworokaty. Ich wierzchołki musza znajdowac sie w jednej płaszczyznie, a krawedzie nie powinny sie przecinac. Podobnie jak w przypadku czworokatów, wiele implementacji OpenGL dzieli wielokaty
na trójkaty, co moze byc zródłem niepozadanych efektów. Specyfikacja wskazuje ograniczona grupe funkcji biblioteki OpenGL, które moga byc wywoływane pomiedzy glBegin a glEnd. Naleza do nich następujące funkcje (lub grupy funkcji): glVertex, glColor, glSecondaryColor, glIndex, glNormal, glTexCoord, glMultiTexCoord, glVertexAttrib, glFogCoord, glArrayElement, glEvalCoord, glEvalPoint, glMaterial, glEdgeFlag, glCallList i glCallLists. Wywołanie funkcji spoza powyższej grupy spowoduje zgłoszenie błedu. Nie ma natomiast ograniczen co do wywoływania funkcji pochodzacych z innych bibliotek wykorzystywanych w programie.

Definiowanie współrzędnych wierzchołków figur

Współrzedne wierzchołków figur podstawowych standardowo definiuje sie przy pomocy funkcji z grupy glVertex. Co do zasady wierzchołki prymitywów graficznych opisywane sa w bibliotece OpenGL przy pomocy czterech współrzednych: (x, y, z,w). Poniewaz nie we wszystkich przypadkach konieczne jest stosowanie wszystkich współrzednych, OpenGL zawiera funkcje definiujace tylko trzy pierwsze współrzedne (wtedy wartosc współrzędnej w wynosi domyslnie 1) oraz funkcje definiujace dwie pierwsze współrzędne (wtedy wartosc współrzednej z wynosi domyslnie 0, a wartosc współrzędnej w wynosi 1).
Grupa glVertex obejmuje 24 funkcje, które mozna podzielic na 3 równoliczne podgrupy, kazda wymagajaca innej ilosci współrzednych. Parametrami funkcji z kazdej podgrup sa albo kolejne współrzedne wierzchołków, albo wskazniki na tablice zawierajace te współrzedne. Jak zapewne Czytelnik zauwazył, wiekszosc prymitywów wymaga scisle okreslonej ilosci wierzchołków. OpenGL w trakcie procesu rysowania prymitywu pomija te ostatnie wierzchołki, których ilosc nie pozwala na zbudowanie prymitywu.

Funkcje z grupy glVertex2

C/C++
void glVertex2d( GLdouble x, GLdouble y )
void glVertex2f( GLfloat x, GLfloat y )
void glVertex2i( GLint x, GLint y )
void glVertex2s( GLshort x, GLshort y )
void glVertex2dv( const GLdouble * v )
void glVertex2fv( const GLfloat * v )
void glVertex2iv( const GLint * v )
void glVertex2sv( const GLshort * v )

Funkcje z grupy glVertex3

C/C++
void glVertex3d( GLdouble x, GLdouble y, GLdouble z )
void glVertex3f( GLfloat x, GLfloat y, GLfloat z )
void glVertex3i( GLint x, GLint y, GLint z )
void glVertex3s( GLshort x, GLshort y, GLshort z )
void glVertex3dv( const GLdouble * v )
void glVertex3fv( const GLfloat * v )
void glVertex3iv( const GLint * v )
void glVertex3sv( const GLshort * v )

Funkcje z grupy glVertex4

C/C++
void glVertex4d( GLdouble x, GLdouble y, GLdouble z, GLdouble w )
void glVertex4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
void glVertex4i( GLint x, GLint y, GLint z, GLint w )
void glVertex4s( GLshort x, GLshort y, GLshort z, GLshort w )
void glVertex4dv( const GLdouble * v )
void glVertex4fv( const GLfloat * v )
void glVertex4iv( const GLint * v )
void glVertex4sv( const GLshort * v )

Prostokąty

Wspecjalny sposób potraktowano w bibliotece OpenGL prostokaty. Opracowana została bowiem oddzielna grupa funkcji glRect rysujacych prostokąt na podstawie współrzednych dwóch wierzchołków: lewego górnego i prawego dolnego. Prostokat rysowany jest na płaszczyznie o równaniu Z = 0, a jego boki sa równoległe do osi układu współrzednych. Stanowi to duze oczywiście ograniczenie, ale umozliwia jednoczesnie opracowanie szczególnie szybkiej implementacji rysowania prostokatów.
Podobnie jak funkcje z grupy glVertex, funkcje glRect dostepne sa w wersjach wymagajacych dwóch par współrzednych wierzchołków oraz pobierających wskaznik na tablice ze współrzednymi wierzchołków:
C/C++
void glRectd( GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2 )
void glRectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
void glRecti( GLint x1, GLint y1, GLint x2, GLint y2 )
void glRects( GLshort x1, GLshort y1, GLshort x2, GLshort y2 )
void glRectdv( const GLdouble * v1, const GLdouble * v2 )
void glRectfv( const GLfloat * v1, const GLfloat * v2 )
void glRectiv( const GLint * v1, const GLint * v2 )
void glRectsv( const GLshort * v1, const GLshort * v2 )

Punkty

Punkt w bibliotece OpenGL nie podlega efektom perspektywy i ma standardowo kształt kwadratu (piksela lub jego wielokrotnosci). Wielkosc rysowanych punktów okresla funkcja:
C/C++
void glPointSize( GLfloat size )
Parametr size okresla srednice punktu i jego wartosc musi byc wieksza od 0. Domyslnie wielkosc punktów wynosi 1 i jest to jedyna wielkosc, której obsługe wymaga specyfikacja OpenGL. Dopuszczalny zakres wielkosci punktu oraz krok z jakim wielkosc ta moze byc zmieniana zalezy od implementacji biblioteki OpenGL. Punkty o róznych rozmiarach przedstawia rysunek 5.

Rysunek 5. Program Punkty - punkty o róznych rozmiarach
Rysunek 5. Program Punkty - punkty o róznych rozmiarach

Linie

Podobnie jak w przypadku punktów biblioteka OpenGL umozliwia zmiane grubosci (szerokosci) rysowanych linii. Słuzy do tego funkcja:
C/C++
void glLineWidth( GLfloat width )
Parametr okresla grubosc linii i musi byc wiekszy od 0. Domyslnie grubosc linii wynosi 1. Dopuszczalny zakres grubosci linii oraz krok z jakim wielkość ta moze byc zmieniana zalezy od implementacji biblioteki OpenGL.
Rysunek 6. Program Linie - linie o róznych grubosciach i wzorach
Rysunek 6. Program Linie - linie o róznych grubosciach i wzorach
Poza gruboscia biblioteka OpenGL pozwala na okreslenie wzoru jakim bedzie rysowana linia (patrz rysunek 6). Umozliwia to funkcja:
C/C++
void glLineStipple( GLint factor, GLushort pattern )
której parametr pattern to 16-bitowa liczba całkowita zawierajaca wzór rysowanej linii, a factor okresla zwielokrotnienie bitów wzoru. Wartosc parametru factor jest ograniczona i w razie potrzeby obcinana do przedziału [1, 256], a wartosc poczatkowa wynosi 1. Poczatkowy wzór linii okresla stała FFFFh, która oznacza linie ciagła. Standardowo rysowanie linii ze wzorami jest wyłaczone. Właczenie tego mechanizmu wymaga wywołania funkcji glEnable z parametrem GL LINE - STIPPLE.

Programy przykładowe

Pierwszy przykładowy program (plik prymitywy graficzne.cpp) pozwala na przetestowanie wszystkich prymitywów graficznych dostępnych w bibliotece OpenGL. Szczególnie wazna jest mozliwosc bezposredniej oceny sposobu konstruowania takich prymitywów jak wstegi trójkatów i czworokatów. Program umozliwia zmiane rodzaju prymitywu bez usuwania współrzędnych wierzchołków poprzedniego prymitywu. Moze dac to czasami bardzo zaskakujace efekty. Do przechowywania współrzednych wierzchołków prymitywów zastosowano klase vector z biblioteki standardowej C++.
Nowym elementem biblioteki GLUT, który pojawił sie w pierwszym przykładowym programie jest wyswietlanie ciagów znaków w postaci numerów wierzchołków prymitywów. Realizuje to funkcja:
C/C++
void glutBitmapCharacter( void * font, int character )
której parametr font okresla rodzaj wyswietlanej czcionki bitmapowej, a character znak jaki ma zostac wyswietlony. Czcionki bitmapowe sa na stałe zapisane w bibliotece GLUT jako mapy bitowe. GLUT nie zawiera funkcji umozliwiajacych skorzystanie z czcionek bitmapowych zawartych w zewnetrznych plikach.
Biblioteka GLUT w wersji 3.x zawiera nastepujace czcionki bitmapowe:
  • GLUT BITMAP 8 BY 13 - typowa czcionka o wymiarach znaków 8 × 13 pikseli; znaki ASCII z przedziału [0, 255]; odpowiednik standardowej czcionki X Window o nazwie: -misc-fixed-medium-r-normal?13-120-75-75-C-80-iso8859-1,
  • GLUT BITMAP 9 BY 15 - typowa czcionka o wymiarach znaków 9 × 15 pikseli; znaki ASCII z przedziału [0, 255]; odpowiednik standardowej czcionki X Window o nazwie: -misc-fixed-medium-r-normal?15-140-75-75-C-90-iso8859-1
  • GLUT BITMAP TIMES ROMAN 10 - 10-punktowa czcionka proporcjonalna Times Roman; znaki ASCII z przedziałów: [32, 126] i [160, 255]; odpowiednik czcionki X Window o nazwie: -adobe-times-medium-r-normal?10-100-75-75-p-54-iso8859-1,
  • GLUT BITMAP TIMES ROMAN 24 - 24-punktowa czcionka proporcjonalna Times Roman; znaki ASCII z przedziałów: [32, 126] i [160, 255]; odpowiednik czcionki X Window o nazwie: -adobe-times-medium-r-normal?24-240-75-75-p-124-iso8859-1,
  • GLUT BITMAP HELVETICA 10 - 10-punktowa czcionka proporcjonalna Helvetica; znaki ASCII z przedziałów: [32, 126] i [160, 255]; odpowiednik czcionki X Window o nazwie: -adobe-helvetica-medium-r-normal?10-100-75-75-p-56-iso8859-1,
  • GLUT BITMAP HELVETICA 12 - 12-punktowa czcionka proporcjonalna Helvetica; znaki ASCII z przedziałów: [32, 126] i [160, 255]; odpowiednik czcionki X Window o nazwie: -adobe-helvetica-medium-r-normal?12-120-75-75-p-67-iso8859-1,
  • GLUT BITMAP HELVETICA 18 - 18-punktowa czcionka proporcjonalna Helvetica; znaki ASCII z przedziałów: [32, 126] i [160, 255]; odpowiednik czcionki X Window o nazwie: -adobe-helvetica-medium-r-normal?18-180-75-75-p-98-iso8859-1.
Jak Czytelnik juz zapewne zauwazył wszystkie czcionki zawieraja znaki ASCII kodowane w standardzie ISO 8859-1, czyli bez polskich liter. Niestety nie istnieje prosta metoda wyswietlenia czcionek zawierajacych polskie litery. W tym miejscu jedynie sygnalizujemy uzycie w programie nowej funkcji:
C/C++
void glRasterPos2i( GLint x, GLint y )
Funkcja ta, nalezaca do licznej grupy funkcji glRasterPos, okresla położenie wyswietlanej grafiki rastrowej - w tym przypadku liczby określającej numer wierzchołka prymitywu. Dokładny opis operacji na rastrach znajdzie sie w jednym z nastepnych odcinków kursu.
Drugi przykładowy program (plik punkty.cpp) prezentuje podstawowe mozliwosci rysowania punktów w bibliotece OpenGL. Rozmiar punktów reguluja przyciski ?+? (zwiekszenie) i ?-? (zmniejszenie). Rozmiar punktów oraz ich współrzedne przechowywane sa w obiektach klasy vector z biblioteki standardowej C++.
Trzeci przykładowy program (plik linie.cpp) prezentuje podstawowe mozliwosci rysowania linii w bibliotece OpenGL. Szerokosc rysowanej linii reguluja przyciski ?+? (zwiekszenie) i ?-? (zmniejszenie). Menu podręczne udostepnia kilka wzorów linii. Szerokosc i wzór linii oraz współrzedne ich poczatku i konca przechowywane sa w obiektach klasy vector z biblioteki standardowej C++.

Plik prymitywy graficzne.cpp

C/C++
/*
(c) Janusz Ganczarski
http://www.januszg.hg.pl
JanuszG(małpeczka)enter.net.pl
*/

#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>
#include <vector>

// stałe do obsługi menu podręcznego

enum
{
    RECTANGLES = GL_POLYGON + 100, // prostokąty
    CLEAR_VERTEX, // usuwanie wierzchołków
    EXIT // wyjście
};

// rodzaj rysowanego prymitywu graficznego

int primitive = GL_POINTS;

// współrzędne wierzchołków prymitywu

std::vector < GLint > vertex_x;
std::vector < GLint > vertex_y;

// funkcja generująca scenę 3D

void Display()
{
    // kolor tła - zawartość bufora koloru
    glClearColor( 1.0, 1.0, 1.0, 1.0 );
   
    // czyszczenie bufora koloru
    glClear( GL_COLOR_BUFFER_BIT );
   
    // wybór macierzy modelowania
    glMatrixMode( GL_MODELVIEW );
   
    // macierz modelowania = macierz jednostkowa
    glLoadIdentity();
   
    // kolor prymitywu
    glColor3f( 0.0, 1.0, 0.0 );
   
    // rysowanie prymitywu
    if( primitive == RECTANGLES )
    for( unsigned int i = 0; i + 1 < vertex_x.size(); i += 2 )
         glRecti( vertex_x[ i ], vertex_y[ i ], vertex_x[ i + 1 ], vertex_y[ i + 1 ] );
    else
         glBegin( primitive );
   
    for( unsigned int i = 0; i < vertex_x.size(); i++ )
         glVertex2i( vertex_x[ i ], vertex_y[ i ] );
   
    glEnd();
   
    // kolor krawędzi oraz wierzchołków prymitywów
    glColor3f( 0.0, 0.0, 0.0 );
   
    // krawędzie trójkątów
    if( primitive == GL_TRIANGLES )
    {
        glBegin( GL_LINES );
        unsigned int pos = 0;
        while( vertex_x.size() - pos >= 3 )
        {
            glVertex2i( vertex_x[ pos + 0 ], vertex_y[ pos + 0 ] );
            glVertex2i( vertex_x[ pos + 1 ], vertex_y[ pos + 1 ] );
            glVertex2i( vertex_x[ pos + 1 ], vertex_y[ pos + 1 ] );
            glVertex2i( vertex_x[ pos + 2 ], vertex_y[ pos + 2 ] );
            glVertex2i( vertex_x[ pos + 2 ], vertex_y[ pos + 2 ] );
            glVertex2i( vertex_x[ pos + 0 ], vertex_y[ pos + 0 ] );
            pos += 3;
        }
        glEnd();
    }
    else
   
    // krawędzie wstęgi trójkątów
    if( primitive == GL_TRIANGLE_STRIP )
    {
        glBegin( GL_LINES );
        // krawędzie pierwszego trójkąta wstęgi
        if( vertex_x.size() > 2 )
        {
            glVertex2i( vertex_x[ 0 ], vertex_y[ 0 ] );
            glVertex2i( vertex_x[ 1 ], vertex_y[ 1 ] );
            glVertex2i( vertex_x[ 1 ], vertex_y[ 1 ] );
            glVertex2i( vertex_x[ 2 ], vertex_y[ 2 ] );
            glVertex2i( vertex_x[ 2 ], vertex_y[ 2 ] );
            glVertex2i( vertex_x[ 0 ], vertex_y[ 0 ] );
        }
       
        // krawędzie kolejnych trójkątów wstęgi
        for( unsigned int i = 3; i < vertex_x.size(); i++ )
        {
            glVertex2i( vertex_x[ i ], vertex_y[ i ] );
            glVertex2i( vertex_x[ i - 1 ], vertex_y[ i - 1 ] );
            glVertex2i( vertex_x[ i ], vertex_y[ i ] );
            glVertex2i( vertex_x[ i - 2 ], vertex_y[ i - 2 ] );
        }
        glEnd();
    }
    else
   
    // krawędzie wachlarza trójkątów
    if( primitive == GL_TRIANGLE_FAN )
    {
        glBegin( GL_LINES );
        // krawędzie pierwszego trójkąta wachlarza
        if( vertex_x.size() > 2 )
        {
            glVertex2i( vertex_x[ 0 ], vertex_y[ 0 ] );
            glVertex2i( vertex_x[ 1 ], vertex_y[ 1 ] );
            glVertex2i( vertex_x[ 1 ], vertex_y[ 1 ] );
            glVertex2i( vertex_x[ 2 ], vertex_y[ 2 ] );
            glVertex2i( vertex_x[ 2 ], vertex_y[ 2 ] );
            glVertex2i( vertex_x[ 0 ], vertex_y[ 0 ] );
        }
       
        // krawędzie kolejnych trójkątów wachlarza
        for( unsigned int i = 3; i < vertex_x.size(); i++ )
        {
            glVertex2i( vertex_x[ 0 ], vertex_y[ 0 ] );
            glVertex2i( vertex_x[ i ], vertex_y[ i ] );
            glVertex2i( vertex_x[ i ], vertex_y[ i ] );
            glVertex2i( vertex_x[ i - 1 ], vertex_y[ i - 1 ] );
        }
        glEnd();
    }
    else
   
    // krawędzie czworokątów
    if( primitive == GL_QUADS )
    {
        glBegin( GL_LINES );
        unsigned int pos = 0;
        while( vertex_x.size() - pos >= 4 )
        {
            glVertex2i( vertex_x[ pos + 0 ], vertex_y[ pos + 0 ] );
            glVertex2i( vertex_x[ pos + 1 ], vertex_y[ pos + 1 ] );
            glVertex2i( vertex_x[ pos + 1 ], vertex_y[ pos + 1 ] );
            glVertex2i( vertex_x[ pos + 2 ], vertex_y[ pos + 2 ] );
            glVertex2i( vertex_x[ pos + 2 ], vertex_y[ pos + 2 ] );
            glVertex2i( vertex_x[ pos + 3 ], vertex_y[ pos + 3 ] );
            glVertex2i( vertex_x[ pos + 3 ], vertex_y[ pos + 3 ] );
            glVertex2i( vertex_x[ pos + 0 ], vertex_y[ pos + 0 ] );
            pos += 4;
        }
        glEnd();
    }
    else
   
    // wstęga czworokątów
    if( primitive == GL_QUAD_STRIP )
    {
        glBegin( GL_LINES );
        // krawędzie pierwszego czworokąta wstęgi
        if( vertex_x.size() > 3 )
        {
            glVertex2i( vertex_x[ 0 ], vertex_y[ 0 ] );
            glVertex2i( vertex_x[ 1 ], vertex_y[ 1 ] );
            glVertex2i( vertex_x[ 1 ], vertex_y[ 1 ] );
            glVertex2i( vertex_x[ 3 ], vertex_y[ 3 ] );
            glVertex2i( vertex_x[ 3 ], vertex_y[ 3 ] );
            glVertex2i( vertex_x[ 2 ], vertex_y[ 2 ] );
            glVertex2i( vertex_x[ 2 ], vertex_y[ 2 ] );
            glVertex2i( vertex_x[ 0 ], vertex_y[ 0 ] );
        }
       
        // krawędzie kolejnych czworokątów wstęgi
        for( unsigned int i = 4; i + 1 < vertex_x.size(); i += 2 )
        {
            glVertex2i( vertex_x[ i ], vertex_y[ i ] );
            glVertex2i( vertex_x[ i - 2 ], vertex_y[ i - 2 ] );
            glVertex2i( vertex_x[ i ], vertex_y[ i ] );
            glVertex2i( vertex_x[ i + 1 ], vertex_y[ i + 1 ] );
            glVertex2i( vertex_x[ i + 1 ], vertex_y[ i + 1 ] );
            glVertex2i( vertex_x[ i - 1 ], vertex_y[ i - 1 ] );
        }
        glEnd();
    }
    else
   
    // krawędzie wielokąta
    if( primitive == GL_POLYGON )
    {
        glBegin( GL_LINE_LOOP );
        for( unsigned int i = 0; i < vertex_x.size(); i++ )
             glVertex2i( vertex_x[ i ], vertex_y[ i ] );
       
        glEnd();
    }
    else
   
    // krawędzie prostokątów
    if( primitive == RECTANGLES )
    {
        glBegin( GL_LINES );
        for( unsigned int i = 0; i + 1 < vertex_x.size(); i += 2 )
        {
            glVertex2i( vertex_x[ i ], vertex_y[ i ] );
            glVertex2i( vertex_x[ i + 1 ], vertex_y[ i ] );
           
            glVertex2i( vertex_x[ i + 1 ], vertex_y[ i ] );
            glVertex2i( vertex_x[ i + 1 ], vertex_y[ i + 1 ] );
           
            glVertex2i( vertex_x[ i + 1 ], vertex_y[ i + 1 ] );
            glVertex2i( vertex_x[ i ], vertex_y[ i + 1 ] );
           
            glVertex2i( vertex_x[ i ], vertex_y[ i + 1 ] );
            glVertex2i( vertex_x[ i ], vertex_y[ i ] );
        }
        glEnd();
    }
   
    // wielkość wierzchołków prymitywów
    glPointSize( 3.0 );
   
    // rysowanie wierzchołków prymitywów
    glBegin( GL_POINTS );
    for( unsigned int i = 0; i < vertex_x.size(); i++ )
         glVertex2i( vertex_x[ i ], vertex_y[ i ] );
   
    glEnd();
   
    // rysowanie numerów wierzchołków prymitywów
    for( unsigned int i = 0; i < vertex_x.size(); i++ )
    {
        // położenie napisu
        glRasterPos2i( vertex_x[ i ] + 2, vertex_y[ i ] + 2 );
       
        // konwersja liczba -> ciąg znaków
        char str[ 10 ];
        sprintf( str, "%i", i + 1 );
       
        // długość napisu
        int len = strlen( str );
       
        // wyświetlenie kolejnych znaków (cyfr) napisu
        for( int i = 0; i < len; i++ )
             glutBitmapCharacter( GLUT_BITMAP_9_BY_15, str[ i ] );
       
    }
   
    // skierowanie poleceń do wykonania
    glFlush();
   
    // zamiana buforów koloru
    glutSwapBuffers();
}

// zmiana wielkości okna

void Reshape( int width, int height )
{
    // obszar renderingu - całe okno
    glViewport( 0, 0, width, height );
   
    // wybór macierzy rzutowania
    glMatrixMode( GL_PROJECTION );
   
    // macierz rzutowania = macierz jednostkowa
    glLoadIdentity();
   
    // rzutowanie prostokątne
    gluOrtho2D( 0, width, 0, height );
   
    // generowanie sceny 3D
    Display();
}

// obsługa przycisków myszki

void MouseButton( int button, int state, int x, int y )
{
    if( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN )
    {
        // zapamiętanie współrzędnych wierzchołka prymitywu
        vertex_x.insert( vertex_x.end(), x );
        vertex_y.insert( vertex_y.end(), glutGet( GLUT_WINDOW_HEIGHT ) - y );
        Display();
    }
}

// obsługa menu podręcznego

void Menu( int value )
{
    switch( value )
    {
        // punkty
    case GL_POINTS:
        primitive = GL_POINTS;
        glutSetWindowTitle( "Prymitywy graficzne - punkty (GL_POINTS)" );
        Display();
        break;
       
        // linie
    case GL_LINES:
        primitive = GL_LINES;
        glutSetWindowTitle( "Prymitywy graficzne - odcinki (GL_LINES)" );
        Display();
        break;
       
        // odcinki
    case GL_LINE_STRIP:
        primitive = GL_LINE_STRIP;
        #ifdef WIN32
       
        glutSetWindowTitle( "Prymitywy graficzne - łamana (GL_LINE_STRIP)" );
        #else
       
        glutSetWindowTitle( "Prymitywy graficzne - lamana (GL_LINE_STRIP)" );
        #endif
       
        Display();
        break;
       
        // łamana zamknięta
    case GL_LINE_LOOP:
        primitive = GL_LINE_LOOP;
        #ifdef WIN32
       
        glutSetWindowTitle( "Prymitywy graficzne - łamana zamknięta (GL_LINE_LOOP)" );
        #else
       
        glutSetWindowTitle( "Prymitywy graficzne - lamana zamknieta (GL_LINE_LOOP)" );
        #endif
       
        Display();
        break;
       
        // trójkąty
    case GL_TRIANGLES:
        primitive = GL_TRIANGLES;
        #ifdef WIN32
       
        glutSetWindowTitle( "Prymitywy graficzne - trójkąty (GL_TRIANGLES)" );
        #else
       
        glutSetWindowTitle( "Prymitywy graficzne - trojkaty (GL_TRIANGLES)" );
        #endif
       
        Display();
        break;
       
        // wstęga trójkątów
    case GL_TRIANGLE_STRIP:
        primitive = GL_TRIANGLE_STRIP;
        #ifdef WIN32
       
        glutSetWindowTitle( "Prymitywy graficzne - wstęga trójkątów (GL_TRIANGLE_STRIP)" );
        #else
       
        glutSetWindowTitle( "Prymitywy graficzne - wstega trojkatow (GL_TRIANGLE_STRIP)" );
        #endif
       
        Display();
        break;
       
        // wachlarz trójkątów
    case GL_TRIANGLE_FAN:
        primitive = GL_TRIANGLE_FAN;
        #ifdef WIN32
       
        glutSetWindowTitle( "Prymitywy graficzne - wachlarz trójkątów (GL_TRIANGLE_FAN)" );
        #else
       
        glutSetWindowTitle( "Prymitywy graficzne - wachlarz trojkatow (GL_TRIANGLE_FAN)" );
        #endif
       
        Display();
        break;
       
        // czworokąty
    case GL_QUADS:
        primitive = GL_QUADS;
        #ifdef WIN32
       
        glutSetWindowTitle( "Prymitywy graficzne - czworokąty (GL_QUADS)" );
        #else
       
        glutSetWindowTitle( "Prymitywy graficzne - czworokaty (GL_QUADS)" );
        #endif
       
        Display();
        break;
       
        // wstęga czworokątów
    case GL_QUAD_STRIP:
        primitive = GL_QUAD_STRIP;
        #ifdef WIN32
       
        glutSetWindowTitle( "Prymitywy graficzne - wstęga czworokątów (GL_QUAD_STRIP)" );
        #else
       
        glutSetWindowTitle( "Prymitywy graficzne - wstega czworokatow (GL_QUAD_STRIP)" );
        #endif
       
        Display();
        break;
       
        // wielokąt
    case GL_POLYGON:
        primitive = GL_POLYGON;
        #ifdef WIN32
       
        glutSetWindowTitle( "Prymitywy graficzne - wielokąt (GL_POLYGON)" );
        #else
       
        glutSetWindowTitle( "Prymitywy graficzne - wielokat (GL_POLYGON)" );
        #endif
       
        Display();
        break;
       
        // prostokąty
    case RECTANGLES:
        primitive = RECTANGLES;
        #ifdef WIN32
       
        glutSetWindowTitle( "Prymitywy graficzne - prostokąty" );
        #else
       
        glutSetWindowTitle( "Prymitywy graficzne - prostokaty" );
        #endif
       
        Display();
        break;
       
        // usuwanie wierzchołków
    case CLEAR_VERTEX:
        vertex_x.erase( vertex_x.begin(), vertex_x.end() );
        vertex_y.erase( vertex_y.begin(), vertex_y.end() );
        Display();
        break;
       
        // wyjście
    case EXIT:
        exit( 0 );
    }
}

int main( int argc, char * argv[] )
{
    // inicjalizacja biblioteki GLUT
    glutInit( & argc, argv );
   
    // inicjalizacja bufora ramki
    glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB );
   
    // rozmiary głównego okna programu
    glutInitWindowSize( 550, 500 );
   
    // utworzenie głównego okna programu
    glutCreateWindow( "Prymitywy graficzne - punkty (GL_POINTS)" );
   
    // dołączenie funkcji generującej scenę 3D
    glutDisplayFunc( Display );
   
    // dołączenie funkcji wywoływanej przy zmianie rozmiaru okna
    glutReshapeFunc( Reshape );
   
    // obsługa przycisków myszki
    glutMouseFunc( MouseButton );
   
    // utworzenie podmenu - Prymitywy
    int MenuPrimitive = glutCreateMenu( Menu );
    glutAddMenuEntry( "Punkty (GL_POINTS)", GL_POINTS );
    glutAddMenuEntry( "Odcinki (GL_LINES)", GL_LINES );
    #ifdef WIN32
   
    glutAddMenuEntry( "Łamana (GL_LINE_STRIP)", GL_LINE_STRIP );
    glutAddMenuEntry( "Łamana zamknięta (GL_LINE_LOOP)", GL_LINE_LOOP );
    glutAddMenuEntry( "Trójkąty (GL_TRIANGLES)", GL_TRIANGLES );
    glutAddMenuEntry( "Wstęga trójkątów (GL_TRIANGLE_STRIP)", GL_TRIANGLE_STRIP );
    glutAddMenuEntry( "Wachlarz trójkątów (GL_TRIANGLE_FAN)", GL_TRIANGLE_FAN );
    glutAddMenuEntry( "Czworokąty (GL_QUADS)", GL_QUADS );
    glutAddMenuEntry( "Wstęga czworokątów (GL_QUAD_STRIP)", GL_QUAD_STRIP );
    glutAddMenuEntry( "Wielokąt (GL_POLYGON)", GL_POLYGON );
    glutAddMenuEntry( "Prostokąty", RECTANGLES );
    #else
   
    glutAddMenuEntry( "Lamana (GL_LINE_STRIP)", GL_LINE_STRIP );
    glutAddMenuEntry( "Lamana zamknieta (GL_LINE_LOOP)", GL_LINE_LOOP );
    glutAddMenuEntry( "Trojkaty (GL_TRIANGLES)", GL_TRIANGLES );
    glutAddMenuEntry( "Wstega trójkatów (GL_TRIANGLE_STRIP)", GL_TRIANGLE_STRIP );
    glutAddMenuEntry( "Wachlarz trójkatow (GL_TRIANGLE_FAN)", GL_TRIANGLE_FAN );
    glutAddMenuEntry( "Czworokaty (GL_QUADS)", GL_QUADS );
    glutAddMenuEntry( "Wstega czworokatów (GL_QUAD_STRIP)", GL_QUAD_STRIP );
    glutAddMenuEntry( "Wielokat (GL_POLYGON)", GL_POLYGON );
    glutAddMenuEntry( "Prostokaty", RECTANGLES );
    #endif
   
    // menu główne
    glutCreateMenu( Menu );
    glutAddSubMenu( "Prymitywy", MenuPrimitive );
    #ifdef WIN32
   
    glutAddMenuEntry( "Usuń wierzchołki", CLEAR_VERTEX );
    glutAddMenuEntry( "Wyjście", EXIT );
    #else
   
    glutAddMenuEntry( "Usun wierzcholki", CLEAR_VERTEX );
    glutAddMenuEntry( "Wyjscie", EXIT );
    #endif
   
    // określenie przycisku myszki obsługującego menu podręczne
    glutAttachMenu( GLUT_RIGHT_BUTTON );
   
    // wprowadzenie programu do obsługi pętli komunikatów
    glutMainLoop();
    return 0;
}

Plik punkty.cpp


C/C++
/*
(c) Janusz Ganczarski
http://www.januszg.hg.pl
JanuszG(małpeczka)enter.net.pl
*/

#include <GL/glut.h>
#include <stdlib.h>
#include <vector>

// stałe do obsługi menu podręcznego

enum
{
    CLEAR_POINTS, // usuwanie punktów
    EXIT // wyjście
};

// współrzędne punktów

std::vector < GLint > vertex_x;
std::vector < GLint > vertex_y;

// rozmiary punktów

std::vector < GLfloat > points_size;

// początkowy rozmiar punktów

GLfloat point_size = 10.0;

// funkcja generująca scenę 3D

void Display()
{
    // kolor tła - zawartość bufora koloru
    glClearColor( 1.0, 1.0, 1.0, 1.0 );
   
    // czyszczenie bufora koloru
    glClear( GL_COLOR_BUFFER_BIT );
   
    // wybór macierzy modelowania
    glMatrixMode( GL_MODELVIEW );
   
    // macierz modelowania = macierz jednostkowa
    glLoadIdentity();
   
    // kolor punktów
    glColor3f( 1.0, 0.0, 0.0 );
   
    // rysowanie punktów
    for( unsigned int i = 0; i < vertex_x.size(); i++ )
    {
        // wielkość punktów
        glPointSize( points_size[ i ] );
        glBegin( GL_POINTS );
        glVertex2i( vertex_x[ i ], vertex_y[ i ] );
        glEnd();
    }
   
    // skierowanie poleceń do wykonania
    glFlush();
   
    // zamiana buforów koloru
    glutSwapBuffers();
}

// zmiana wielkości okna

void Reshape( int width, int height )
{
    // obszar renderingu - całe okno
    glViewport( 0, 0, width, height );
   
    // wybór macierzy rzutowania
    glMatrixMode( GL_PROJECTION );
   
    // macierz rzutowania = macierz jednostkowa
    glLoadIdentity();
   
    // rzutowanie prostokątne
    gluOrtho2D( 0, width, 0, height );
   
    // generowanie sceny 3D
    Display();
}

// obsługa przycisków myszki

void MouseButton( int button, int state, int x, int y )
{
    if( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN )
    {
        // zapamiętanie współrzędnych punktu
        vertex_x.insert( vertex_x.end(), x );
        vertex_y.insert( vertex_y.end(), glutGet( GLUT_WINDOW_HEIGHT ) - y );
       
        // zapamiętanie bieżącego rozmiaru punktu
        points_size.insert( points_size.end(), point_size );
       
        // narysowanie sceny
        Display();
    }
}

// obsługa klawiatury

void Keyboard( unsigned char key, int x, int y )
{
    // zwiększenie rozmiaru punktu
    if( key == '+' )
         point_size += 0.25;
    else
   
    // zmniejszenie rozmiaru punktu
    if( key == '-' && point_size > 0 )
         point_size -= 0.25;
   
    // narysowanie sceny
    Display();
}

// obsługa menu podręcznego

void Menu( int value )
{
    switch( value )
    {
        // usuwanie współrzędnych i rozmiarów punktów
    case CLEAR_POINTS:
        vertex_x.erase( vertex_x.begin(), vertex_x.end() );
        vertex_y.erase( vertex_y.begin(), vertex_y.end() );
        points_size.erase( points_size.begin(), points_size.end() );
        Display();
        break;
       
        // wyjście
    case EXIT:
        exit( 0 );
    }
}

int main( int argc, char * argv[] )
{
    // inicjalizacja biblioteki GLUT
    glutInit( & argc, argv );
   
    // inicjalizacja bufora ramki
    glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB );
   
    // rozmiary głównego okna programu
    glutInitWindowSize( 500, 500 );
   
    // utworzenie głównego okna programu
    glutCreateWindow( "Punkty" );
   
    // dołączenie funkcji generującej scenę 3D
    glutDisplayFunc( Display );
   
    // dołączenie funkcji wywoływanej przy zmianie rozmiaru okna
    glutReshapeFunc( Reshape );
   
    // obsługa przycisków myszki
    glutMouseFunc( MouseButton );
   
    // dołączenie funkcji obsługi klawiatury
    glutKeyboardFunc( Keyboard );
   
    // menu główne
    glutCreateMenu( Menu );
    #ifdef WIN32
   
    glutAddMenuEntry( "Usuń punkty", CLEAR_POINTS );
    glutAddMenuEntry( "Wyjście", EXIT );
    #else
   
    glutAddMenuEntry( "Usun punkty", CLEAR_POINTS );
    glutAddMenuEntry( "Wyjscie", EXIT );
    #endif
   
    // określenie przycisku myszki obsługującego menu podręczne
    glutAttachMenu( GLUT_RIGHT_BUTTON );
   
    // wprowadzenie programu do obsługi pętli komunikatów
    glutMainLoop();
    return 0;
}

Plik linie.cpp

C/C++
/*
(c) Janusz Ganczarski
http://www.januszg.hg.pl
JanuszG(małpeczka)enter.net.pl
*/

#include <GL/glut.h>
#include <stdlib.h>
#include <vector>

// stałe do obsługi menu podręcznego

enum
{
    STIPPLE_1111111111111111, // wzór linii 1111111111111111
    STIPPLE_0000000011111111, // wzór linii 0000000011111111
    STIPPLE_1111111100000000, // wzór linii 1111111100000000
    STIPPLE_0000111100001111, // wzór linii 0000111100001111
    STIPPLE_1111000011110000, // wzór linii 1111000011110000
    STIPPLE_0011001100110011, // wzór linii 0011001100110011
    STIPPLE_1100110011001100, // wzór linii 1100110011001100
    CLEAR_LINES, // usuwanie linii
    EXIT // wyjście
};

// współrzędne końców linii

std::vector < GLint > vertex_x;
std::vector < GLint > vertex_y;

// szerokości linii

std::vector < GLfloat > lines_width;

// początkowa szerokość linii

GLfloat line_width = 10.0;

// wzory linii

std::vector < GLfloat > lines_stipple;

// początkowy wzór rysowanej linii

GLushort line_stipple = 0xFFFF;

// wskaźnik naciśnięcia lewego przycisku myszki

int button_state = GLUT_UP;

// funkcja generująca scenę 3D

void Display()
{
    // kolor tła - zawartość bufora koloru
    glClearColor( 1.0, 1.0, 1.0, 1.0 );
   
    // czyszczenie bufora koloru
    glClear( GL_COLOR_BUFFER_BIT );
   
    // wybór macierzy modelowania
    glMatrixMode( GL_MODELVIEW );
   
    // macierz modelowania = macierz jednostkowa
    glLoadIdentity();
   
    // kolor linii
    glColor3f( 1.0, 0.0, 0.0 );
   
    // włączenie rysowania wzorów linii
    glEnable( GL_LINE_STIPPLE );
   
    // rysowanie linii
    for( unsigned int i = 0; i < vertex_x.size(); i += 2 )
    {
        // szerokość linii
        glLineWidth( lines_width[ i / 2 ] );
       
        // wzór rysowanej linii
        glLineStipple( 1, lines_stipple[ i / 2 ] );
       
        // rysowanie pojedynczej linii
        glBegin( GL_LINES );
        glVertex2i( vertex_x[ i ], vertex_y[ i ] );
        glVertex2i( vertex_x[ i + 1 ], vertex_y[ i + 1 ] );
        glEnd();
    }
   
    // wyłączenie rysowania wzorów linii
    glDisable( GL_LINE_STIPPLE );
   
    // skierowanie poleceń do wykonania
    glFlush();
   
    // zamiana buforów koloru
    glutSwapBuffers();
}

// zmiana wielkości okna

void Reshape( int width, int height )
{
    // obszar renderingu - całe okno
    glViewport( 0, 0, width, height );
   
    // wybór macierzy rzutowania
    glMatrixMode( GL_PROJECTION );
   
    // macierz rzutowania = macierz jednostkowa
    glLoadIdentity();
   
    // rzutowanie prostokątne
    gluOrtho2D( 0, width, 0, height );
   
    // generowanie sceny 3D
    Display();
}

// obsługa przycisków myszki

void MouseButton( int button, int state, int x, int y )
{
    if( button == GLUT_LEFT_BUTTON )
    {
        // początek rysowania linii
        if( state == GLUT_DOWN && button_state == GLUT_UP )
        {
            // zapamiętanie współrzędnych początku i końca linii
            vertex_x.insert( vertex_x.end(), x );
            vertex_y.insert( vertex_y.end(), glutGet( GLUT_WINDOW_HEIGHT ) - y );
            vertex_x.insert( vertex_x.end(), x );
            vertex_y.insert( vertex_y.end(), glutGet( GLUT_WINDOW_HEIGHT ) - y );
           
            // zapamiętanie bieżącej szerokości linii
            lines_width.insert( lines_width.end(), line_width );
           
            // zapamiętanie bieżącego wzoru linii
            lines_stipple.insert( lines_stipple.end(), line_stipple );
           
            // zmiana wartości wskaźnika
            button_state = GLUT_DOWN;
           
            // narysowanie sceny
            Display();
        }
        else
       
        // zakończenie rysowania linii
        if( state == GLUT_UP && button_state == GLUT_DOWN )
        {
            vertex_x[ vertex_x.size() - 1 ] = x;
            vertex_y[ vertex_y.size() - 1 ] = glutGet( GLUT_WINDOW_HEIGHT ) - y;
           
            // zmiana wartości wskaźnika
            button_state = GLUT_UP;
           
            // narysowanie sceny
            Display();
        }
    }
}

// obsługa ruchu kursora myszki

void MouseMotion( int x, int y )
{
    // zmiana końca położenia linii
    if( button_state == GLUT_DOWN )
    {
        // zmiana współrzędnych końca linii
        vertex_x[ vertex_x.size() - 1 ] = x;
        vertex_y[ vertex_y.size() - 1 ] = glutGet( GLUT_WINDOW_HEIGHT ) - y;
       
        // narysowanie sceny
        Display();
    }
}

// obsługa klawiatury

void Keyboard( unsigned char key, int x, int y )
{
    // zwiększenie szerokości linii
    if( key == '+' )
         line_width += 0.25;
    else
   
    // zmniejszenie szerokości linii
    if( key == '-' && line_width > 0 )
         line_width -= 0.25;
   
    // narysowanie sceny
    Display();
}

// obsługa menu podręcznego

void Menu( int value )
{
    switch( value )
    {
        // wzór linii 1111111111111111
    case STIPPLE_1111111111111111:
        line_stipple = 0xFFFF;
        Display();
        break;
       
        // wzór linii 0000000011111111
    case STIPPLE_0000000011111111:
        line_stipple = 0x00FF;
        Display();
        break;
       
        // wzór linii 1111111100000000
    case STIPPLE_1111111100000000:
        line_stipple = 0xFF00;
        Display();
        break;
       
        // wzór linii 0000111100001111
    case STIPPLE_0000111100001111:
        line_stipple = 0x0F0F;
        Display();
        break;
       
        // wzór linii 1111000011110000
    case STIPPLE_1111000011110000:
        line_stipple = 0xF0F0;
        Display();
        break;
       
        // wzór linii 0011001100110011
    case STIPPLE_0011001100110011:
        line_stipple = 0x3333;
        Display();
        break;
       
        // wzór linii 1100110011001100
    case STIPPLE_1100110011001100:
        line_stipple = 0xCCCC;
        Display();
        break;
       
        // usuwanie linii
    case CLEAR_LINES:
        vertex_x.erase( vertex_x.begin(), vertex_x.end() );
        vertex_y.erase( vertex_y.begin(), vertex_y.end() );
        lines_width.erase( lines_width.begin(), lines_width.end() );
        lines_stipple.erase( lines_stipple.begin(), lines_stipple.end() );
        Display();
        break;
       
        // wyjście
    case EXIT:
        exit( 0 );
    }
}

int main( int argc, char * argv[] )
{
    // inicjalizacja biblioteki GLUT
    glutInit( & argc, argv );
   
    // inicjalizacja bufora ramki
    glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB );
   
    // rozmiary głównego okna programu
    glutInitWindowSize( 500, 500 );
   
    // utworzenie głównego okna programu
    glutCreateWindow( "Linie" );
   
    // dołączenie funkcji generującej scenę 3D
    glutDisplayFunc( Display );
   
    // dołączenie funkcji wywoływanej przy zmianie rozmiaru okna
    glutReshapeFunc( Reshape );
   
    // obsługa przycisków myszki
    glutMouseFunc( MouseButton );
   
    // obsługa ruchu kursora myszki
    glutMotionFunc( MouseMotion );
   
    // dołączenie funkcji obsługi klawiatury
    glutKeyboardFunc( Keyboard );
   
    // utworzenie podmenu - Prymitywy
    int MenuStipple = glutCreateMenu( Menu );
    glutAddMenuEntry( "1111111111111111", STIPPLE_1111111111111111 );
    glutAddMenuEntry( "0000000011111111", STIPPLE_0000000011111111 );
    glutAddMenuEntry( "1111111100000000", STIPPLE_1111111100000000 );
    glutAddMenuEntry( "0000111100001111", STIPPLE_0000111100001111 );
    glutAddMenuEntry( "1111000011110000", STIPPLE_1111000011110000 );
    glutAddMenuEntry( "0011001100110011", STIPPLE_0011001100110011 );
    glutAddMenuEntry( "1100110011001100", STIPPLE_1100110011001100 );
   
    // menu główne
    glutCreateMenu( Menu );
    #ifdef WIN32
   
    glutAddSubMenu( "Wzór linii", MenuStipple );
    glutAddMenuEntry( "Usuń linie", CLEAR_LINES );
    glutAddMenuEntry( "Wyjście", EXIT );
    #else
   
    glutAddSubMenu( "Wzor linii", MenuStipple );
    glutAddMenuEntry( "Usun linie", CLEAR_LINES );
    glutAddMenuEntry( "Wyjscie", EXIT );
    #endif
   
    // określenie przycisku myszki obsługującego menu podręczne
    glutAttachMenu( GLUT_RIGHT_BUTTON );
   
    // wprowadzenie programu do obsługi pętli komunikatów
    glutMainLoop();
    return 0;
}
Poprzedni dokument Następny dokument
Okrawanie i obcinanie Wielokąty