Модель доски для дартса на OpenGL

Darts3D

Задача: Построить 3D модель доски для дартса используя графическую библиотеку OpenGL.

Алгоритм простой. Будем последовательно рисовать 7 слоёв. Каждый следующий будет закрывать предыдущий.
1) слой чёрного цвета - "молоко"
2) красные и зелёные сектора (кольцо даблов)
3) чёрные и белые сектора
4) красные и зелёные сектора (кольцо треблов)
5) чёрные и белые сектора
6) зелёное внутреннее кольцо
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++
ВложениеРазмер
Darts3D.rar73.37 кб