Министерство образования и науки Российской Федерации
ФГАОУ ВПО «Уральский федеральный университет
им. первого Президента России Б.Н.Ельцина»
Теплоэнергетический факультет
КАФЕДРА ПРИКЛАДНОЙ МАТЕМАТИКИ
Курсовая работа
по дисциплине «Компьютерная графика»
Модель трехмерной сцены и библиотека OpenGL
Студент: Котовский В.В.
Екатеринбург,
2010
Средствами графической библиотеки OpenGL построить динамическую трехмерную сцену, включающую заданные тело и поверхность вида z=f(x,y). Заданные графические объекты должны быть представлены в следующих видах:
· в виде каркасной модели, позволяющей видеть контуры примитивов, из которых составлены объекты;
· в виде реалистических изображений, построенных с учетом параметров источника освещения и параметров отражающих свойств материала;
· в виде объектов с наложенной на них текстурой.
Заданное тело: вентилятор.
Заданная поверхность:
,где а, b – параметры.
Каркасные модели и поверхности могут быть представлены с помощью примитивов OpenGL, таких как:
× GL_LINES
× GL_LINE_STRIP
× GL_LINE_LOOP
× GL_TRIANGLES
× GL_TRIANGLE_STRIP
× GL_TRIANGLE_FAN
× GL_QUADS
× GL_QUAD_STRIP
× GL_POLYGON
×
Примитивы LINE могут быть использованы только для создание, например, сетки, поскольку нормали к ним не пропишешь и освещение на них не будет правильно отображаться.
Примитивы TRIANGLE и QUAD применимы для создания, пожалуй, всех поверхностей и тел – куб, пирамида, параллелепипед, сфера, цилиндр и т.д. С использованием TRIANGLE поверхности и тела получаются верно сглаженными при меньшем разбиении, нежели с QUAD.
Примитив POLYGON применим для получения круга.
В данной работе используются примитивы: GL_QUADS, GL_LINES, GL_POLYGON для построение каркасной модели тела, а для построения поверхности используется GL_QUADS.
Составные части модели вентилятора
Сетка
Сетка вентилятора составлена из трех основных частей
- Круговая составляющая сетки
где bFan+17 – радиус окружности, rWeb – разбиение окружности |
Фрагмент кода программы круговой составляющей сетки
q=0;
while(q<rWeb)
{
glBegin(GL_LINES);
glVertex3f(0,(bFan+17)*sin(q*2*M_PI/rWeb),(bFan+17)*cos(q*2*M_PI/rWeb));
glVertex3f(0,(bFan+17)*sin((q+1)*2*M_PI/rWeb),(bFan+17)*cos((q+1)*2*M_PI/
rWeb));
glEnd();
q++;
}
- Дуговая составляющая сетки
где bFan+2 – радиус полуокружности, rWeb – разбиение окружности |
Фрагмент кода программы дуговой составляющей сетки
int iWeb=0;
while(iWeb<rWeb)
{
glBegin(GL_LINES);
glVertex3f((bFan+2)*cos(iWeb*M_PI/rWeb),(bFan+2)*sin(iWeb*M_PI/rWeb)+15,0);
glVertex3f((bFan+2)*cos((iWeb+1)*M_PI/rWeb),(bFan+2)*sin((iWeb+1)*M_PI/rWeb)+15,0);
glEnd();
iWeb++;
}
- Косой прут сетки
| |
где a, b – параметры отрезка |
Фрагмент кода программы косого прута сетки
glBegin(GL_LINES);
glVertex3f(bFan+2,15,0);
glVertex3f(bFan,rFan,0);
glEnd();
1. Винт
Винт вентилятора составлен из трех основных частей
- Лопасть вентилятора
где bFan – половина ширины лопасти в основании, lFan – длина лопасти, N – разбиение лопасти |
Фрагмент кода программы лопасти вентилятора
doublebFan=5;
double lFan=15;
glBindTexture(GL_TEXTURE_2D,texture4);
float N=30;
float NNN=100;
int i=0;
while(i<N)
{
glBegin(GL_QUADS);
glTexCoord2d(i/N,0);
glNormal3f(-2*lFan*bFan*i/(N*N)*sin(i*M_PI/(1.5*N)), 2*bFan*bFan/(N*log(NNN))*(log(i+26)*i*sin(i*M_PI/(1.5*N))-log(i+25)*(i+1)*sin((i+1)*M_PI/(1.5*N))), 2*bFan*lFan*log(i+25)/(N*log(NNN)));
glVertex3f(-bFan*log(i+25)/log(NNN),lFan*i/N,-bFan*(i)/N*sin(i*M_PI/(N*1.5)));
glTexCoord2d(i/N,1);
glNormal3f(-2*lFan*bFan*i/(N*N)*sin(i*M_PI/(1.5*N)), 2*bFan*bFan/(N*log(NNN))*(log(i+26)*i*sin(i*M_PI/(1.5*N))-log(i+25)*(i+1)*sin((i+1)*M_PI/(1.5*N))),2*bFan*lFan*log(i+25)/(N*log(NNN)));
glVertex3f(bFan*log(i+25)/log(NNN),lFan*i/N,bFan*(i)/N*sin(i*M_PI/(N*1.5)));
glTexCoord2d((i+1.0)/N,1);
glNormal3f(-2*lFan*bFan*i/(N*N)*sin(i*M_PI/(1.5*N)), 2*bFan*bFan/(N*log(NNN))*(log(i+26)*i*sin(i*M_PI/(1.5*N))-log(i+25)*(i+1)*sin((i+1)*M_PI/(1.5*N))),2*bFan*lFan*log(i+25)/(N*log(NNN)));
glVertex3f(bFan*log((i+26))/log(NNN),lFan*(i+1)/N,bFan*(i+1)/N*sin((i+1)*M_PI/(N*1.5)));
glTexCoord2d((i+1.0)/N,0);
glNormal3f(-2*lFan*bFan*i/(N*N)*sin(i*M_PI/(1.5*N)), 2*bFan*bFan/(N*log(NNN))*(log(i+26)*i*sin(i*M_PI/(1.5*N))-log(i+25)*(i+1)*sin((i+1)*M_PI/(1.5*N))),2*bFan*lFan*log(i+25)/(N*log(NNN)));
glVertex3f(-bFan*log((i+26))/log(NNN),lFan*(i+1)/N,
*(i+1)/N*sin((i+1)*M_PI/(N*1.5)));glEnd();
i++;
}
- Цилиндр, объединяющий лопасти вентилятора в винт
где M – разбиение цилиндра |
Фрагмент кода программы цилиндра, объединяющего лопасти вентилятора в винт
M=30;
int qRoll=0;
glBindTexture(GL_TEXTURE_2D,texture2);
while (qRoll<M)
{
glBegin(GL_QUADS);
glTexCoord2d(0,qRoll/M);
glNormal3f(0,sin((2*M_PI*qRoll)/M),cos((2*M_PI*qRoll)/M));
glVertex3f(-1,sin((2*M_PI*qRoll)/M),cos((2*M_PI*qRoll)/M));
glTexCoord2d(0,(qRoll+1.0)/M);
glNormal3f(0,sin((2*M_PI*(qRoll+1))/M),cos((2*M_PI*(qRoll+1))/M));
glVertex3f(-1,sin((2*M_PI*(qRoll+1))/M),cos((2*M_PI*(qRoll+1))/M));
glTexCoord2d(1,(qRoll+1.0)/M);
glNormal3f(0,sin((2*M_PI*(qRoll+1))/M),cos((2*M_PI*(qRoll+1))/M));
glVertex3f(1,sin((2*M_PI*(qRoll+1))/M),cos((2*M_PI*(qRoll+1))/M));
glTexCoord2d(1,qRoll/M);
glNormal3f(0,sin((2*M_PI*qRoll)/M),cos((2*M_PI*qRoll)/M));
glVertex3f(1,sin((2*M_PI*qRoll)/M),cos((2*M_PI*qRoll)/M));
glEnd();
qRoll++;
}
- Крышка на цилиндр
где M – разбиение круга |
Фрагмент кода программы цилиндра, объединяющего лопасти вентилятора в винт
int M=30;
int qFan=0;
glBegin(GL_POLYGON);
while (qFan<M)
{
glNormal3f(1,0,0);
if(qFan<M/4)
{
glTexCoord2d(0,1-qFan*4/M);
}
if((qFan>=M/4)&&(qFan<M/2))
{
glTexCoord2d((qFan-M/4)*4/M,0);
}
if((qFan>=M/2)&&(qFan<3*M/4))
{
glTexCoord2d(1,(qFan-M/2)*4/M);
}
if(qFan>=3*M/4)
{
glTexCoord2d(1-(qFan-3*M/4)*4/M,1);
}
glVertex3f(1,sin((2*M_PI*qFan)/M),cos((2*M_PI*qFan)/M));
qFan++;
}
glEnd();
2. Стойка
Стойка вентилятора составлена из трех основных частей
- Верхняя часть корпуса (полусфера)
где rFan – наибольший радиус в фигуре, iM, M – разбиения полусферы |
Фрагмент кода программы верхней части корпуса (полусферы)
M=30;
int iM=30;
double phi, psi;
q=0;
int i=0;
while (q<M)
{
while (i<iM)
{
glBindTexture(GL_TEXTURE_2D, texture2);
glBegin(GL_QUADS);
phi=(-(M_PI*(i))/iM); psi=((M_PI*(q))/M);
glNormal3f(-3*rFan*sin(phi),rFan*cos(phi)*sin(psi),rFan*cos(phi)*cos(psi));
glTexCoord2d((sin(phi)+1)/2,(cos(psi)+1)/2);
glVertex3d(
*rFan*sin(phi)+bFan,rFan*cos(phi)*sin(psi), rFan*cos(phi)*cos(psi));phi=(-(M_PI*(i+1))/iM); psi=((M_PI*(q))/M);
glNormal3f(-3*rFan*sin(phi),rFan*cos(phi)*sin(psi),rFan*cos(phi)*cos(psi));
glTexCoord2d((sin(phi)+1)/2,(cos(psi)+1)/2);
glVertex3d(
*rFan*sin(phi)+bFan,rFan*cos(phi)*sin(psi), rFan*cos(phi)*cos(psi));phi=(-(M_PI*(i+1))/iM); psi=((M_PI*(q+1))/M);
glNormal3f(-3*rFan*sin(phi),rFan*cos(phi)*sin(psi),rFan*cos(phi)*cos(psi));
glTexCoord2d((sin(phi)+1)/2,(cos(psi)+1)/2);
glVertex3d(
*rFan*sin(phi)+bFan,rFan*cos(phi)*sin(psi), rFan*cos(phi)*cos(psi));phi=(-(M_PI*(i))/iM); psi=((M_PI*(q+1))/M);
glNormal3f(-3*rFan*sin(phi),rFan*cos(phi)*sin(psi),rFan*cos(phi)*cos(psi));
glTexCoord2d((sin(phi)+1)/2,(cos(psi)+1)/2);
glVertex3d(
*rFan*sin(phi)+bFan,rFan*cos(phi)*sin(psi), rFan*cos(phi)*cos(psi));glEnd();
i++;
}
i=0;
q++;
}
- Цилиндрический элемент стойки
Этот элемент стойки вентилятора состоит из цилиндров и кругов (крышки для цилиндров). Все они вызываются с помощью функции OpenGL – glCallList. Большая часть кода элементов вентилятора считывается программой лишь однажды, в СallLists, а вызов уже происходит неоднократно, по мере необходимости, в функции RenderGLScene(). Этот способ наиболее эффективен как для скорости работы программы, так и для редактирования готового кода программы, благодаря чему одинаковые примитивы (цилиндр, круг, квадрат, линии и т.д.) было легко использовать вызовом CallList и, применяя элементарные преобразования – поворот, перемещение, масштабирование объектов, видоизменять необходимым образом для получения данных элементов тела.Элементы цилиндр и круг были описаны выше, поэтому не будем повторяться. |
- Ножка стойки