Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: taifun от Октября 29, 2009, 15:29



Название: QT + OpenGL
Отправлено: taifun от Октября 29, 2009, 15:29
взял пример OpenGL "Hello GL" запустил все нормально, знак QT вращается все красиво.
вставляю в
Код:
paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    glTranslated(0.0, 0.0, -10.0);
    glRotated(xRot / 16.0, 1.0, 0.0, 0.0);
    glRotated(yRot / 16.0, 0.0, 1.0, 0.0);
    glRotated(zRot / 16.0, 0.0, 0.0, 1.0);
    glCallList(object);

    glutSolidTeapot (1);
}

ругается, на glutSolidTeapot (1);                          error: `glutSolidTeapot' was not declared in this scope
библиотеку что ли добавить нужно какую-то, вообще хочу попробывать какой-нибудь 3Д объект нарисовать, сферу, цилиндр как сделать?


Название: Re: QT + OpenGL
Отправлено: ecspertiza от Октября 29, 2009, 15:37
Ну да GLUT это отдельная либа, ее нужно сначала скачать будет, а чтобы рисовать цилиндр там сферы покури мануал по OpenGL, скачай книжечку "Qt профессиональное программирование на С++" там в 23-ей главе очень хорошо описано как работать Qt+OpenGL ;)


Название: Re: QT + OpenGL
Отправлено: Igors от Октября 29, 2009, 15:43
вообще хочу попробывать какой-нибудь 3Д объект нарисовать, сферу, цилиндр как сделать?
Сделайте сначала плоскость 10х10 (из 100 полигонов).  А затем сфера и цилиндр легко получаются из плоскости :)


Название: Re: QT + OpenGL
Отправлено: taifun от Октября 29, 2009, 16:03
не хотелось бы через плоскости, хотелось бы что бы написал glutSolidTeapot (1) или auxSolidSphere( 1 ) и готово
 или через плоскости лучше, можете объяснить как лучше и быстрее будет отрисовывать? не даром я зашел где новички задают вопросы  ;) спасибо!


Название: Re: QT + OpenGL
Отправлено: Igors от Октября 29, 2009, 16:52
не хотелось бы через плоскости, хотелось бы что бы написал glutSolidTeapot (1) или auxSolidSphere( 1 ) и готово
 или через плоскости лучше, можете объяснить как лучше и быстрее будет отрисовывать? не даром я зашел где новички задают вопросы  ;) спасибо!
Просто на готовых шейпах далеко не уехать - их набор ограничен. Ну поиграетесь Вы с чайником (teapot) и что с того? А вот если Вы научитесь создавать/вычислять полигоны и вертексы - тогда многое можно и самому создать. и для загрузки 3D моделей из файлов все готово. Начните с создания 1 полигона в плоскости XY. Просто изменив учебный пример (не забивайте голову умными книгами)

Код:
glBegin(GL_QUADS);
glVertex3f(0, 0, 0);
glVertex3f(10, 0, 0);
glVertex3f(10, 10, 0);
glVertex3f(0, 10, 0);
glEnd();
Затем создайте в цикле 100 полигонов (mesh 10x10). Ну а там уже до цилиндра рукой подать :)



Название: Re: QT + OpenGL
Отправлено: taifun от Ноября 06, 2009, 11:19
Я просто ленивый, потому и не хотел сам писать. Но сейчас почитал поразбирался, понял что вы правы и если я научусь работать с полигонами, то это даст мне большие возможности, Спасибо за совет!

Вот у меня еще вопрос
void VMMutomo::paintGL()
Код:
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glLoadIdentity();
    glTranslated(0.0, 0.0, -10.0);
    glRotated(xRot / 16.0, 1.0, 0.0, 0.0);
    glRotated(yRot / 16.0, 0.0, 1.0, 0.0);
    glRotated(zRot / 16.0, 0.0, 0.0, 1.0);
    //glCallList(object);

    glEnable(GL_DEPTH_TEST);
    //qglColor(trolltechGreen);
    qglColor(Qt::white);
    //glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);

    gluQuadricDrawStyle(quadratic, GLU_FILL);
    gluQuadricNormals(quadratic, GLU_SMOOTH);

    glTranslatef(0.0f,0.0f,0.0f);                               // Центр цилиндра
    gluCylinder(quadratic,0.05f,0.05f,0.9f,32,5);       // Рисуем наш цилиндр

/*
    //glTranslated(0.0, 0.0, 0.7);
    qglColor(Qt::black);
    gluSphere(quadratic,0.1f,32,32);                       // Рисуем сферу
*/

//******************* рисуем оси координат ******************
    glBegin(GL_LINES);
        glColor3f(0.0, 0.0, 1.0);       //ось Х
        glVertex3d(0.0, 0.0, 0.0);
        glVertex3d(0.25, 0.0, 0.0);

        glColor3f(0.0, 1.0, 0.0);       //ось Y
        glVertex3d(0.0, 0.0, 0.0);
        glVertex3d(0.0, 0.25, 0.0);

        glColor3f(1.0, 0.0, 0.0);       //ось Y
        glVertex3d(0.0, 0.0, 0.0);
        glVertex3d(0.0, 0.0, 0.25);
    glEnd();
//************************************************************
}

этот цилиндр рисуется но видна передняя стенка, "задняя" видимая часть почему-то отрезается, хотя должна быть видимой по идеи. Когда делаю отображаю цилиндр линиями gluQuadricDrawStyle(quadratic, GLU_FILL); то эта часть видна - отображается все верно. В чем проблема?


Название: Re: QT + OpenGL
Отправлено: Igors от Ноября 06, 2009, 11:42
и если я научусь работать с полигонами, то это даст мне большие возможности
Хорошие слова, но они не подтверждаются приведенным фрагментом Вашего кода где никаких полигонов Вы не создаете, а вместо этого нашли функцию которая это делает (gluCylinder). Конечно, дело Ваше как изучать, но толку от использования готового немного. Например, понадобится согнутый цилиндр и что будете делать? "Нет могу, нет такой функции" :)

этот цилиндр рисуется но видна передняя стенка, "задняя" видимая часть почему-то отрезается, хотя должна быть видимой по идеи. Когда делаю отображаю цилиндр линиями gluQuadricDrawStyle(quadratic, GLU_FILL); то эта часть видна - отображается все верно. В чем проблема?
Посмотрите GL_CULL_FACE и GL_CULL_FACE_MODE и установите нужный.
И вместо "отображаю цилиндр линиями" грамотно говорить "рисую wireframe" :)


Название: Re: QT + OpenGL
Отправлено: taifun от Ноября 06, 2009, 11:51
Учту замечания. А вы можете посоветовать книгу или интернет ресурс, где есть материал как работать с полигонами, примеры. А то пока особо в этом нарправление не разбирался, вот понял что сферу можно треугольниками построить, квадратами же не получится, ведь так?


Название: Re: QT + OpenGL
Отправлено: Igors от Ноября 06, 2009, 12:23
Учту замечания. А вы можете посоветовать книгу или интернет ресурс, где есть материал как работать с полигонами, примеры. А то пока особо в этом нарправление не разбирался,
Книг много, но OGL сам очень развесистый поэтому вероятно Вы просто "утонете в информации" без толку. Для того чтобы начать строить простые 3D объекты - Вы уже все знаете, нужно строить :) Используя, по мере надобности, хотя бы тот же OGL help из вижуал студии.

вот понял что сферу можно треугольниками построить, квадратами же не получится, ведь так?
Получится, правда будут quads у которых 2 вертекса совпадают. Это не смертельно хотя в некоторых случаях могут быть проблемы. Вообще quads или triangles не проблема: если у Вас есть 4 вертекса - Вы всегда можете отдать OGL либо 1 quad или 2 triangles (и здесь же проверить корректность quad'a).

Сфера получается из плоскости 2-мя деформациями bend. Цилиндр - одной деформацией bend. Сделайте плоскость, потом поговорим :)


Название: Re: QT + OpenGL
Отправлено: taifun от Ноября 06, 2009, 12:58
плоскость вот так я нарисовал:

Код:
for(int i=0; i<10; i++){
        for(int k=0; k<10; k++){
            glBegin(GL_QUADS);
                glVertex3d(0.0, 0.0, 0.0);
                glVertex3d(2*k, 0.0, 0.0);
                glVertex3d(2*k, 2*i, 0.0);
                glVertex3d(0.0, 2*i, 0.0);
            glEnd();
        }
}

правда размеры не те которые Вы сказали, но я думаю это не суть важно, главное принцип понять, ведь так?


Название: Re: QT + OpenGL
Отправлено: Igors от Ноября 06, 2009, 13:55
плоскость вот так я нарисовал:

Код:
for(int i=0; i<10; i++){
        for(int k=0; k<10; k++){
            glBegin(GL_QUADS);
                glVertex3d(0.0, 0.0, 0.0);
                glVertex3d(2*k, 0.0, 0.0);
                glVertex3d(2*k, 2*i, 0.0);
                glVertex3d(0.0, 2*i, 0.0);
            glEnd();
        }
}

правда размеры не те которые Вы сказали, но я думаю это не суть важно, главное принцип понять, ведь так?
Так, но плоскость Вы нарисовали неправильно :)
1) glBegin и glEnd надо вынести за все циклы, ведь вы заряжаете сразу серию полигонов а не по чайной ложке.
2) как же первый вертекс может быть одинаков для всех полигонов? Он у них разный
3) (Необязательно но желательно), вместо (k,j) используйте имена (u, v) - они в 3D имеют именно тот смысл который здесь нужен
4) что это за огрызок кода? Сделайте порядочную функцию, например такую

Код:
void DrawPlaneOGL( const float center[3], float sizeU, float sizeV, float resolutionU, float resolutionV )
{
 ...
}


Название: Re: QT + OpenGL
Отправлено: taifun от Ноября 06, 2009, 16:09
А вот так лучше уже?

Код:
float center[3] = {-5, -5, 0};
drPlane (center, 5, 5, 10, 10);

//***************************************
void VMMutomo::drPlane (float center[3], float sizeU, float sizeV, float longU, float longV){
    glBegin(GL_QUADS);
        for(int u = 0; u < longU; u++){
            for(int v = 0; v < longV; v++){
                glVertex3d(center[0] + sizeV*v,     center[1] + sizeU*u,     center[2] + 0.0);
                glVertex3d(center[0] + sizeV*(v+1), center[1] + sizeU*u,     center[2] + 0.0);
                glVertex3d(center[0] + sizeV*(v+1), center[1] + sizeU*(u+1), center[2] + 0.0);
                glVertex3d(center[0] + sizeV*v,     center[1] + sizeU*(u+1), center[2] + 0.0);

            }
        }
    glEnd();
}

и сразу бы хотел узнать есть ли такая переменная типа glPoint3D(x, y, z), из которой можно вытащить потом  координату Х glPoint.X?


Название: Re: QT + OpenGL
Отправлено: Igors от Ноября 06, 2009, 17:10
А вот так лучше уже?
Лучше, но надо шлифовать

1) "u" обычно ассоциируется с осью/координатой "x", лучше этого придерживаться. Также легче/интуитивнее строить по строкам, а не по столбцам

2) Если это "center" то он должен центру и соответствовать. А у Вас это левый верхний угол. Также sizeU(V) это размер всей плоскости вдоль оси X(Y), вызывающему неинтересно рассчитывать размер полигона, это должно быть в самой функции.

3) Если параметры float то и вызывайте glVertex3f (и добавляйте 0.0f)

4) Можно задать resolution в числе шагов вдоль X(Y), как у Вас, ничего плохого здесь нет. Но тогда эти параметры должны быть типа int

и сразу бы хотел узнать есть ли такая переменная типа glPoint3D(x, y, z), из которой можно вытащить потом  координату Х glPoint.X?
Сам не видел, но много раз слышал про дельфи-программиста который радостно воскликнул "Я нашел компоненту чтобы сравнить 2 числа!!!"  :)

То же и здесь - надо писать свой конкретный класс вместо того чтобы искать нечто, которое еще и подойдет кое-как. Например

Код:
struct Vec3D {
// avoid constructor

  void xyz( float _x = 0.0f, float _y = 0.0f, float _z = 0.0f ) { x = _x; y = _y; z = _z; }

  Vec3D & operator += ( const Vec3D & t )   { ... }
  Vec3D & operator *= ( float t )                 { ... }
  ...
  friend Vec3D operator + ( const Vec3D & t1,  const Vec3D & t2 )  { .. }
  friend Vec3D operator - ( const Vec3D & t1,  const Vec3D & t2 )  { .. }
  ...

// data
  float x, y, z;
};


Название: Re: QT + OpenGL
Отправлено: taifun от Ноября 09, 2009, 09:52
С классом для трехмерной точки понятно.
Вот подправил код:
Код:
    float center[3] = {0, 0, 0};
    drPlane (center, 50, 50, 10, 10);

void VMMutomo::drPlane (float center[3], float sizePU, float sizePV, float numU, float numV){
    float sRectU = sizePU/numU;
    float sRectV = sizePV/numV;
    float centSpaceU = sizePU/2;
    float centSpaceV = sizePV/2;
    center[0] -= centSpaceU;
    center[1] -= centSpaceV;

    glBegin(GL_QUADS);
        for(int v = 0; v < numV; v++){
            for(int u = 0; u < numU; u++){
                glVertex3d(center[0] + sRectU*u,     center[1] + sRectV*v,     center[2] + 0.0);
                glVertex3d(center[0] + sRectU*(u+1), center[1] + sRectV*v,     center[2] + 0.0);
                glVertex3d(center[0] + sRectU*(u+1), center[1] + sRectV*(v+1), center[2] + 0.0);
                glVertex3d(center[0] + sRectU*u,     center[1] + sRectV*(v+1), center[2] + 0.0);

            }
        }
    glEnd();
}


Название: Re: QT + OpenGL
Отправлено: Igors от Ноября 09, 2009, 10:57
Ладно, цилиндр. Для каждого вертекса координата Y вычисляется точно так же как и для плоскости. Как вычислить X и Z ?
Посмотрим на цилиндр сверху - видим окружность. Значит

Код:
x = center[0] + cos(angle) * radius;
z = center[2] + sin(angle) * radius;
Где взять angle? Цилиндр - это плоскость свернутая в трубочку. "Шов" (там где 2 свернутых края сходятся) на 12 часов, разворот против часовой стрелки. Значит, для каждого вертекса

Код:
angle = float (u) / numU * PI * 2 - PI / 2;

Примечание: вычисления становятся короче/удобнее если u, v меняются в диапазоне [-0.5f; +0.5f]

Вот подправил код:
Очень плохо подправили. Предыдущие замечания проигнорировали, центр хотя и добавили но с какой стати функция его модифицирует? Так что о сфере и др. вещах поговорим когда у Вас все будет чисто и аккуратно.


Название: Re: QT + OpenGL
Отправлено: taifun от Ноября 09, 2009, 13:32
Пока пишу функцию для цилиндра, гляньте на фукцию, которая строит плоскость (я поработал над ней):
Код:
float center[3] = {0, 0, 0};
drPlane (center, 50, 50, 10, 10);

void VMMutomo::drawPlane (float center[3], float sizePU, float sizePV, int numU, int numV){
    float sRectU = sizePU/numU;
    float sRectV = sizePV/numV;
    float centSpaceU = sizePU/2;
    float centSpaceV = sizePV/2;
    float StartPLeft = center[0] - centSpaceU;
    float StartPTop = center[1] - centSpaceV;
    //center[0] -= centSpaceU;
    //center[1] -= centSpaceV;

    glBegin(GL_QUADS);
        for(int v = 0; v < numV; v++){
            for(int u = 0; u < numU; u++){
                glVertex3f(StartPLeft + sRectU*u,     StartPTop + sRectV*v,     center[2] + 0.0f);
                glVertex3f(StartPLeft + sRectU*(u+1), StartPTop + sRectV*v,     center[2] + 0.0f);
                glVertex3f(StartPLeft + sRectU*(u+1), StartPTop + sRectV*(v+1), center[2] + 0.0f);
                glVertex3f(StartPLeft + sRectU*u,     StartPTop + sRectV*(v+1), center[2] + 0.0f);

            }
        }
    glEnd();
}
жду ваших замечаний, пока жду работаю над построением цилиндра...


Название: Re: QT + OpenGL
Отправлено: Igors от Ноября 09, 2009, 13:51
Пока пишу функцию для цилиндра, гляньте на фукцию, которая строит плоскость (я поработал над ней):
Ну вот, другое дело. Но еще надо работать

1) Функция не изменяет center, значит он должен быть объявлен как const float center[3]

2) Хотя это и проблемы вызывающего, numU(V) не могут быть меньше 1, функция должна это пресекать

3) centSpaceU(V), StartPLeft (Right) - зачем плодить переменные? Лучше так
Код:
float offset[3] = { center[0] - sizeU / 2, center[1] - sizeV / 2, center[2] };

4) Ошибка в счетчиках циклов: они должны изменяться до numU(V) - 1

5) Если мне не изменяет память, Вы писали о своей лени. Ваш код говорит обратное - Вы прибавляете смещения 12 раз. Ленивый программист должен написать примерно так
Код:
inline void OutVertex( float x, float y, float z, const float offset[3] )
{
  glVertex3f(x + offset[0], y + offset[1], z + offset[2]);
}


Название: Re: QT + OpenGL
Отправлено: taifun от Ноября 09, 2009, 14:45
доработал:

Код:
void VMMutomo::drawPlane (const float center[3], float sizePU, float sizePV, int numU, int numV){
    float sRectU = sizePU/numU;
    float sRectV = sizePV/numV;
    float startPoint[3] = { center[0] - sizePU / 2, center[1] - sizePV / 2, center[2] };

    glBegin(GL_QUADS);
        for(int v = 0; v < numV; v++){
            for(int u = 0; u < numU; u++){
                glVertex3f(startPoint[0] + sRectU*u,     startPoint[1] + sRectV*v,     startPoint[2]);
                glVertex3f(startPoint[0] + sRectU*(u+1), startPoint[1] + sRectV*v,     startPoint[2]);
                glVertex3f(startPoint[0] + sRectU*(u+1), startPoint[1] + sRectV*(v+1), startPoint[2]);
                glVertex3f(startPoint[0] + sRectU*u,     startPoint[1] + sRectV*(v+1), startPoint[2]);

            }
        }
    glEnd();
}

относительно пункта 4, если делать так как вы говорите, то у меня получится на одну точку меньше по Х и по Y соответственно получится всего 9 полигонов, а не 10. А вот насчет 5 пункта что-то я вообще не понял, где это применить?


Название: Re: QT + OpenGL
Отправлено: Igors от Ноября 09, 2009, 15:31
относительно пункта 4, если делать так как вы говорите, то у меня получится на одну точку меньше по Х и по Y соответственно получится всего 9 полигонов, а не 10. А вот насчет 5 пункта что-то я вообще не понял, где это применить?
Относительно пункта 4 я был неправ :) Насчет пункта 5 - ну не знаю как объяснить словами

Код:
#define PI    3.141592f
#define PI2  (PI * 2.0f)

inline void OutVertex( float x, float y, float z, const float scale[3], const float center[3] )
{
  glVertex3f(x * scale[0] + center[0], y * scale]1] + center[1], z * scale[2] + center[2]);
}

void VMMutomo::drawPlane ( const float center[3], float sizePU, float sizePV, int numU, int numV )
{
  if (numU < 1) numU = 1;
  if (numV < 1) numV = 1;

  float u = -0.5f, v = -0.5f;
  float du = 1.0f / numU;
  float dv = 1.0f / numV;
  float scale[3] = { sizePU, sizePV, 1.0f };

  glBegin(GL_QUADS);
  for(int j = 0; j < numV; ++j, v += dv) {
    for(int i = 0; i < numU; ++i, u += du) {
     OutVertex(u,        v,        0.0f, scale, center);
     OutVertex(u + du, v,        0.0f, scale, center);
     OutVertex(u + du, v + dv, 0.0f, scale, center);
     OutVertex(u,        v + dv, 0.0f, scale, center);
    }
  }
  glEnd();
}

void VMMutomo::drawCylinder( const float center[3], float height, float radius, int numU, int numV )
{
  if (numU < 1) numU = 1;
  if (numV < 1) numV = 1;

  float u = -0.5f, v = -0.5f;
  float du = 1.0f / numU;
  float dv = 1.0f / numV;
  float scale[3] = { radius, height, radius };

  glBegin(GL_QUADS);
  for(int j = 0; j < numV; ++j, v += dv) {
    for(int i = 0; i < numU; ++i, u += du) {
     float angle1 = u * PI2 + PI * 1.5f;
     float x1 = cos(angle1);
     float z1 = sin(angle1);

     float angle2 = (u + du) * PI2 + PI * 1.5f;
     float x2 = cos(angle2);
     float z2 = sin(angle2);

     OutVertex(x1, v,        z1, scale, center);
     OutVertex(x2, v,        z2, scale, center);
     OutVertex(x2, v + dv, z2, scale, center);
     OutVertex(x1, v + dv, z1, scale, center);
    }
  }
  glEnd();
}


Название: Re: QT + OpenGL
Отправлено: taifun от Ноября 09, 2009, 16:48
да по написанию получается короче, но я пока не буду так делать, мне для понимания так проще. вот написал и для цилиндра:
Код:
void VMMutomo::drawPlane (const float center[3], float sizePU, float sizePV, int numU, int numV){
    if (numU < 1) numU = 1;
    if (numV < 1) numV = 1;
    float sRectU = sizePU/numU;
    float sRectV = sizePV/numV;
    float startPoint[3] = { center[0] - sizePU / 2, center[1] - sizePV / 2, center[2] };

    glBegin(GL_QUADS);
        for(int v = 0; v < numV; v++){
            for(int u = 0; u < numU; u++){
                glVertex3f(startPoint[0] + sRectU*u,     startPoint[1] + sRectV*v,     startPoint[2]);
                glVertex3f(startPoint[0] + sRectU*(u+1), startPoint[1] + sRectV*v,     startPoint[2]);
                glVertex3f(startPoint[0] + sRectU*(u+1), startPoint[1] + sRectV*(v+1), startPoint[2]);
                glVertex3f(startPoint[0] + sRectU*u,     startPoint[1] + sRectV*(v+1), startPoint[2]);
            }
        }
    glEnd();
}

void VMMutomo::drawCylinder (const float center[3], float longCyl, float radius, int numU, int numV){
    if (numU < 1) numU = 1;
    if (numV < 1) numV = 1;
    float angle = 0;
    float x, z;
    float sRectV = longCyl/numU;
    float startPoint[3] = { center[0] - radius, center[1] - longCyl / 2, center[2] };
  
    glBegin(GL_QUADS);
        for(int v = 0; v < numV; v++){
            for(int u = 0; u < numU; u++){
                angle = float (u) / numU * PI * 2 - PI / 2;
                x = center[0] + cos(angle) * radius;
                z = center[2] + sin(angle) * radius;

                float angle1 = float (u+1) / numU * PI * 2 - PI / 2;
                float x1 = center[0] + cos(angle) * radius;
                float z1 = center[2] + sin(angle) * radius;

                glVertex3f(x,     startPoint[1] + sRectV*v,     z);
                glVertex3f(x1,    startPoint[1] + sRectV*v,     z1);
                glVertex3f(x1,    startPoint[1] + sRectV*(v+1), z1);
                glVertex3f(x,     startPoint[1] + sRectV*(v+1), z);

            }
        }
    glEnd();
}
все бы хорошо, да вот только почему-то получилось, что строятся линии только длиной longCyl, а те которые образую кольца не видно


Вставил Вашу функцию все прекрасно работает, буду разбираться завтра утром что сделал не так, а если не справлюсь, тогда потребуется ваша помощь - я напишу. А так вообще по коду есть замечания?


Название: Re: QT + OpenGL
Отправлено: Igors от Ноября 09, 2009, 17:30
все бы хорошо, да вот только почему-то получилось, что строятся линии только длиной longCyl, а те которые образую кольца не видно
Ну так надо angle1 использовать когда он вычислен - а Вы снова заряжаете angle.
Код:
angle = float (u) / numU * PI * 2 - PI / 2;          // неверно
angle = float (u) / (numU - 1) * PI * 2 + PI / 2;  // правильно
Смысл: полный поворот (который будут делать все вертексы последние по "u") = PI * 2 (полная окружность). Первые (по "u") вертексы должны быть повернуты на PI / 2 (шов сзади). Пока текстуры нет - шва не видно.

А так вообще по коду есть замечания?
:) Наложите текстуру и будет понятно почему выгодно иметь u, v в диапазоне [-0.5f; +0.5f]


Название: Re: QT + OpenGL
Отправлено: taifun от Ноября 10, 2009, 11:07
текстуры пока еще не научился накладывать, буду учиться ...
переписал (показывает нормально), замечания есть?

Код:
void VMMutomo::drawCylinder (const float center[3], float longCyl, float radius, int numU, int numV){
    if (numU < 1) numU = 1;
    if (numV < 1) numV = 1;   

    float u1 = -0.5f, v1 = -0.5f;
    float du = 1.0f / numU;
    float dv = 1.0f / numV;
    float startPoint[3] = { center[0] - radius, center[1], center[2] };

    glBegin(GL_QUADS);
        for(int v = 0; v < numV; v++, v1+=dv){
            for(int u = 0; u < numU; u++, u1+=du){

                float angle1 = u1 * PI2 + PI * 1.5f;
                float x1 = center[0] + cos(angle1) * radius;
                float z1 = center[2] + sin(angle1) * radius;

                float angle2 = (u1 + du) * PI2 + PI * 1.5f;
                float x2 = center[0] + cos(angle2) * radius;
                float z2 = center[2] + sin(angle2) * radius;

                glVertex3f(x1,     startPoint[1] + longCyl*v1,     z1);
                glVertex3f(x2,     startPoint[1] + longCyl*v1,     z2);
                glVertex3f(x2,     startPoint[1] + longCyl*(v1+dv), z2);
                glVertex3f(x1,     startPoint[1] + longCyl*(v1+dv), z1);

            }
        }
    glEnd();

    glPushMatrix();
        glTranslated(0.0, longCyl/2, 0.0);
        glRotated(90.0,1.0,0.0,0.0);
        gluDisk(quadratic,0.0f,radius,numU,numV);

        glTranslated(0.0, 0.0, longCyl);
        gluDisk(quadratic,0.0f,radius,numU,numV);
    glPopMatrix();
}

приделал торцевые стороны, жду Ваших замечаний.


Название: Re: QT + OpenGL
Отправлено: Igors от Ноября 10, 2009, 13:07
текстуры пока еще не научился накладывать, буду учиться ...
"Не все сразу" - разумный подход. Но с др. стороны такие легкие и приятные вещи как наложение текстуры имеет смысл задействовать сразу. Вам нужно будет вызвать glTexCoord2f(u,v) перед glVertex3fv.  Как активировать текстуру - наберите в хелпе glBindTexture, оттуда Вы легко найдете еще 2-3 функции которые Вам понадобятся. За день с нуля можно разобраться.

переписал (показывает нормально), замечания есть?
Если мы смотрим только эту функцию (drawCylinder) - то все хорошо. А теперь посмотрим 2 функции: drawPlane и drawCylinder. Бросается в глаза что они отличаются очень немногим. Если Вы будете строить сферу - опять кусок кода будет сдублирован - и так каждый раз для новой модели. Такое программирование методом copy/paste никогда не было уважаемым делом, а по-простому говоря "так делать западло". Если Вам пришлось так копировать (хотя бы 1 раз) то у Вас возникли вещи которые надо обобщить. Для этого и придуманы наследование, виртуальные функции и.т.п. Хотя можно сделать и в стиле чистого "С". Но в любом случае это делать надо.

приделал торцевые стороны, жду Ваших замечаний.
Не используйте стандартных функций если Вы хотите научиться строить сами.


Название: Re: QT + OpenGL
Отправлено: taifun от Ноября 10, 2009, 14:19
1. С текстурами разберусь на неделе.
2. Я думаю сейчас напишу еще функцию для окружности, сферы и пойму что можно быдет вынести и как модернезировать код.
3.  :) это я просто хотел посмотреть как будет смотрется. Никак не могу сообразить как вычислять координаты вершин полигона для окружности  ???


Название: Re: QT + OpenGL
Отправлено: Igors от Ноября 10, 2009, 14:31
Никак не могу сообразить как вычислять координаты вершин полигона для окружности  ???
:)

x = cos(angle) * radius;
y = sin(angle) * radius;

Это параметрическое (параметр angle) уравнение окружности в плоскости XY


Название: Re: QT + OpenGL
Отправлено: taifun от Ноября 10, 2009, 16:34
что-то здесь совсем туго  :-[
Код:
void VMMutomo::drawCircle (const float center[3],  float radius, int numU, int numV){
    if (numU < 1) numU = 1;
    if (numV < 1) numV = 1;

    float u1 = -0.5f, v1 = -0.5f;
    float du = 1.0f / numU;
    float dv = 1.0f / numV;
    float startPoint[3] = { center[0] - radius, center[1], center[2] };

    glBegin(GL_QUADS);
        for(int v = 0; v < numV; v++, v1+=dv){
            for(int u = 0; u < numU; u++, u1+=du){

                float angle1 = u1 * PI2 + PI * 1.5f;
                float x1 = center[0] + cos(angle1) * u1;
                float y1 = center[1] + sin(angle1) * v1;

                float angle2 = (u1 + du) * PI2 + PI * 1.5f;
                float x2 = center[0] + cos(angle2) * (u1+du);
                float y2 = center[1] + sin(angle2) * (v1+dv);

                glVertex3f(x1, y1, center[3]);
                glVertex3f(x2, y1, center[3]);
                glVertex3f(x2, y2, center[3]);
                glVertex3f(x1, y2, center[3]);

            }
        }
    glEnd();
}

а вот угол высчитываем angle1 = u1 * PI2 + PI * 1.5f что это за формула такая


Название: Re: QT + OpenGL
Отправлено: Igors от Ноября 10, 2009, 17:07
что-то здесь совсем туго  :-[
- Для массива из 3 элементов последним будет center[2]

- Что вы собрались строить: окружность (она не имеет площади) или диск (с дыркой или без)?

- В любом случае где радиус(ы) ?

а вот угол высчитываем angle1 = u1 * PI2 + PI * 1.5f что это за формула такая
Формулы не запоминаются а выводятся. На листе бумаги нарисуйте оси X и Y. Нарисуйте круг с центром в (0, 0). Поставьте на круге 8 жирных точек (вертексы в виде сверху). Точка (-1, 0) (9 часов) первая она соответствует u = -0.5f. Обходим круг против часовой стрелки и попадаем  в ту же точку. Значит для каждой точки угол = u * PI2. Добавляем 1.5 * PI. Изменилось только что мы начинаем с точки (0, 1) (12 часов)

В общем, дело творческое и надо включать пространственное представление :)


Название: Re: QT + OpenGL
Отправлено: taifun от Ноября 10, 2009, 17:22
center[3] - который раз уже наступаю на эти грабли и ошибку не показывает в этом месте даже

так диск с нулевым внутренним радиусом - это же и есть окружность или я не правильно понимаю? лучше бы диск делать, а там задав у него нулевой внутренний радиус, получим торцевую сторону цилиндра.

ща добегу до дома и буду рисовать.


Название: Re: QT + OpenGL
Отправлено: Авварон от Ноября 10, 2009, 17:30
диск - это диск. У него есть поверхность. У окружности поверхности нет, есть только внешняя линия.


Название: Re: QT + OpenGL
Отправлено: Igors от Ноября 10, 2009, 17:54
center[3] - который раз уже наступаю на эти грабли и ошибку не показывает в этом месте даже
В С/С++ указатель и массив - одно и то же, ничего показывать оно не должно. Не хотите один раз написать класс Vec3D - мучайтесь

так диск с нулевым внутренним радиусом - это же и есть окружность или я не правильно понимаю? лучше бы диск делать, а там задав у него нулевой внутренний радиус, получим торцевую сторону цилиндра.
Здесь используется геометрия времен Евклида и Пифагора, поэтому выдумывать новые термины совсем ни к чему. Окружность, диск, сфера, шар - все это разные вещи.

ща добегу до дома и буду рисовать.
:)


Название: Re: QT + OpenGL
Отправлено: taifun от Ноября 11, 2009, 11:49
Точно окружность - это окружность, а диск - это диск. Не прав был.

значит строим диск, но не получается  ???
Код:
glBegin(GL_QUADS);
        for(int v = 0; v < numV; v++, v1+=dv){
            for(int u = 0; u < numU; u++, u1+=du){

                float angle1 = u1 * PI2 + PI * 1.5f;
                float x1 = cos(angle1) * v1;
                float y1 = sin(angle1) * v1;

                float angle2 = (u1 + du) * PI2 + PI * 1.5f;
                float x2 = cos(angle2) * v1;
                float y2 = sin(angle2) * v1;

                float angle3 = u1 * PI2 + PI * 1.5f;
                float x3 = cos(angle1) * (v1 + dv);
                float y3 = sin(angle1) * (v1 + dv);

                float angle4 = (u1 + du) * PI2 + PI * 1.5f;
                float x4 = cos(angle2) * (v1 + dv);
                float y4 = sin(angle2) * (v1 + dv);

                glVertex3f(x1, y1, center[2]);
                glVertex3f(x2, y2, center[2]);
                glVertex3f(x3, y3, center[2]);
                glVertex3f(x4, y4, center[2]);

            }
        }
    glEnd();


Название: Re: QT + OpenGL
Отправлено: Igors от Ноября 11, 2009, 12:08
значит строим диск, но не получается  ???

Давайте сначала улучшим процесс вычисления вертекса. Сведем все расчеты в 1 ф-цию и будем вызывать ее так

Код:
...
CalcDiskVertex(u, v, center, minRad, maxRad);
CalcDiskVertex(u + du, v, center, minRad, maxRad);
CalcDiskVertex(u + du, v + dv, center, minRad, maxRad);
CalcDiskVertex(u, v + dv, center, minRad, maxRad);
...
Где

minRad - радиус дырки (может быть 0)
maxRad - радиус диска

Теперь сама ф-ция

Код:
void CalcDiskVertex( float u, float v, const float center[3], float minRad, float maxRad )
{
  float angle = u * PI2 - PI / 2;  // используем параметр "u" для угла поворота

  float radius = minRad + (v  + 0.5f) * (maxRad - minRad);    // используем параметр "v" для радиуса

  glVertex3f(center[0] + cos(angle) * radius, center[1] + sin(angle) * radius, center[2]);  // готовченко!
}


Название: Re: QT + OpenGL
Отправлено: taifun от Ноября 12, 2009, 11:44
сфера - и опять не хватает мозгов, с 8 часов сижу :

Код:
void VMMutomo::drwShpere (const float center[3], float radius, int numU, int numV){
    if (numU < 1) numU = 1;
    if (numV < 1) numV = 1;

    float u1 = -0.5f, v1 = -0.5f;
    float du = 1.0f / numU;
    float dv = 1.0f / numV;
    float shift = radius/2;
    float startPoint[3] = { center[0] - shift, center[1] - shift, center[2] - shift};

    glBegin(GL_QUADS);
        for(int v = 0; v < numV; v++, v1+=dv){
            for(int u = 0; u < numU; u++, u1+=du){


                CalcShereVertex(u1,      v1,      u1,      center, radius);
                CalcShereVertex(u1 + du, v1,      u1 + du, center, radius);
                CalcShereVertex(u1 + du, v1 + dv, u1 + du, center, radius);
                CalcShereVertex(u1,      v1 + dv, u1,      center, radius);

            }
        }
    glEnd();
}

void VMMutomo::CalcShereVertex(float x, float y, float z, const float center[3], float radius){
    float ang1 = x * PI2 ;
    float ang2 =  ........;
    float x1 = center[0] + sin(ang1) * cos(ang2) * radius;
    float y1 = center[1] + sin(ang1) * sin(ang2) * radius;
    float z1 = center[2] + cos(ang2) * radius;
    glVertex3f(x1, y1, z1);
}


Название: Re: QT + OpenGL
Отправлено: Igors от Ноября 12, 2009, 12:12
сфера - и опять не хватает мозгов, с 8 часов сижу :
Такое самобичевание ни к чему :) Возьмите лист бумаги, нарисуйте оси XY и окружность с центром (0, 0). Это сечение сферы в плоскости XY. Поставьте точку на окружности. Если у нас есть параметр "v" [-0.5f; +0.5f] то с координатой у все ясно

y = sin(v * PI) * radius;

x и z вычисляются почти так же как и для цилиндра, разница в том что радиус переменный. Больше y - меньше радиус и наоборот. Найдите как вычислить радиус для x и z. 


Название: Re: QT + OpenGL
Отправлено: taifun от Ноября 12, 2009, 15:27
x и z вычисляются почти так же как и для цилиндра, разница в том что радиус переменный. Больше y - меньше радиус и наоборот. Найдите как вычислить радиус для x и z. 

радиус для x и z  будет radius * (-y), то есть получается так:

Код:
void CalcShereVertex(float x, float y, float z, const float center[3], float radius){
    float ang1 = x * PI2;
    float ang2 = y * PI;
    float x1 = center[0] + cos(ang1) * (radius * (-y));
    float y1 = center[1] + sin(ang2) * radius;
    float z1 = center[2] + sin(ang1) * (radius * (-y));
    glVertex3f(x1, y1, z1);
}


Название: Re: QT + OpenGL
Отправлено: Igors от Ноября 12, 2009, 15:42
радиус для x и z  будет radius * (-y), то есть получается так:
Представьте что сфера - это арбуз. Вы отрезаете скибку сверху - ее радиус маленький. А посредине - самый большой. Так что не может быть -y. Думайте


Название: Re: QT + OpenGL
Отправлено: taifun от Ноября 12, 2009, 15:56
Radius = cos(v*pi) *radius


Название: Re: QT + OpenGL
Отправлено: Igors от Ноября 12, 2009, 16:11
Radius = cos(v*pi) *radius
Молодец, правильно. И эта формула берется не с потолка, ее можно вывести. Уравнение сферы

x*x + y*y + z*z = radius*radius;

Положим radius = 1 (для сферы радиус = масштаб, домножить на него всегда успеем)

x*x + y*y + z*z = 1.0f;

Отсюда

radius_xz = sqrt(1.0f - y * y);
radius_xz = sqrt(1.0f - sin(v * PI) * sin(v * PI));
radius_xz = cos(v * PI);

Ну что, пора замахнуться на торус (бублик). Или можно отдохнуть с наложением текстур :)
Интересно также "раскрасить" модель, например u - красный цвет, v - синий


Название: Re: QT + OpenGL
Отправлено: taifun от Ноября 13, 2009, 08:45
ага, вот только закончу с сферой, вот строится полусфера:
Код:
void drwShpere (const float center[3], float radius, int numU, int numV){
    if (numU < 1) numU = 1;
    if (numV < 1) numV = 1;

    float u1 = -0.5f, v1 = -0.5f;
    float du = 1.0f / numU;
    float dv = 1.0f / numV;
    float shift = radius/2;
    float startPoint[3] = { center[0] - shift, center[1] - shift, center[2] - shift};

    glBegin(GL_QUADS);
        for(int v = 0; v < numV; v++, v1+=dv){
            for(int u = 0; u < numU; u++, u1+=du){


                CalcShereVertex(u1,      v1,      u1,      center, radius);
                CalcShereVertex(u1 + du, v1,      u1 + du, center, radius);
                CalcShereVertex(u1 + du, v1 + dv, u1 + du, center, radius);
                CalcShereVertex(u1,      v1 + dv, u1,      center, radius);

            }
        }
    glEnd();
}

void CalcShereVertex(float x, float y, float z, const float center[3], float radius){
    float ang1 = x * PI2;
    float ang2 = y * PI;
    float x1 = center[0] + sin(ang2) * cos(ang1) * radius;
    float y1 = center[1] + sin(ang2) * sin(ang1) * radius;
    float z1 = center[2] + cos(ang2) * radius;
    glVertex3f(x1, y1, z1);
}

а сфера никак ... я так полагаю чет с координатой z1 не то


Название: Re: QT + OpenGL
Отправлено: Igors от Ноября 13, 2009, 12:53
а сфера никак ... я так полагаю чет с координатой z1 не то
Ну наверное потому что Вы обозвали ее "Shere" - вот она и не хочет :)

Код:
void CalcSphereVertex(float u, float v, const float center[3], float radius)
{
    float ang1 = u * PI2 - PI / 2;
    float ang2 = v * PI;
    float x1 = center[0] + cos(ang1) * cos(ang2) * radius;
    float y1 = center[1] + sin(ang2) * radius;
    float z1 = center[2] + sin(ang1) * cos(ang2) * radius;
    glVertex3f(x1, y1, z1);
}


Название: Re: QT + OpenGL
Отправлено: taifun от Ноября 13, 2009, 14:39
блин вроде с матиматекой не все так плохо у меня было в школе, алгебра - 4, геометрию 5 вообще обожал (или может дело в том что вообще отсутствует практика работы с полигонами) .... Пока почитаю про освещение и текстуры, а то чет сфера вообще уныло выглядит без освящения, а на скриншотах на разных сайтах по ОпенЖЛ замечательно выглядит, а с понедельника или на выходных буду думать над бубликом


Название: Re: QT + OpenGL
Отправлено: Igors от Ноября 13, 2009, 15:09
блин вроде с матиматекой не все так плохо у меня было в школе, алгебра - 4, геометрию 5 вообще обожал (или может дело в том что вообще отсутствует практика работы с полигонами) ....
:) Не расстраивайтесь, 3D только кажется простым но это впечатление обманчиво.