#include <iostream>
#include <GL\glut.h>
#include <GL\GLU.h>
#include <stdlib.h>
#include "colors.h"
//список операций
enum
{
BDODECAHEDRON,
BSPHERE,
BCUBE,
ADODECAHEDRON,
ASPHERE,
ACUBE,
_A,
_B,
_A_OR_B,
_A_AND_B,
_A_SUB_B,
_B_SUB_A
};
//положение сцены
const GLdouble left = -3.0;
const GLdouble right = 3.0;
const GLdouble bottom = -3.0;
const GLdouble top = 3.0;
GLdouble near = 4.0;
GLdouble far = 10.0;
//поворот сцены
GLfloat rotatex = 0;
GLfloat rotatey = 0;
//кнопка мыши и ее положение
int button_state = GLUT_UP;
int button_x, button_y;
GLint A, B, C, D;
int csg_op = _A_OR_B;
//позиция фигуры по OX и OY
GLfloat x_position = 0.0;
GLfloat y_position = 0.0;
GLfloat cube_position = 0.0;
GLfloat sphere_position = 0.0;
GLfloat dodecahedron_position = 0.0;
GLint cube(const GLfloat color[], GLfloat position_x, GLfloat position_y)
{
GLint S;
S = glGenLists(1);
glNewList(S, GL_COMPILE);
glColor4fv(color);
glPushMatrix();
glTranslatef(position_x, position_y, 0);
glutSolidCube(2.3);
glPopMatrix();
glEndList();
return S;
}
GLint sphere(const GLfloat x[], GLfloat position_x, GLfloat position_y)
{
GLint S;
S = glGenLists(1);
glNewList(S, GL_COMPILE);
glColor4fv(x);
glPushMatrix();
glTranslatef(position_x, position_y, 0);
glutSolidSphere(1.5, 30, 30);
glPopMatrix();
glEndList();
return S;
}
GLint dodecahedron(const GLfloat x[], GLfloat position_x, GLfloat position_y)
{
GLint S;
S = glGenLists(1);
glNewList(S, GL_COMPILE);
glColor4fv(x);
glPushMatrix();
glTranslatef(position_x, position_y, 0);
glutSolidDodecahedron();
glPopMatrix();
glEndList();
return S;
}
// установка буфера по шаблону так, чтобы выделить и отобразить
// эти элементы объекта, которые находятся внутри объекта B;
// сторону (переднюю или заднюю) поиска элементов объекта A
// определяет параметр cull_face
void A_In_B(GLint A, GLint B, GLenum cull_face, GLenum stencil_func)
{
// сначала рисуем объект А в буфер глубины при
// выключенном сохранении составляющих RGBA в буфер цвета
glEnable(GL_DEPTH_TEST);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glCullFace(cull_face);
glCallList(A);
//находим область фигуры А внутри В,
//заполним нулями область В, увелиив буфер трафарета
glDepthMask(GL_FALSE);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 0, 0);
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
glCullFace(GL_BACK);
glCallList(B);
//уменьшим буфер трафарета на границе фигуры В
glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
glCullFace(GL_FRONT);
glCallList(B);
//заполняем единицами область фигуры А и не рисуем ее внутри В
glDepthMask(GL_TRUE);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilFunc(stencil_func, 0, 1);
glDisable(GL_DEPTH_TEST);
glCullFace(cull_face);
glCallList(A);
//запрещаем тест трафарета
glDisable(GL_STENCIL_TEST);
}
//освещение и материал
void init(void)
{
GLfloat front_color[] = { 1, 0, 0, 1 };
GLfloat back_color[] = { 1, 1, 1, 1 };
GLfloat lightposition[] = { 3.0, 3.0, 5.0, 0.0 };
glEnable(GL_LIGHTING);
glDepthFunc(GL_LESS);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glLightfv(GL_LIGHT0, GL_POSITION, lightposition);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
glMaterialfv(GL_FRONT, GL_DIFFUSE, front_color);
glMaterialfv(GL_BACK, GL_DIFFUSE, back_color);
glEnable(GL_CULL_FACE);
}
void DisplayScene()
{
glClearColor(0.0, 0.5, 0.2, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// выбор матрицы моделирования
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// смещение координат объектов к центру сцены
glTranslatef(0, 0, -(near + far) / 2);
glRotatef(rotatex, 1.0, 0.0, 0.0);
glRotatef(rotatey, 0.0, 1.0, 0.0);
switch (csg_op)
{
case ASPHERE:
sphere_position = y_position ;
A = sphere(Orange, 0, sphere_position);
glEnable(GL_DEPTH_TEST);
glCallList(A);
glCallList(B);
glDisable(GL_DEPTH_TEST);
break;
case ACUBE:
cube_position = y_position;
A = cube(CadetBlue, 0, cube_position);
glEnable(GL_DEPTH_TEST);
glCallList(A);
glCallList(B);
glDisable(GL_DEPTH_TEST);
break;
case ADODECAHEDRON:
dodecahedron_position = y_position;
A = dodecahedron(YellowGreen, 0, dodecahedron_position);
glEnable(GL_DEPTH_TEST);
glCallList(A);
glCallList(B);
glDisable(GL_DEPTH_TEST);
break;
case BSPHERE:
sphere_position = x_position;
B = sphere(Brown, sphere_position, 0);
glEnable(GL_DEPTH_TEST);
glCallList(A);
glCallList(B);
glDisable(GL_DEPTH_TEST);
break;
case BCUBE:
cube_position = x_position;
B = cube(DarkMagenta, cube_position, 0);
glEnable(GL_DEPTH_TEST);
glCallList(A);
glCallList(B);
glDisable(GL_DEPTH_TEST);
break;
case BDODECAHEDRON:
dodecahedron_position = x_position;
B = dodecahedron(DarkViolet, dodecahedron_position, 0);
glEnable(GL_DEPTH_TEST);
glCallList(A);
glCallList(B);
glDisable(GL_DEPTH_TEST);
break;
case _A:
glEnable(GL_DEPTH_TEST);
glCallList(A);
glDisable(GL_DEPTH_TEST);
break;
case _B:
glEnable(GL_DEPTH_TEST);
glCallList(B);
glDisable(GL_DEPTH_TEST);
break;
case _A_OR_B:
glEnable(GL_DEPTH_TEST);
glCallList(A);
glCallList(B);
glDisable(GL_DEPTH_TEST);
break;
case _A_AND_B:
A_In_B(A, B, GL_BACK, GL_NOTEQUAL);
// отключение записи составляющих RGBA в буфер цвета
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
// включение теста буфера глубины
glEnable(GL_DEPTH_TEST);
// выбор функции для теста буфера глубины
glDepthFunc(GL_ALWAYS);
// отображение объекта B
glCallList(B);
// выбор функции для теста буфера глубины
glDepthFunc(GL_LESS);
// элементы, расположенные B во внутренней части А
A_In_B(B, A, GL_BACK, GL_NOTEQUAL);
break;
case _A_SUB_B:
// элементов объекта, А расположенные внутри B
A_In_B(A, B, GL_FRONT, GL_NOTEQUAL);
// отключение записи составляющих RGBA в буфер цвета
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
// включение теста буфера глубины
glEnable(GL_DEPTH_TEST);
// выбор функции для теста буфера глубины
glDepthFunc(GL_ALWAYS);
// отображение объекта B
glCallList(B);
// выбор функции для теста буфера глубины
glDepthFunc(GL_LESS);
// элементы объекта Б, во внутренней части А
A_In_B(B, A, GL_BACK, GL_EQUAL);
break;
case _B_SUB_A:
// элементы объекта Б, содержащиеся в интерьере И
A_In_B(B, A, GL_FRONT, GL_NOTEQUAL);
// отключение записи составляющих RGBA в буфер цвета
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
// включение теста буфера глубины
glEnable(GL_DEPTH_TEST);
// выбор функции для теста буфера глубины
glDepthFunc(GL_ALWAYS);
// отображение объекта А
glCallList(A);
// выбор функции для теста буфера глубины
glDepthFunc(GL_LESS);
// элементов объекта, А расположенные внутри B
A_In_B(A, B, GL_BACK, GL_EQUAL);
break;
}
glutSwapBuffers();
}
// изменение размера окна
void Reshape(int width, int height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(left, right, bottom, top, near, far);
DisplayScene();
}
//кнопка мыши
void MouseButton(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON)
{
// запоминание состояния левой кнопки мыши
button_state = state;
// сохранение положения курсора мыши
if (state == GLUT_DOWN)
{
button_x = x;
button_y = y;
}
}
}
//движение курсора мыши
void MouseMotion(int x, int y)
{
if (button_state == GLUT_DOWN)
{
rotatey += 30 * (right - left) / glutGet(GLUT_WINDOW_WIDTH) *(x - button_x);
button_x = x;
rotatex -= 30 * (top - bottom) / glutGet(GLUT_WINDOW_HEIGHT) *(button_y - y);
button_y = y;
glutPostRedisplay();
}
}
//список функций, которые поместим в меню
void Menu(int value)
{
switch (value)
{
case BDODECAHEDRON:
case BSPHERE:
case BCUBE:
case ADODECAHEDRON:
case ASPHERE:
case ACUBE:
case _A:
case _B:
case _A_OR_B:
case _A_AND_B:
case _A_SUB_B:
case _B_SUB_A:
csg_op = value;
DisplayScene();
break;
}
}
//привязка клавиатуре
void processSpecialKeys(int key, int x, int y)
{
switch (key) {
case GLUT_KEY_LEFT:
x_position -= 0.1;
break;
case GLUT_KEY_RIGHT:
x_position += 0.1;
break;
case GLUT_KEY_UP:
y_position += 0.1;
break;
case GLUT_KEY_DOWN:
y_position -= 0.1;
break;
case GLUT_KEY_F1:
csg_op = _A_AND_B;
DisplayScene();
break;
case GLUT_KEY_F2:
csg_op = _A_SUB_B;
DisplayScene();
break;
case GLUT_KEY_F3:
csg_op = _B_SUB_A;
DisplayScene();
break;
case GLUT_KEY_F4:
csg_op = _A_OR_B;
DisplayScene();
break;
}
DisplayScene();
}
void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case '-':
near += 0.1;
break;
case '+':
near -= 0.1;
break;
}
DisplayScene();
}
int main(int argc, char * argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_STENCIL);
glutInitWindowSize(500, 500);
glutCreateWindow("Курсовая");
glutDisplayFunc(DisplayScene);
glutReshapeFunc(Reshape);
glutMouseFunc(MouseButton);
glutMotionFunc(MouseMotion);
int MenuFigures1 = glutCreateMenu(Menu);
glutAddMenuEntry("Сфера", ASPHERE);
glutAddMenuEntry("Куб", ACUBE);
glutAddMenuEntry("Додекаэдр", ADODECAHEDRON);
int MenuFigures2 = glutCreateMenu(Menu);
glutAddMenuEntry("Сфера", BSPHERE);
glutAddMenuEntry("Куб", BCUBE);
glutAddMenuEntry("Додекаэдр", BDODECAHEDRON);
int MenuAspect = glutCreateMenu(Menu);
glutCreateMenu(Menu);
glutAddSubMenu("Выбрать фигуру А", MenuFigures1);
glutAddSubMenu("Выбрать фигуру B", MenuFigures2);
glutAttachMenu(GLUT_RIGHT_BUTTON);
glutSpecialFunc(processSpecialKeys);
glutKeyboardFunc(keyboard);
A = cube(Orange, cube_position, 0);
C = sphere(Aqua, sphere_position, 0);
B = dodecahedron(Khaki, dodecahedron_position, 0);
init();
glutMainLoop();
return 0;
}