Министерство образования Российской Федерации
НОВОСИБИРСКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ
«Задание полигональных моделей объектов Трехмерная визуализация с использование OPEN GL».
Группа: ПМ-11
Студенты: Голубева М.
Николаева А.
Вариант: 5
Преподаватель:
Новосибирск
2004
Цель работы: ознакомиться с основным способом задания полигональных моделей – методом тиражирования сечений; ознакомиться со средствами трехмерной визуализации в OpenGL (источники света, свойства материалов, текстуры).
Задания.
№ |
Путь |
Сечение |
Способ тиражирования сечения |
5 |
прямой |
выпуклый многоугольник |
с масштабированием |
Входные данные задаются с помощью текстового файла с имение param.txt, в котором содержится данные о сечении ( т.е количество точек в сечении, координаты этих точек, количество сечений в изображаемой фигуре, положение сечения вдоль пути, которое задается длиной пути от начальной вершины в процентах).
Все данные вводятся с учетом следующих направление осей координат:
y
z
![]() |
x
Чтобы изменение размера фигуры было нагляднее в программе предусмотрен ее поворот для каждой из осей.
Нормали в вершинах объекта задаются двумя способами.
В первом случае, узлы одной плоскости имеют разное направление нормалей. Направление в этом случае совпадает с вектором, выходящем из центра плоскости и проходящем через соответствующую вершину плоскости.
Во втором, нормаль имеет одинаковое направление во всех узлах одной плоскости и направлена, перпендикулярна этой плоскости. Нахождение это направление в программе реализовано с помощью процедуры ортогонализации Грамма-Шмидта. За начальную систему выбирается система из трех векторов: два из них принадлежат плоскости, к которой ищется перпендикуляр, а в качестве третьего вектора принимается единичный вектор из плоскости xy.
Также, используется наложение текстуры. Размер изображенной фигуры увеличивается после нажатия стрелки вверх и уменьшается при нажатии стрелки вниз.
Текст программы:
/*лаба №2_1 (прямой,выпуклый прямоугольник, с масштабированием)
нормаль задается в каждой точке*/
#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>
#include <math.h>
#include<stdio.h>
#include<conio.h>
# include<math.h>
#define max_t 10 //максимальное количество узлов в сечении
#define max_s 100 //максимальное кол-во сечений
#define len_x 4 //длина пути по х
#define len_y 4 //длина пути по у
#define len_z 8 //длина пути по z
float razm=1; //маштабирование
float delta=3; //величина увеличения поворота по осям
float f=0,g=0,p=0; //переменные для поворота по осям
float p1=0; //переменные для масштабирования
int XY[max_t][2]; //массив хранения координат точек сечения
int z[max_s],mashy[max_s],mashx[max_s];
float xprev[max_t],yprev[max_t],zprev[max_t];//предыдущее сечение
float xtek[max_t],ytek[max_t],ztek[max_t];//текущее сечение
int n;//количество узлов в вершине
int k;// количество сечений
GLuint TexId;//
//уменьшение размера фигуры
void CALLBACK OnKeyDown()
{razm = razm-0.1;
}
//увеличение размера фигуры
void CALLBACK OnKeyUp()
{razm = razm +0.1;
}
//поворот по z
void CALLBACK OnKey9()
{f = f + delta;
}
void CALLBACK OnKey0()
{f = f - delta;
}
//поворот по y
void CALLBACK OnKeyLeft()
{g = g + delta;
}
void CALLBACK OnKeyRight()
{g = g - delta;
}
//поворот по x
void CALLBACK OnKey8()
{p = p-delta;
}
void CALLBACK OnKey7()
{p= p +delta;
}
//величина масштабирования
void CALLBACK OnKey6()
{ p1 = p1-0.2;
}
void CALLBACK OnKey5()
{ p1= p1 +0.2;
}
//чтение исходных данных
void readdata(void)
{ int i;
FILE* param=fopen("param.txt","r");
fscanf(param,"%d ",&n);
for(i=0; i<n; i++)
{ fscanf(param,"%d %d",&XY[i][0],&XY[i][1]);
}
fscanf(param,"%d ",&k);
for(i=0; i<k; i++)
{ fscanf(param,"%d %d %d",&z[i],&mashx[i],&mashy[i]);
}
fclose(param);
}
//подпрограмма работы с текстурой
void TextureInit(void)
{
char strFile[]="texture11.bmp";
AUX_RGBImageRec *pImage;
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
glGenTextures(1,&TexId);
pImage = auxDIBImageLoad(strFile);
glBindTexture(GL_TEXTURE_2D, TexId);
gluBuild2DMipmaps(GL_TEXTURE_2D,3,pImage->sizeX,
pImage->sizeY,GL_RGB,GL_UNSIGNED_BYTE,
pImage->data);
);
}
//подпрограмм рисования фигуры
void drawer(void)
{ float delta_z; //длина по z
float xn,yn,zn;
int i,j;
//изображение самого левого сечения фигуры
glColor3d(0.8,0.8,0.8);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glBegin(GL_POLYGON);
for (j=0; j<n; j++)
{ xprev[j] = 0.01*mashx[0]*razm*XY[j][0];
yprev[j] = 0.01*mashy[0]*razm*XY[j][1];
zprev[j] = (len_z/100.)*razm*z[0];
glVertex3d(xprev[j],yprev[j],zprev[j]);
}
glEnd();
//всех остальных
for (i=1;i<k; i++)
{ delta_z=(len_z/100.)*z[i];
//координаты точек нового сечения
xtek[0] = 0.01*mashx[i]*razm*XY[0][0];
ytek[0] = 0.01*mashy[i]*razm*XY[0][1];
ztek[0] = delta_z*razm;
xn = xprev[0];//запоминаем первую точку предыдущего сечения
yn = yprev[0];
zn = zprev[0];
/*glColor3d устанавливает текущий цвет, которым будут рисоваться фигуры*/ glColor3d(1,1,1);
/*функция glPolygonMode. Она устанавливает опции для отрисовки многоугольника.
Первый параметр может принимать значения - GL_FRONT, GL_BACK и GL_FRONT_AND_BACK.
Первый параметр указывает: к лицевой, тыльной или же к обеим сторонам применяется опция, заданная вторым параметром.
Второй параметр указывает, как будет рисоваться многоугольник.
Он принимает значения:GL_FILL(рисуем заполненный многоугольник). */
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glBegin(GL_QUADS);
/*Четырехугольники рисуются вызовом функции glBegin с параметром GL_QUADS .
: каждые четыре вершины определяют свой четырехугольник. */
for (j=0; j<n-1; j++)
{
//закрашиваем верхнюю,переднюю и нижнию поверхность фигуры
glNormal3d(xtek[j],ytek[j],0);
glTexCoord2d(1,1);
glVertex3d(xtek[j],ytek[j],ztek[j]);
glNormal3d(xprev[j],yprev[j],0);
glTexCoord2d(1,0);
glVertex3d(xprev[j],yprev[j],zprev[j]);
glNormal3d(xprev[j+1],yprev[j+1],0);
glTexCoord2d(0,0);
glVertex3d(xprev[j+1],yprev[j+1],zprev[j+1]);
xprev[j] = xtek[j];
yprev[j] = ytek[j];
zprev[j] = ztek[j];
xtek[j+1] = 0.01*mashx[i]*razm*XY[j+1][0];
ytek[j+1] = 0.01*mashy[i]*razm*XY[j+1][1];
ztek[j+1] = delta_z*razm;
glNormal3d(xtek[j+1],ytek[j+1],0);
glTexCoord2d(0,1);
glVertex3d(xtek[j+1],ytek[j+1],ztek[j+1]); }
//дальная сторона
glNormal3d(xtek[j],ytek[j],0);
glTexCoord2d(1,1);
glVertex3d(xtek[j],ytek[j],ztek[j]);
glNormal3d(xprev[j],yprev[j],0);
glTexCoord2d(1,0);
glVertex3d(xprev[j],yprev[j],zprev[j]);
glNormal3d(xn,yn,0);
glTexCoord2d(0,0);
glVertex3d(xn,yn,zn);
glNormal3d(xprev[0],yprev[0],0);
glTexCoord2d(0,1);
glVertex3d(xprev[0],yprev[0],zprev[0]);
xprev[j] = xtek[j];
yprev[j] = ytek[j];
zprev[j] = ztek[j];
glEnd();
}
//самого правого сечения
glColor3d(0.8,0.8,0.8);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glBegin(GL_POLYGON);
for (j=0; j<n; j++)
{ glVertex3d(xprev[j],yprev[j],zprev[j]);
}
glEnd();
}
void CALLBACK resize(int width,int height)
{ glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-7,7, -7,7, -7,7);
gluLookAt(3,0,0, 0,0,0, 0,1,0);
glMatrixMode(GL_MODELVIEW);
}
void CALLBACK display(void)
{ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix(); // сохраняем текущие координаты
glRotated(f,0,0,1); //поворот по оси z
glRotated(g,0,1,0); //поворот по оси y
glRotated(p,1,0,0); //поворот по оси x
glScaled(1 +p1,1+p1,1+p1); //масштабирование
glTranslated(0,0,-4); // сдвигаемся по оси z на -4
drawer(); //изображение фигуры
glPopMatrix(); // возвращаемся к старой системе координат
auxSwapBuffers();
}
void main()
{ GLfloat ch[] = {0.5,0.5,0.5,1};
// GLfloat pos[] = {0,100,0,1};
GLfloat fon[] = {0.2,0.2,0.2,1}; //цвет освещения
// GLfloat ch[] = {0,100,0,1};
GLfloat pos[] = {100,10,10,1};
readdata();
auxInitPosition(0,0,600,600);
auxInitDisplayMode(AUX_RGB | AUX_DEPTH | AUX_DOUBLE);
auxInitWindow( "OpenGL Application Template" );
auxIdleFunc(display);
auxReshapeFunc(resize);
/*Режим сглаживания можно устанавливать вызовом функции
glEnable(GL_POINT_SMOOTH)
*/
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,fon);
glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,ch);
glLightfv(GL_LIGHT0,GL_POSITION,pos);
TextureInit();
auxKeyFunc(AUX_UP, OnKeyUp);
auxKeyFunc(AUX_DOWN, OnKeyDown);
auxKeyFunc(AUX_SPACE, OnKeySpace);
auxKeyFunc(AUX_LEFT, OnKeyLeft);
auxKeyFunc(AUX_RIGHT, OnKeyRight);
auxKeyFunc(AUX_9, OnKey9);
auxKeyFunc(AUX_0, OnKey0);
auxKeyFunc(AUX_7, OnKey7);
auxKeyFunc(AUX_8, OnKey8);
auxKeyFunc(AUX_5, OnKey5);
auxKeyFunc(AUX_6, OnKey6);
auxMainLoop(display);
}
/*лаба №2_2 (прямой,выпуклый прямоугольник, с масштабированием
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.