Задача: Построить 3D модель доски для дартса используя графическую библиотеку OpenGL. Алгоритм простой. Будем последовательно рисовать 7 слоёв. Каждый следующий будет закрывать предыдущий. Чтобы цвета не сливались, эти слои будут на расстоянии примерно 0.1. Файл "func.h" #ifndef _FUNC_H #define _FUNC_H #include "D:\\Common\\OpenGLSB.h" #include <time.h> #include <stdlib.h> #include <math.h> #if !defined(M_PI) #define M_PI 3.1415926535897932384626433832795028841971 #endif; // вычисление косинуса и синуса (по углу в градусах) double Cos(double angle) { return cos(angle * M_PI / 180.0); } double Sin(double angle) { return sin(angle * M_PI / 180.0); } // рисует сектор, диапазон [start_angle, start_angle + 18] void Sector(int start_angle, int p, float z, float Radius, GLenum mode) { // p = 0 - рисуем белым или чёрным // иначе - рисуем красным или зелёным // если каждый сектор по 18 градусов и цвета чередуются, то в зависимости от остатка от делания на 2 выбирается цвет if (p) { if (start_angle / 18 % 2) glColor3f(1, 0, 0); // красный else glColor3f(0, 1, 0); // зелёный } else { if (start_angle / 18 % 2) glColor3f(0, 0, 0); // черный else glColor3f(1, 1, 1); // белый } glBegin(mode); glVertex3f(0, 0, z); glNormal3f(0, 0, 1); for(int i = 0; i <= 18; i++) glVertex3f(Radius * Cos(start_angle + i), Radius * Sin(start_angle + i), z); glEnd(); } // рисует круг void Circle(float Radius, float z, GLenum mode) { glBegin(mode); glNormal3f(0, 0, 1); for(int t = 0; t < 360; t++) glVertex3f(Radius * Cos(t), Radius * Sin(t), z); glEnd(); } void Darts(float scale, float width) { // Стандартные размеры мишени: // внутренняя ширина колец «даблов» и «треблов» 8 мм. // внутренний диаметр «яблочка» 12,7 мм. // внутренний диаметр внешнего центрального кольца 31,8 мм. // расстояние от центра мишени до внешней стороны проволоки кольца «даблов» 170,0 мм. // расстояние от центра мишени до внешней стороны проволоки кольца «треблов» 107,0 мм. float wDouble = 8 * scale; float doubleRadius = 170 * scale; float tripleRadius = 107 * scale; float rE = (31.8 / 2) * scale; float rI = (12.7 / 2) * scale; // радиус всей доски float Radius = doubleRadius * 1.3; // задняя стенка glColor3f(0, 0, 0); Circle(Radius, width / -2, GL_POLYGON); Circle(Radius, width / 2 - 0.1, GL_POLYGON); // контуры (чтобы не сливалось с фоном) glColor3f(1, 1, 1); Circle(Radius, width / -2, GL_LINE_LOOP); Circle(Radius, width / 2, GL_LINE_LOOP); // ребро доски glBegin(GL_QUADS); glColor3f(0, 0, 0); for(int t = 0; t < 360; t++) { glVertex3f( Radius * Cos(t), Radius * Sin(t), width / 2 ); glVertex3f( Radius * Cos(t), Radius * Sin(t), -width / 2 ); glVertex3f( Radius * Cos(1 + t), Radius * Sin(1 + t), -width / 2 ); glVertex3f( Radius * Cos(1 + t), Radius * Sin(1 + t), width / 2 ); } glEnd(); GLenum mode = GL_POLYGON; // лицевая часть for(int t = 0; t <= 360; t += 18) { Sector(t, 1, width / 2 + 0.0, doubleRadius, mode); // кольцо даблов Sector(t, 0, width / 2 + 0.1, doubleRadius - wDouble, mode); // кольцо между даблами и треблами Sector(t, 1, width / 2 + 0.2, tripleRadius, mode); // кольцо треблов Sector(t, 0, width / 2 + 0.3, tripleRadius - wDouble, mode); // кольцо между треблами и центром } // зелёным цветом центральное кольцо glColor3f(0, 1, 0); Circle(rE, width / 2 + 0.4, mode); // красным цветом "яблочко" glColor3f(1, 0, 0); Circle(rI, width / 2 + 0.5, mode); // рисуем проволоку glLineWidth(2); mode = GL_LINE_LOOP; glColor3f(0.5, 0.5, 0.5); Circle(doubleRadius, width / 2 + 0.3, mode); // даблы (внешний радиус) Circle(doubleRadius - wDouble, width / 2 + 0.03, mode); // даблы (внутренний радиус) Circle(tripleRadius, width / 2 + 0.3, mode); // треблы (внешний радиус) Circle(tripleRadius - wDouble, width / 2 + 0.03, mode); // треблы (внутренний радиус) Circle(rE, width / 2 + 0.4, mode); // центральное кольцо Circle(rI, width / 2 + 0.5, mode); // "яблочко" glPopMatrix(); } // рисует поверхность (пол) void Parket(const float radius) { glPushMatrix(); glBegin(GL_QUADS); glVertex3f(-radius, -radius, 0); glVertex3f(-radius, radius, 0); glVertex3f( radius, radius, 0); glVertex3f( radius, -radius, 0); glEnd(); glPopMatrix(); } #endif; Файл "Darts3D.cpp" #include "func.h" #include <time.h> #include <stdlib.h> #include <math.h> // позиция источкика света GLfloat lightPos[] = {0, 100, 200, 0}; // угол поворота по x, y, z float xRot = 0, yRot = 0, zRot = 0; // смещение по x, y, z float translateY = -56, translateX = 0, translateZ = 33; void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glRotatef(-90, 1, 0, 0); glTranslatef(-translateX, -translateY, -translateZ); glLightfv(GL_LIGHT0, GL_POSITION, lightPos); glPushMatrix(); glColor3f(1, 0, 0); glRotatef(90, 1, 0, 0); glRotatef(xRot, 0, 1, 0); glTranslatef(0, 25, 0); Darts(0.088, 1); glColor3f(0, 1, 0); Parket(500); glPopMatrix(); glPopMatrix(); glutSwapBuffers(); } void reshape(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); GLfloat fAspect = (GLfloat)w/(GLfloat)h; gluPerspective(60, fAspect, 1, 5000.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void init() { glClearColor(0.0, 0.0, 0.0, 0.0); glFrontFace(GL_CCW); float mat_specular[] = {1.0, 1.0, 1.0, 0}; float diffuseLight[] = {0.7, 0.7, 0.7, 1}; float ambientLight[] = {0.3, 0.3, 0.3, 1.0}; glClearColor(0, 0, 0, 0); glShadeModel(GL_SMOOTH); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMateriali(GL_FRONT, GL_SHININESS, 128); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight); glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight); glEnable(GL_LIGHT0); glEnable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT, GL_AMBIENT); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); srand(time(0)); } void SpecialKeys(int key, int x, int y) { // клавиши влево/вправо меняют угол по x // вверх/вниз - приближают/отдаляют наблюдателя if (key == GLUT_KEY_LEFT) { xRot += 2; glutPostRedisplay(); } if (key == GLUT_KEY_RIGHT) { xRot -= 2; glutPostRedisplay(); } if (key == GLUT_KEY_UP) { translateY += 5; glutPostRedisplay(); } if (key == GLUT_KEY_DOWN) { translateY -= 5; glutPostRedisplay(); } } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(1024, 860); glutInitWindowPosition(100, 100); glutCreateWindow("Darts"); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutSpecialFunc(SpecialKeys); glutMainLoop(); return 0; }
Ключевые слова:
Darts, Дартс, OpenGl, C++
|
|||||||