Уроки, алгоритмы, программы, примеры

Вход на сайт

Материалы по разделам

Построения
на плоскости (2D)
Графика
в пространстве (3D)
Вычислительная
геометрия
Физическое
моделирование
Фрактальная
графика

Новые комментарии

Не получается, емаё
огромное спасибо за подробное объяснение про 3д графику на питоне, в интернете очень мало подобной информации
dobryj den, popytalas otkryt prikreplionnyj fail ctoby posmotret kak rabotaet, no mne ego ne pokazyvaet vydajet osibku. Pochemu?
Очень интересно! ии сайт крутой жалко что умирает(
У Вас число превысит максимальное число int. Можно использовать в Вашем случае uint, но лучше все переписать на double.

Счетчики и рейтинг

Рейтинг@Mail.ru Яндекс.Метрика
Скриншот к примеру
Среда программирования: 
Qt

Хотелось бы объяснить использование OpenGL в Qt для вращения трехмерной фигуры.
В данном примере приведен измененный код из статьи "Введение в OpenGL на Qt/C++" для отрисовки разноцветного икосаэдра.
Цвета задаются рандомно, а сама отрисовка производится через встроенные функции отрисовки по массивам координат.

Код программы: 

// widget.cpp
#include "widget.h"
 
GLfloat VerMas[12][3]; // массив вершин
GLubyte IndMas[20][3]; // массив индексов
GLfloat ClrMas[12][3]; // массив цветов граней
const static float pi=3.141593, k=pi/180;
 
Widget::Widget(QWidget *parent)
    : QGLWidget(parent)
{
    resize(300,300);
    xRotation = 0;
    yRotation = 0;
    zRotation = 0;
    scale = 1;
}
 
void Widget::initializeGL()
{
   // инициализация OpenGL
   qglClearColor(Qt::white);
   glEnable(GL_DEPTH_TEST);
   glShadeModel(GL_FLAT);
   glEnable(GL_CULL_FACE);
   glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
 
   initVerMas(); // инициализация массива вершин
   initColorMas(); // инициализация массива цветов
   initIndMas();  // инициализация массива индексов
 
   glEnableClientState(GL_VERTEX_ARRAY); // активизация массива вершин
   glEnableClientState(GL_COLOR_ARRAY);  // активизация массива цветов
}
 
void Widget::resizeGL(int nWidth, int nHeight)
{
    // что будем делать при изменении размера окна
    glViewport(0, 0, nHeight, nHeight);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
}
 
void Widget::paintGL() // рисование
{
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // очистка буфера изображения и глубины
 
   glMatrixMode(GL_MODELVIEW); // устанавливает положение и ориентацию матрице моделирования
   glLoadIdentity();           // загружает единичную матрицу моделирования
 
   glScalef(scale, scale, scale);        // масштабирование
   glRotatef(xRotation, 1.0f, 0.0f, 0.0f); // поворот по X
   glRotatef(yRotation, 0.0f, 1.0f, 0.0f); // поворот по Y
   glRotatef(zRotation, 0.0f, 0.0f, 1.0f); // поворот по Z
 
   drawAxis();
 
   QColor clr(128, 128, 0, 255);
   qglColor(clr);
   // извлечение данных о массиве вершин
   glVertexPointer(3, GL_FLOAT, 0, VerMas);
   // извлечение данных о цветах
   glColorPointer(3, GL_FLOAT, 0, ClrMas);
   // построение поверхности, используя массив индексов
   glDrawElements(GL_TRIANGLES, 60, GL_UNSIGNED_BYTE, IndMas);
 
}
 
void Widget::mousePressEvent(QMouseEvent* pe) // нажатие клавиши мыши
{
   // запоминаем координату нажатия мыши
   mousePos = pe->pos();
}
 
void Widget::mouseMoveEvent(QMouseEvent* pe) // изменение положения стрелки мыши
{
   xRotation += 180/scale*(GLfloat)(pe->y()-mousePos.y())/height(); // вычисляем углы поворота
   zRotation += 180/scale*(GLfloat)(pe->x()-mousePos.x())/width();
 
   mousePos = pe->pos();
 
   updateGL(); // обновляем изображение
}
 
void Widget::mouseReleaseEvent(QMouseEvent *pe)
{
}
 
void Widget::drawAxis()
{
    glLineWidth(3.0f); // устанавливаем ширину линии
 
    glColor4f(1.00f, 0.00f, 0.00f, 1.0f); // устанавливается цвет последующих линий
    // ось x
    glBegin(GL_LINES); // построение линии
        glVertex3f( 1.0f,  0.0f,  0.0f); // первая точка
        glVertex3f(-1.0f,  0.0f,  0.0f); // вторая точка
    glEnd();
 
    QColor halfGreen(0, 128, 0, 255);
    qglColor(halfGreen);
    glBegin(GL_LINES);
        // ось y
        glVertex3f( 0.0f,  1.0f,  0.0f);
        glVertex3f( 0.0f, -1.0f,  0.0f);
 
        glColor4f(0.00f, 0.00f, 1.00f, 1.0f);
        // ось z
        glVertex3f( 0.0f,  0.0f,  1.0f);
        glVertex3f( 0.0f,  0.0f, -1.0f);
    glEnd();
}
 
void Widget::wheelEvent(QWheelEvent* pe) // вращение колёсика мыши
{
    // если колесико вращаем вперед -- умножаем переменную масштаба на 1.1
    // иначе -- делим на 1.1
    if ((pe->delta())>0) scale*=1.1; else if ((pe->delta())<0) scale/=1.1;
 
    updateGL();
}
 
void Widget::initIndMas()   // массив индексов
{
   // задаем индексы каждого из треугольников
   IndMas[0][0]=0; // индекс первой вершины
   IndMas[0][1]=2; // индекс второй вершины
   IndMas[0][2]=1; // индекс третьей вершины
 
   IndMas[1][0]=0;
   IndMas[1][1]=3;
   IndMas[1][2]=2;
 
   IndMas[2][0]=0;
   IndMas[2][1]=4;
   IndMas[2][2]=3;
 
   IndMas[3][0]=0;
   IndMas[3][1]=5;
   IndMas[3][2]=4;
 
   IndMas[4][0]=0;
   IndMas[4][1]=1;
   IndMas[4][2]=5;
 
   IndMas[5][0]=6;
   IndMas[5][1]=1;
   IndMas[5][2]=7;
 
   IndMas[6][0]=7;
   IndMas[6][1]=1;
   IndMas[6][2]=2;
 
   IndMas[7][0]=7;
   IndMas[7][1]=2;
   IndMas[7][2]=8;
 
   IndMas[8][0]=8;
   IndMas[8][1]=2;
   IndMas[8][2]=3;
 
   IndMas[9][0]=8;
   IndMas[9][1]=3;
   IndMas[9][2]=9;
 
   IndMas[10][0]=9;
   IndMas[10][1]=3;
   IndMas[10][2]=4;
 
   IndMas[11][0]=9;
   IndMas[11][1]=4;
   IndMas[11][2]=10;
 
   IndMas[12][0]=10;
   IndMas[12][1]=4;
   IndMas[12][2]=5;
 
   IndMas[13][0]=10;
   IndMas[13][1]=5;
   IndMas[13][2]=6;
 
   IndMas[14][0]=6;
   IndMas[14][1]=5;
   IndMas[14][2]=1;
 
   IndMas[15][0]=7;
   IndMas[15][1]=11;
   IndMas[15][2]=6;
 
   IndMas[16][0]=8;
   IndMas[16][1]=11;
   IndMas[16][2]=7;
 
   IndMas[17][0]=9;
   IndMas[17][1]=11;
   IndMas[17][2]=8;
 
   IndMas[18][0]=10;
   IndMas[18][1]=11;
   IndMas[18][2]=9;
 
   IndMas[19][0]=6;
   IndMas[19][1]=11;
   IndMas[19][2]=10;
}
 
void Widget::initVerMas() // определить массив вершин
{
   GLfloat R=0.75; // радиус сферы
 
   // начальные значения
   GLfloat a=4*R/sqrt(10+2*sqrt(5)); // сторона икосаэдра
   GLfloat alpha=acos((1-a*a/2/R/R)); // первый угол поворота по тэта
 
   // точки икосаэдра
   VerMas[0][0]=0;   // x
   VerMas[0][1]=0;   // y
   VerMas[0][2]=R;   // z
 
   VerMas[1][0]=R*sin(alpha)*sin(0);
   VerMas[1][1]=R*sin(alpha)*cos(0);
   VerMas[1][2]=R*cos(alpha);
 
   VerMas[2][0]=R*sin(alpha)*sin(72*k);
   VerMas[2][1]=R*sin(alpha)*cos(72*k);
   VerMas[2][2]=R*cos(alpha);
 
   VerMas[3][0]=R*sin(alpha)*sin(2*72*k);
   VerMas[3][1]=R*sin(alpha)*cos(2*72*k);
   VerMas[3][2]=R*cos(alpha);
 
   VerMas[4][0]=R*sin(alpha)*sin(3*72*k);
   VerMas[4][1]=R*sin(alpha)*cos(3*72*k);
   VerMas[4][2]=R*cos(alpha);
 
   VerMas[5][0]=R*sin(alpha)*sin(4*72*k);
   VerMas[5][1]=R*sin(alpha)*cos(4*72*k);
   VerMas[5][2]=R*cos(alpha);
 
   VerMas[6][0]=R*sin(pi-alpha)*sin(-36*k);
   VerMas[6][1]=R*sin(pi-alpha)*cos(-36*k);
   VerMas[6][2]=R*cos(pi-alpha);
 
   VerMas[7][0]=R*sin(pi-alpha)*sin(36*k);
   VerMas[7][1]=R*sin(pi-alpha)*cos(36*k);
   VerMas[7][2]=R*cos(pi-alpha);
 
   VerMas[8][0]=R*sin(pi-alpha)*sin((36+72)*k);
   VerMas[8][1]=R*sin(pi-alpha)*cos((36+72)*k);
   VerMas[8][2]=R*cos(pi-alpha);
 
   VerMas[9][0]=R*sin(pi-alpha)*sin((36+2*72)*k);
   VerMas[9][1]=R*sin(pi-alpha)*cos((36+2*72)*k);
   VerMas[9][2]=R*cos(pi-alpha);
 
   VerMas[10][0]=R*sin(pi-alpha)*sin((36+3*72)*k);
   VerMas[10][1]=R*sin(pi-alpha)*cos((36+3*72)*k);
   VerMas[10][2]=R*cos(pi-alpha);
 
   VerMas[11][0]=0;
   VerMas[11][1]=0;
   VerMas[11][2]=-R;
}
 
void Widget::initColorMas() // задание цветов граней
{
   for (int i=0; i<12; i++)
   {
      // цвета генерируем рандомно
      ClrMas[i][0]=0.1f*(qrand()%10);
      ClrMas[i][1]=0.1f*(qrand()%10);
      ClrMas[i][2]=0.1f*(qrand()%10);
   }
}

Прикрепленный файлРазмер
openGL_qt.zip5.76 кб