#include <GL/glut.h>
#include <stdlib.h>
// stałe do obsługi menu podręcznego
enum
{
FULL_WINDOW, // aspekt obrazu - całe okno
ASPECT_1_1, // aspekt obrazu 1:1
WIRE_SPHERE, // kula
WIRE_CONE, // stożek
WIRE_CUBE, // sześcian
WIRE_TORUS, // torus
WIRE_DODECAHEDRON, // dwunastościan
WIRE_TEAPOT, // czajnik
WIRE_OCTAHEDRON, // ośmiościan
WIRE_TETRAHEDRON, // czworościan
WIRE_ICOSAHEDRON, // dwudziestościan
EXIT // wyjście
};
// aspekt obrazu
int aspect = ASPECT_1_1;
// rodzaj obiektu
int object = WIRE_SPHERE;
// rozmiary bryły obcinania
const GLdouble left = -40.0;
const GLdouble right = 40.0;
const GLdouble bottom = -70.0;
const GLdouble top = 70.0;
const GLdouble Near = 200.0;
const GLdouble Far = 70.0;
// współczynnik skalowania
GLfloat scale = 1.0;
// kąty obrotu
GLfloat rotatex = 0.0;
GLfloat rotatey = 0.0;
// przesunięcie
GLfloat translatex = 0.0;
GLfloat translatey = 0.0;
// wskaźnik naciśnięcia lewego przycisku myszki
int button_state = GLUT_UP;
// położenie kursora myszki
int button_x, button_y;
// funkcja generująca scenę 3D
void DrawCube(int x, int y, int z, int c)
{
glTranslatef(x, y, z);
glColor3f(0.0f, 0.0f, c);
glutSolidCube(1);
glTranslatef(-x, -y, -z);
}
void DrawWireCube(int x, int y, int z, int c)
{
glTranslatef(x, y, z);
glColor3f(0.0f, c, 0.0f);
glutWireCube(1);
glTranslatef(-x, -y, -z);
}
int tab[20][20] =
{
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,1,0,0,0,0,0,0,1,0,0,0,1,1,1,1,0,0,1,0 },
{ 0,1,1,1,1,1,1,1,1,0,0,0,1,0,0,1,0,0,1,0 },
{ 0,1,0,0,0,1,0,1,0,0,0,0,1,0,0,1,0,0,1,0 },
{ 0,1,0,0,0,1,0,1,0,0,0,0,1,0,0,1,0,0,1,0 },
{ 0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0 },
{ 0,1,0,1,0,1,0,1,0,0,0,0,1,0,0,1,0,0,1,0 },
{ 0,1,0,1,0,1,0,1,0,0,0,0,1,0,0,1,0,0,1,0 },
{ 0,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0 },
{ 0,1,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,1,0 },
{ 0,1,1,1,1,0,0,1,0,0,0,0,1,0,0,1,0,0,1,0 },
{ 0,0,0,0,1,0,0,1,0,0,0,0,1,0,1,1,0,0,1,0 },
{ 0,0,0,0,1,0,0,1,0,0,0,0,1,0,1,0,0,0,1,0 },
{ 0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,1,0 },
{ 0,1,0,1,0,0,0,0,1,0,0,0,0,0,1,1,1,1,1,0 },
{ 0,1,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0 },
{ 0,1,0,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0 },
{ 0,1,1,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
};
void DrawBoard()
{
for (int i = -10; i < 10; ++i)
{
for (int j = -10; j < 10; ++j)
{
if (tab[i + 10][j + 10] == 0)
{
DrawCube(i, j, 0, 1);
DrawWireCube(i, j, 0, 1);
}
else
{
DrawCube(i, j, 0, 0);
}
}
}
for (int i = -10; i < 10; ++i)
{
for (int j = -10; j < 10; ++j)
{
if (tab[i + 10][j + 10] == 0)
{
DrawCube(i, j, 1, 1);
DrawWireCube(i, j, 1, 1);
}
}
}
for (int i = -10; i < 10; ++i)
{
for (int j = -10; j < 10; ++j)
{
if (tab[i + 10][j + 10] == 0)
{
DrawCube(i, j, 2, 1);
DrawWireCube(i, j, 2, 1);
}
}
}
}
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();
// przesunięcie układu współrzędnych obiektu do środka bryły odcinania
glTranslatef(0, 0, -(Near + Far) / 2);
// przesunięcie obiektu - ruch myszką
glTranslatef(translatex, translatey, 0.0);
// skalowanie obiektu - klawisze "+" i "-"
glScalef(scale, scale, scale);
// obroty obiektu - klawisze kursora
glRotatef(rotatex, 1.0, 0, 0);
glRotatef(rotatey, 0, 1.0, 0);
DrawBoard();
// 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();
// parametry bryły obcinania
if (aspect == ASPECT_1_1)
{
// wysokość okna większa od wysokości okna
if (width < height && width > 0)
glFrustum(left, right, bottom * height / width, top * height / width, Near, Far);
else
// szerokość okna większa lub równa wysokości okna
if (width >= height && height > 0)
glFrustum(left * width / height, right * width / height, bottom, top, Near, Far);
}
else
glFrustum(left, right, bottom, top, Near, Far);
// generowanie sceny 3D
Display();
}
// obsługa klawiatury
void Keyboard(unsigned char key, int x, int y)
{
// klawisz +
if (key == '+')
scale += 0.1;
else
// klawisz -
if (key == '-' && scale > 0.1)
scale -= 0.1;
// odrysowanie okna
Reshape(glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
}
// obsługa klawiszy funkcyjnych i klawiszy kursora
void SpecialKeys(int key, int x, int y)
{
switch (key)
{
// kursor w lewo
case GLUT_KEY_LEFT:
rotatey -= 1;
break;
// kursor w górę
case GLUT_KEY_UP:
rotatex -= 1;
break;
// kursor w prawo
case GLUT_KEY_RIGHT:
rotatey += 1;
break;
// kursor w dół
case GLUT_KEY_DOWN:
rotatex += 1;
break;
}
// odrysowanie okna
Reshape(glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
}
// obsługa przycisków myszki
void MouseButton(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON)
{
// zapamiętanie stanu lewego przycisku myszki
button_state = state;
// zapamiętanie położenia kursora myszki
if (state == GLUT_DOWN)
{
button_x = x;
button_y = y;
}
}
}
// obsługa ruchu kursora myszki
void MouseMotion(int x, int y)
{
if (button_state == GLUT_DOWN)
{
translatex += 1.1 *(right - left) / glutGet(GLUT_WINDOW_WIDTH) *(x - button_x);
button_x = x;
translatey += 1.1 *(top - bottom) / glutGet(GLUT_WINDOW_HEIGHT) *(button_y - y);
button_y = y;
glutPostRedisplay();
}
}
// obsługa menu podręcznego
void Menu(int value)
{
switch (value)
{
// obszar renderingu - całe okno
case FULL_WINDOW:
aspect = FULL_WINDOW;
Reshape(glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
break;
// obszar renderingu - aspekt 1:1
case ASPECT_1_1:
aspect = ASPECT_1_1;
Reshape(glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
break;
// kula
case WIRE_SPHERE:
object = WIRE_SPHERE;
Display();
break;
// cylinder
case WIRE_CONE:
object = WIRE_CONE;
Display();
break;
// sześcian
case WIRE_CUBE:
object = WIRE_CUBE;
Display();
break;
// torus
case WIRE_TORUS:
object = WIRE_TORUS;
Display();
break;
// dwunastościan
case WIRE_DODECAHEDRON:
object = WIRE_DODECAHEDRON;
Display();
break;
// czajnik
case WIRE_TEAPOT:
object = WIRE_TEAPOT;
Display();
break;
// ośmiościan
case WIRE_OCTAHEDRON:
object = WIRE_OCTAHEDRON;
Display();
break;
// czworościan
case WIRE_TETRAHEDRON:
object = WIRE_TETRAHEDRON;
Display();
break;
// dwudziestościan
case WIRE_ICOSAHEDRON:
object = WIRE_ICOSAHEDRON;
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(400, 400);
// utworzenie głównego okna programu
#ifdef WIN32
glutCreateWindow("Przekształcenia");
#else
glutCreateWindow("Przeksztalcenia");
#endif
// dołączenie funkcji generującej scenę 3D
glutDisplayFunc(Display);
// dołączenie funkcji wywoływanej przy zmianie rozmiaru okna
glutReshapeFunc(Reshape);
// dołączenie funkcji obsługi klawiatury
glutKeyboardFunc(Keyboard);
// dołączenie funkcji obsługi klawiszy funkcyjnych i klawiszy kursora
glutSpecialFunc(SpecialKeys);
// obsługa przycisków myszki
glutMouseFunc(MouseButton);
// obsługa ruchu kursora myszki
glutMotionFunc(MouseMotion);
// utworzenie podmenu - aspekt obrazu
int MenuAspect = glutCreateMenu(Menu);
#ifdef WIN32
glutAddMenuEntry("Aspekt obrazu - całe okno", FULL_WINDOW);
#else
glutAddMenuEntry("Aspekt obrazu - cale okno", FULL_WINDOW);
#endif
glutAddMenuEntry("Aspekt obrazu 1:1", ASPECT_1_1);
// utworzenie podmenu - obiekt
int MenuObject = glutCreateMenu(Menu);
glutAddMenuEntry("Kula", WIRE_SPHERE);
#ifdef WIN32
glutAddMenuEntry("Stożek", WIRE_CONE);
glutAddMenuEntry("Sześcian", WIRE_CUBE);
glutAddMenuEntry("Torus", WIRE_TORUS);
glutAddMenuEntry("Dwunastościan", WIRE_DODECAHEDRON);
glutAddMenuEntry("Czajnik", WIRE_TEAPOT);
glutAddMenuEntry("Ośmiościan", WIRE_OCTAHEDRON);
glutAddMenuEntry("Czworościan", WIRE_TETRAHEDRON);
glutAddMenuEntry("Dwudziestościan", WIRE_ICOSAHEDRON);
#else
glutAddMenuEntry("Stozek", WIRE_CONE);
glutAddMenuEntry("Szescian", WIRE_CUBE);
glutAddMenuEntry("Torus", WIRE_TORUS);
glutAddMenuEntry("Dwunastoscian", WIRE_DODECAHEDRON);
glutAddMenuEntry("Czajnik", WIRE_TEAPOT);
glutAddMenuEntry("Osmioscian", WIRE_OCTAHEDRON);
glutAddMenuEntry("Czworoscian", WIRE_TETRAHEDRON);
glutAddMenuEntry("Dwudziestoscian", WIRE_ICOSAHEDRON);
#endif
// menu główne
glutCreateMenu(Menu);
glutAddSubMenu("Aspekt obrazu", MenuAspect);
glutAddSubMenu("Obiekt", MenuObject);
#ifdef WIN32
glutAddMenuEntry("Wyjście", EXIT);
#else
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;
}
Mam tu program w OpenGL (starym) który generuje labirynt. Klikając myszką na labirynt można go przesuwać. Naciskając na klawiaturze "+" i "-" można go przybliżać i oddalać, a naciskając strzałki w lewo i prawo można go obracać. Obróćcie teraz labirynt do takiego położenia jak jest na screenie? Dlaczego tak strasznie obcina te ściany? Jak to naprawić? Zwiększałem Near i far w programie, ale nic nie daje.
- plik.png (34 KB) - ściągnięć: 150