Главная
 
Ghost Studio Вторник, 14.05.2024, 20:15:55



Приветствую Вас Гость | RSS
Главная
Меню сайта

Категории каталога
Разное [36]
Всякая всячина)))
Программирование графики [3]
Учебник по OpenGL [6]
Программирование под Windows [8]

Наш опрос
Новый сайт должен быть красивым или должен преобладать минимализм? Удобным он будет в любом случае.
Всего ответов: 46

Главная » Статьи » Учебник по OpenGL

Приложение
  • Приложение содержит информацию в основном прикладного характера, которая может понадобиться при изучении описанного выше материала.

    Стандартные геометрические примитивы

    Рассмотрим стандартные команды построения примитивов, которые реализованы в библиотеках GLU и GLUT.

    Как уже было сказано, чтобы построить примитив из библиотеки GLU, надо сначала создать указатель на quadric- объект с помощью команды gluNewQuadric(), а затем вызвать одну из команд gluSphere(), gluCylinder(), gluDisk(), gluPartialDisk(). Рассмотрим эти команды отдельно:

    void gluSphere(GLUquadricObj*qobj, GLdouble radius, GLint slices, GLint stacks)

    Строит сферу с центром в начале координат и радиусом radius. При этом число разбиений сферы вокруг оси z задается параметром slices, а вдоль оси z параметром stacks.

    void gluCylinder(GLUquadricObj*qobj, GLdouble baseRadius, GLdouble topRadius, GLdouble height, GLint slices, GLint stacks)

    Строит цилиндр без оснований (то есть кольцо), продольная ось параллельна оси z, заднее основание имеет радиус baseRadius , и расположено в плоскости z=0, переднее основание имеет радиус topRadius и расположено в плоскости z=height. Если задать один из радиусов равным нулю, то будет построен конус.

    Параметры slices и stacks имеют тот же смысл, что и в предыдущей команде.

    void gluDisk(GLUquadricObj*qobj, GLdouble innerRadius, GLdouble outerRadius, GLint slices, GLint loops)

    Строит плоский диск (то есть круг) с центром в начале координат и радиусом outerRadius. При этом если значение innerRadius ненулевое, то в центре диска будет находиться отверстие радиусом innerRadius. Параметр slices задает число разбиений диска вокруг оси z, а параметр loops –число концентрических колец, перпендикулярных оси z.

    void gluPartialDisk(GLUquadricObj *qobj, GLdouble innerRadius, GLdouble outerRadius, GLint slices, GLint loops, GLdouble startAngle, GLdouble sweepAngle);

    Отличие этой команды от предыдущей заключается в том, что она строит сектор круга, начальный и конечный углы которого отсчитываются против часовой стрелки от положительного направления оси y и задаются параметрами startAngle и sweepAngle. Углы измеряются в градусах.

    Команды, проводящие построение примитивов из библиотеки GLUT, реализованы через стандартные примитивы OpenGL и GLU. Для построения нужного примитива достаточно произвести вызов соответствующей команды.

    • void glutSolidSphere(GLdouble radius, GLint slices, GLint stacks)
    • void glutWireSphere(GLdouble radius, GLint slices, GLint stacks)

    Команда glutSolidSphere() строит сферу, а glutWireSphere() -каркас сферы радиусом radius. Остальные параметры имеют тот же смысл, что и в предыдущих командах.

    • void glutSolidCube(GLdouble size)
    • void glutWireCube(GLdouble size)

    Эти команды строят куб или каркас куба с центром в начале координат и длиной ребра size.

    • void glutSolidCone(GLdouble base, GLdouble height, GLint slices, GLint stacks)
    • void glutWireCone(GLdouble base, GLdouble height, GLint slices, GLint stacks)

    Эти команды строят конус или его каркас высотой height и радиусом основания base, расположенный вдоль оси z. Основание находится в плоскости z=0. Остальные параметры имеют тот же смысл, что и в предыдущих командах.

    • void glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius, GLint nsides, GLint rings)
    • void glutWireTorus(GLdouble innerRadius, GLdouble outerRadius, GLint nsides, GLint rings)

    Эти команды строят тор или его каркас в плоскости z=0. Внутренний и внешний радиусы задаются параметрами innerRadius, outerRadius. Параметр nsides задает число сторон в кольцах, составляющих ортогональное сечение тора, а rings- число радиальных разбиений тора.

    • void glutSolidTetrahedron(void)
    • void glutWireTetrahedron (void)

    Эти команды строят тетраэдр (правильную треугольную пирамиду) или его каркас, при этом радиус описанной сферы вокруг него равен 1.

    • void glutSolidOctahedron(void)
    • void glutWireOctahedron(void)

    Эти команды строят октаэдр или его каркас, радиус описанной вокруг него сферы равен 1.

    • void glutSolidDodecahedron(void)
    • void glutWireDodecahedron(void)

    Эти команды строят додекаэдр или его каркас, радиус описанной вокруг него сферы равен квадратному корню из трех.

    • void glutSolidIcosahedron(void)
    • void glutWireIcosahedron(void)

    Эти команды строят икосаэдр или его каркас, радиус описанной вокруг него сферы равен 1.

    Создание приложения в среде MS Visual C++ 5.0

    Перед началом работы необходимо скопировать файлы glut.h, glut32.lib glut32.dll в каталоги ..\MSVC\Include\Gl, ..\MSVC\Lib, ..\Windows\System соответственно. Также в этих каталогах надо проверить наличие файлов gl.h, glu.h, opengl32.lib, glu32.lib, opengl32.dll, glu32.dll, которые обычно входят в состав Visual C++ и Windows. При использовании команд из библиотеки GLAUX к перечисленным файлам надо добавить glaux.h, glaux.lib.

    Для создания приложения надо выполнить следующие действия:

    • Создание проекта: для этого надо выбрать File->New->Projects->Win32 Console Application, набрать имя проекта, OK.
    • В появившемся окне выбрать ‘ An empty project ’, Finish , OK .
    • Текст программы можно либо разместить в созданном текстовом файле(выбрав File->New->Files->Text File ), либо добавив файл с расширением *.c или *.cpp в проект (выбрав Project->Add To Project->Files ).
    • Подключить к проекту библиотеки OpenGL. Для этого надо выбрать Project->Settings->Link и в поле Object/library modules набрать названия нужных библиотек: opengl32.lib, glu32.lib, glut32.lib и, если надо, glaux.lib.
    • Для компиляции выбрать Build->Build program.exe , для выполнения – Build->Execute program.exe .
    • Чтобы при запуске не появлялось текстовое окно, надо выбрать Project->Settings->Link и в поле Project Options вместо ‘subsystem:console’ набрать ‘subsystem:windows’,и набрать там же строку ‘/entry:mainCRTStartup’
    • Когда программа готова, рекомендуется перекомпилировать ее в режиме ‘ Release ’ для оптимизации по быстродействию и объему. Для этого сначала надо выбрать Build->Set Active Configuration… и отметить -Win32 Release, а затем заново подключить необходимые библиотеки.

    Создание приложения в среде Borland C++ 5.02

    Как и для Visual C++, сначала надо обеспечить наличие файлов glut.h, glut32.lib, glut32.dll в каталогах ..\BorlandC\Include\Gl, ..\BorlandC\Lib, ..\Windows\System соответственно. Также в этих каталогах надо проверить наличие файлов gl.h, glu.h, opengl32.lib, glu32.lib, opengl32.dll, glu32.dll, которые обычно входят в состав BorlandC++ и Windows. При этом надо учитывать, что версии Microsoft файлов opengl32.lib, glu32.lib, glut32.lib для Borland C++ не подходят и следует использовать только совместимые версии. Чтобы создать такие версии, надо использовать стандартную программу ‘implib, которая находится в каталоге ..\BorlandC\Bin. Для этого надо выполнить команды вида implib ..\BorlandC\Lib\filename.lib ..\filename.dll для перечисленных файлов, которые создают нужный *.lib файл из соответствующего *.dll файла. Кроме того, надо отметить, что компилятор BorlandC не может по неизвестным причинам использовать файл glaux.lib, входящий в состав BorlandC++5.02, при компиляции приложения, использующего библиотеку GLAUX, поэтому возможно от этой библиотеки придется отказаться. Для создания приложения надо выполнить следующие действия:

    • Создание проекта: для этого надо выбрать Project->New Project и заполнить поля в окне Target Expert следующим образом: в поле Platform выбрать Win32,в поле Taget Model выбрать Сonsole, нажать Advanced и отменить выбор пунктов *.rc ‘и *.def.
    • Подключить к проекту библиотеки OpenGL. Для этого надо выбрать в окне проекта название исполняемого файла проекта (*.exe) и нажав правую кнопку мыши выбрать в контекстном меню пункт Add node. Затем надо определить положение файлов opengl32.lib, glu32.lib, glut32.lib.
    • Для компиляции выбрать Project->Build All, для выполнения Debug->Run.

    Пример программы

    Результатом выполнения этой программы является построение тетраэдра с вращающимися вокруг него кольцами, на которые нанесена текстура. В среде MS Visual C++ программа может компилироваться без изменений, а при компиляции в Borland C++ придется закомментировать вызов и описание функции TextureInit(), после чего не будет проводиться наложение текстур. Как было сказано выше, попытка использовать функции из библиотеки GLAUX приводит к сообщению об ошибке при компиляции программы.

    При компиляции программы в MS Visual C++ файл ‘texture.bmp’ надо поместить в каталог проекта или указать полный путь к нему, используя символ ‘/’. Если путь не указан, то при запуске исполняемого файла из операционной системы, файл с текстурой должен находиться в том же каталоге.

    #include <GL\glut.h>
    #include <GL\glaux.h>
    #include <math.h>
    #define TETR_LIST 1
    GLfloat light_col[] = {1,1,1};
    float mat_diff1[]={0.8,0.8,0.8};
    float mat_diff2[]={0.0,0.0,0.9};
    float mat_amb[]= {0.2,0.2,0.2};
    float mat_spec[]={0.6,0.6,0.6};
    float shininess=0.7*128, CurAng=0, RingRad=1, RingHeight=0.1;
    GLUquadricObj* QuadrObj;
    GLuint TexId;
    GLfloat TetrVertex[4][3], TetrNormal[4][3];
    //--Вычисление нормали к плоскости, задаваемой точками a,b,c----------//
    void getnorm (float a[3],float b[3],float c[3],float *n)
    {
    float mult=0;
    n[0]=(b[1]-a[1])*(c[2]-a[2])-(b[2]-a[2])*(c[1]-a[1]);
    n[1]=(c[0]-a[0])*(b[2]-a[2])-(b[0]-a[0])*(c[2]-a[2]);
    n[2]=(b[0]-a[0])*(c[1]-a[1])-(c[0]-a[0])*(b[1]-a[1]);
    //--Определение нужного направления нормали: от точки (0,0,0)---------//
    for (int i=0;i<3;i++) mult+=a[i]*n[i];
    if (mult<0) for (int j=0;j<3;j++) n[j]=-n[j];
    }
    //--Вычисление координат вершин тетраэдра-----------------------------//
    void InitVertexTetr()
    {
    float alpha=0;
    TetrVertex[0][0]=0;TetrVertex[0][1]=1.3;TetrVertex[0][2]=0;
    //--Вычисление координат основания тетраэдра--------------------------//
    for (int i=1;i<4;i++)
    {
    TetrVertex[i][0]=0.94*cos(alpha);
    TetrVertex[i][1]=0;
    TetrVertex[i][2]=0.94*sin(alpha);
    alpha+=120.0*3.14/180.0;
    }
    }
    //--Вычисление нормалей сторон тетраэдра------------------------------//
    void InitNormsTetr()
    {
    getnorm(TetrVertex[0],TetrVertex[1],TetrVertex[2],TetrNormal[0]);
    getnorm(TetrVertex[0],TetrVertex[2],TetrVertex[3],TetrNormal[1]);
    getnorm(TetrVertex[0],TetrVertex[3],TetrVertex[1],TetrNormal[2]);
    getnorm(TetrVertex[1],TetrVertex[2],TetrVertex[3],TetrNormal[3]);
    }
    //--Создание списка построения тетраэдра------------------------------//
    void MakeTetrList()
    {
    glNewList (TETR_LIST,GL_COMPILE);
    //--Задание сторон тетраэдра------------------------------------------//
    glBegin(GL_TRIANGLES);
    for (int i=1;i<4;i++)
    {
    glNormal3fv(TetrNormal[i-1]);
    glVertex3fv(TetrVertex[0]);glVertex3fv(TetrVertex[i]);
    if (i!=3) glVertex3fv(TetrVertex[i+1]);else glVertex3fv(TetrVertex[1]);
    }
    glNormal3fv(TetrNormal[3]);
    glVertex3fv(TetrVertex[1]);
    glVertex3fv(TetrVertex[2]);
    glVertex3fv(TetrVertex[3]);
    glEnd();
    glEndList();
    }
    void DrawRing()
    {
    //--Построение цилиндра (кольца), расположенного параллельно оси z----//
    //--Второй и третий параметры задают радиусы оснований, четвертый-----//
    //--высоту,последние два-число разбиений вокруг и вдоль оси z---------//
    //--При этом дальнее основание цилиндра находится в плоскости z=0-----//
    gluCylinder (QuadrObj,RingRad,RingRad,RingHeight,30,2);
    }
    void TextureInit()
    {
    char strFile[]="texture.bmp";
    //--Выравнивание в *.bmp по байту-------------------------------------//
    glPixelStorei(GL_UNPACK_ALIGNMENT,1);
    //--Создание идентификатора для текстуры- ----------------------------//
    glGenTextures(1,&TexId);
    //--Загрузка изображения в память-------------------------------------//
    AUX_RGBImageRec *pImage = auxDIBImageLoad(strFile);
    int BmpWidth= pImage->sizeX;
    int BmpHeight = pImage->sizeY;
    void* BmpBits = pImage->data;
    //--Начало описания свойств текстуры----------------------------------//
    glBindTexture (GL_TEXTURE_2D,TexId);
    //--Создание уровней детализации и инициализация текстуры ------------//
    gluBuild2DMipmaps(GL_TEXTURE_2D,3,BmpWidth, BmpHeight,GL_RGB,GL_UNSIGNED_BYTE,BmpBits);
    //--Разрешение наложения этой текстуры на quadric-объекты-------------//
    gluQuadricTexture(QuadrObj, GL_TRUE);
    //--Задание параметров текстуры---------------------------------------//
    //--Повтор изображения по параметрическим осям s и t------------------//
    glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
    glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
    //--Не использовать интерполяцию при выборе точки на текстуре---------//
    glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
    glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
    //--Совмещать текстуру и материал объекта-----------------------------//
    glTexEnvi (GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
    }
    void Init(void)
    {
    InitVertexTetr();
    InitNormsTetr();
    MakeTetrList();
    //--Определение свойств материала-------------------------------------//
    glMaterialfv (GL_FRONT_AND_BACK,GL_AMBIENT,mat_amb);
    glMaterialfv (GL_FRONT_AND_BACK,GL_SPECULAR,mat_spec);
    glMaterialf(GL_FRONT,GL_SHININESS,shininess);
    //--Определение свойств освещения-------------------------------------//
    glLightfv(GL_LIGHT0, GL_DIFFUSE, light_col);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    //--Проводить удаление невидимых линий и поверхностей-----------------//
    glEnable(GL_DEPTH_TEST);
    //--Проводить нормирование нормалей-----------------------------------//
    glEnable(GL_NORMALIZE);
    //--Материалы объектов отличаются только цветом диффузного отражения--//
    glEnable(GL_COLOR_MATERIAL);
    glColorMaterial(GL_FRONT_AND_BACK,GL_DIFFUSE);
    //--Создания указателя на quadric-объект для построения колец---------//
    QuadrObj=gluNewQuadric();
    //--Определение свойств текстуры--------------------------------------//
    TextureInit();
    //--Задание перспективной проекции------------------------------------//
    glMatrixMode(GL_PROJECTION);
    gluPerspective(89.0,1.0,0.5,100.0);
    //--Далее будет проводиться только преобразование объектов сцены------//
    glMatrixMode(GL_MODELVIEW);
    }
    void DrawFigures(void)
    {
    //--Включение режима нанесения текстуры-------------------------------//
    glEnable(GL_TEXTURE_2D);
    //--Задаем цвет диффузного отражения для колец------------------------//
    glColor3fv(mat_diff1);
    //--Чтобы не проводить перемножение с предыдущей матрицей загружаем единичную матрицу//
    glLoadIdentity();
    //--Определяем точку наблюдения---------------------------------------//
    gluLookAt(0.0, 0.0, 2.5,0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    //--Сохраняем видовую матрицу, так как дальше будет проводиться поворот колец//
    glPushMatrix();
    //--Производим несколько поворотов на новый угол (это быстрее,--------//
    //--чем умножать предыдущую видовую матрицу на матрицу поворота с-----//
    //--фиксированным углом поворота)-------------------------------------//
    glRotatef (-CurAng,1,1,0);
    glRotatef (CurAng,1,0,0);
    //--Для рисования колец каждое из них надо преобразовать отдельно,----//
    //--поэтому сначала сохраняем видовую матрицу, затем восстанавливаем--//
    glPushMatrix();
    glTranslatef (0,0,-RingHeight/2);
    DrawRing();
    glPopMatrix();
    glPushMatrix();
    glTranslatef (0,RingHeight/2,0);
    glRotatef (90,1,0,0);
    DrawRing();
    glPopMatrix();
    glPushMatrix();
    glTranslatef (-RingHeight/2,0,0);
    glRotatef (90,0,1,0);
    DrawRing();
    glPopMatrix();
    //--Восстанавливаем матрицу для поворотов тетраэдра--------------------//
    glPopMatrix();
    //--Выключаем режим наложения текстуры--------------------------------//
    glDisable(GL_TEXTURE_2D);
    //--Проводим повороты-------------------------------------------------//
    glRotatef(CurAng,1,0,0);
    glRotatef(CurAng/2,1,0,1);
    //--Чтобы тетраэдр вращался вокруг центра, его надо сдвинуть вниз по оси oz//
    glTranslatef(0,-0.33,0);
    //--Задаем цвет диффузного отражения для тетраэдра--------------------//
    glColor3fv(mat_diff2);
    //--Проводим построение тетраэдра-------------------------------------//
    glCallList(TETR_LIST);
    }
    void Display(void)
    {
    //--Инициализация (очистка) текущего буфера кадра и глубины-----------//
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //--Построение объектов-----------------------------------------------//
    DrawFigures();
    //--Перестановка буферов кадра----------------------------------------//
    glutSwapBuffers();
    }
    void Redraw(void)
    {
    //--Увеличение текущего угла поворота---------------------------------//
    CurAng+=1;
    //--Сигнал для вызова процедуры создания изображения (для обновления)-//
    glutPostRedisplay();
    }
    int main(int argc, char **argv)
    {
    //--Инициализация функций библиотеки GLUT-----------------------------//
    glutInit(&argc, argv);
    //--Задание режима с двойной буферизацией, представление цвета в формате RGB,--//
    //--использование буфера глубины --//
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    //--Создание окна приложения-----------------------------------------//
    glutCreateWindow("Example of using OpenGL");
    //--Регистрация функции построения изображения-----------------------//
    glutDisplayFunc(Display);
    //--Регистрация функции обновления изображения-----------------------//
    glutIdleFunc(Redraw);
    //--Инициализация функций OpenGL-------------------------------------//
    Init();
    //--Цикл обработки событий-------------------------------------------//
    glutMainLoop();
    return 0;
    }

    Результат работы программы:

    В программе используется только файл glut.h, который содержит обращения к файлам gl.h и glu.h, поэтому отдельно подключать их не нужно.

    Большим достоинством OpenGL является независимость большинства команд. Например, чтобы отключить наложение текстуры, достаточно закомментировать вызов функции TextureInit(), а чтобы получить статичное изображение достаточно не регистрировать функцию обновления изображения вызовом функции glutIdleFunc(). В этом случае можно использовать режим с одним буфером, заменив GL_DOUBLE на GL_SINGLE в команде glutInitDisplayMode() и добавив команду glFlush() в конце процедуры Display() для очистки этого буфера.





  •   Счетчики и ссылки

    Rambler's Top100
    bigmir TOP100

    Индекс Цитирования Яndex
      Девушка ищет парня
    посмотреть анкету
    девушка ищет парня - посмотреть анкету
    девушка ищет парня
      На правах рекламы
      Развлекательные сайты
  • Знакомства
  • Фото приколы
  • Каталог статей

  • Категория: Учебник по OpenGL | Добавил: Buba (22.06.2007)
    Просмотров: 1560 | Рейтинг: 0.0/0 |

    Всего комментариев: 0
    Имя *:
    Email *:
    Код *:
    Форма входа

    Поиск

    Друзья сайта

    Статистика


    Copyright MyCorp © 2024