crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> 3D пример движения над сценой
ltise
  опции профиля:
сообщение 22.2.2013, 18:17
Сообщение #1


Студент
*

Группа: Участник
Сообщений: 65
Регистрация: 17.4.2010
Пользователь №: 1636

Спасибо сказали: 0 раз(а)




Репутация:   0  


Привет!

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

неделю уже собираю примеры из разных источников - получается какая-то фигня полная :)
в примерах Qt реализации движения камеры к сожалению нету....

Мне надо сделать-то в одном месте программы визуализацию профиля по grayscale пиксмапу в качестве карты глубин... и забыть :)

Заранее спасибо

Сообщение отредактировал ltise - 22.2.2013, 22:39
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 25.2.2013, 9:16
Сообщение #2


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

Спасибо сказали: 113 раз(а)




Репутация:   8  


А как выглядит класс камеры, как рендеришь сцену из карты глубины?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ltise
  опции профиля:
сообщение 26.2.2013, 16:58
Сообщение #3


Студент
*

Группа: Участник
Сообщений: 65
Регистрация: 17.4.2010
Пользователь №: 1636

Спасибо сказали: 0 раз(а)




Репутация:   0  


Цитата(lanz @ 25.2.2013, 9:16) *
А как выглядит класс камеры, как рендеришь сцену из карты глубины?


Немного изменил пример pbuffer2:

Целиком проект тут архив:

Не врубаюсь - как настроить источник света, чтобы волна была металлической и смотрелась реалестично (материал - сталь)...
Счас вообще непойми что получается.. пробовал по разному...


void GLWidget::paintGL()
{
  saveGLState();

  makeCurrent();

  glClearColor(.0, 0.0, .0, 0.1);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glFrustum(-1, 1, -1, 1, 10, 100);
  glTranslatef(0.0f, 0.0f, -15.0f);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glViewport(0, 0, width(), height());

  glBindTexture(GL_TEXTURE_2D, dynamicTexture);
  glEnable(GL_TEXTURE_2D);
  glEnable(GL_MULTISAMPLE);
  glEnable(GL_CULL_FACE);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  const int w = logo.width();
  const int h = logo.height();

  glRotatef(rot_x, 1.0f, 0.0f, 0.0f);
  glRotatef(rot_y, 0.0f, 1.0f, 0.0f);
  glRotatef(rot_z, 0.0f, 0.0f, 1.0f);
  glScalef(scale/w, scale/w, scale/w);

  glDepthFunc(GL_LESS);
  glEnable(GL_DEPTH_TEST);

  //
  //light properties
  //
  float ambient[] = {0.0f, 0.0f, 0.0f, 1.0f};
  float diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};
  float specular[] = {1.0f, 1.0f, 1.0f, 1.0f};
  float position[] = {0.0f, 10.0f, 0, .0f};

  glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
  glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
  glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
  glLightfv(GL_LIGHT0, GL_POSITION, position);

  //
  //light model properties
  //
  float model_ambient[] = {0.4f, 0.4f, 0.4f, 1.0f};

  glLightModelfv(GL_LIGHT_MODEL_AMBIENT, model_ambient);     //small white ambient light


  //
  // meterial properties
  //
  float no_mat[] = {0.0f, 0.0f, 0.0f, 1.0f};
  float mat_ambient[] = {0.7f, 0.7f, 0.7f, 1.0f};
  float mat_diffuse[] = {0.1f, 0.5f, 0.8f, 1.0f};
  float mat_specular[] = {1.0f, 1.0f, 1.0f, 1.0f};
  float high_shininess = 100.0f;

  glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
  glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
  glMaterialf(GL_FRONT, GL_SHININESS, high_shininess);
  glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);


  //
  //draw wave
  //
  glTranslatef(-w+1, 0, 0.0f);

  for(int j=0; j < h-1; ++j)
  {

    glBegin(GL_TRIANGLE_STRIP);
    for(int i=0; i < w-1; ++i)
    {
      double x = i;
      double y = j;
      {
        GLfloat xx = x*2;
        GLfloat zz = y*2;
        int wi = y*w + x;
        GLfloat yy = wave[wi];
        glVertex3f(xx, yy, zz);
      }

      x = i+1;
      y = j;
      {
        GLfloat xx = x*2;
        GLfloat zz = y*2;
        int wi = y*w + x;
        GLfloat yy = wave[wi];
        glVertex3f(xx, yy, zz);
      }

      x = i;
      y = j+1;
      {
        GLfloat xx = x*2;
        GLfloat zz = y*2;
        int wi = y*w + x;
        GLfloat yy = wave[wi];
        glVertex3f(xx, yy, zz);
      }

      x = i+1;
      y = j+1;
      {
        GLfloat xx = x*2;
        GLfloat zz = y*2;
        int wi = y*w + x;
        GLfloat yy = wave[wi];
        glVertex3f(xx, yy, zz);
      }
    }
    glEnd();
  }

  restoreGLState();
}

Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 27.2.2013, 9:03
Сообщение #4


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

Спасибо сказали: 113 раз(а)




Репутация:   8  


Ох с чего же начать :lol:
1.
Раскрывающийся текст

void GLWidget::saveGLState()
{
  glPushAttrib(GL_ALL_ATTRIB_BITS);
  glMatrixMode(GL_PROJECTION);
  glPushMatrix();
  glMatrixMode(GL_MODELVIEW);
  glPushMatrix();
}

void GLWidget::restoreGLState()
{
  glMatrixMode(GL_PROJECTION);
  glPopMatrix();
  glMatrixMode(GL_MODELVIEW);
  glPopMatrix();
  glPopAttrib();
}


Push и Pop должны идти в разном порядке (см. как работает стек (последний пришел-первый ушел)

2. Сохранение состояния не нужны (по крайней мере сейчас)
3. Всю настройку источников света можно вынести в initializeGL
4. Чуть покрутил коэффициенты, убрал мусор
Раскрывающийся текст
void GLWidget::initializeGL()
{
    makeCurrent ();
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClearDepth(1.0f);
    glEnable (GL_NORMALIZE);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);    

    glShadeModel(GL_SMOOTH);

    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);

    // Enable light and set up 2 light sources (GL_LIGHT0 and GL_LIGHT1)
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    
    float ambientLight0[] = { 0.25f, 0.25f, 0.25f, 0.6f };
    float diffuseLight0[] = { 0.2f, 0.2f, 0.2f, 0.1f };
    float specularLight0[] = { 1.0f, 1.0f, 1.0f, 1.0f };
    float position0[] = { 0, 0, -40.0f, 1.0f };

    // Assign created components to GL_LIGHT0
    glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight0);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight0);
    glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight0);
    glLightfv(GL_LIGHT0, GL_POSITION, position0);

      //
  //light model properties
  //
  float model_ambient[] = {0.4f, 0.4f, 0.4f, 1.0f};

  glLightModelfv(GL_LIGHT_MODEL_AMBIENT, model_ambient);     //small white ambient light


  //
  // meterial properties
  //
  float no_mat[] = {0.0f, 0.0f, 0.0f, 1.0f};
  float mat_ambient[] = {0.7f, 0.7f, 0.7f, 0.1f};
  float mat_diffuse[] = {0.1f, 0.5f, 0.8f, 0.1f};
  float mat_specular[] = {1.0f, 1.0f, 1.0f, 1.0f};
  float high_shininess = 0.1f;

  glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
  glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
  glMaterialf(GL_FRONT, GL_SHININESS, high_shininess);
  glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
}

5. Что самое главное для освещения? Правильно, нормали :lol:
Примерно так, неидеально конечно:
Раскрывающийся текст
void GLWidget::paintGL()
{  
  makeCurrent();

  glClearColor(.0, 0.0, .0, 1);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glColor4f (1.0, 1.0, 1.0, 1.0);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glFrustum(-1, 1, -1, 1, 10, 100);
  glTranslatef(0.0f, 0.0f, -15.0f);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glViewport(0, 0, width(), height());
  

  const int w = logo.width();
  const int h = logo.height();
  
  glRotatef(rot_x, 1.0f, 0.0f, 0.0f);
  glRotatef(rot_y, 0.0f, 1.0f, 0.0f);
  glRotatef(rot_z, 0.0f, 0.0f, 1.0f);
  glScalef(scale/w, scale/w, scale/w);

  glTranslatef(-w+1, 0, 0.0f);

  for(int j=0; j < h-1; ++j)
  {

    glBegin(GL_TRIANGLE_STRIP);
    for(int i=0; i < w-1; ++i)
    {
      double x = i;
      double y = j;
      GLfloat v1[] = {0,0,0};
      GLfloat v2[] = {0,0,0};
      {
        GLfloat xx = x*2;
        GLfloat zz = y*2;
        int wi = y*w + x;
        GLfloat yy = wave[wi];
        glVertex3f(xx, yy, zz);
        v1[0] -= xx;
        v1[1] -= yy;
        v1[2] -= zz;
      }

      x = i+1;
      y = j;
      {
        GLfloat xx = x*2;
        GLfloat zz = y*2;
        int wi = y*w + x;
        GLfloat yy = wave[wi];
        glVertex3f(xx, yy, zz);
        v1[0] += xx;
        v1[1] += yy;
        v1[2] += zz;
        v2[0] -= xx;
        v2[1] -= yy;
        v2[2] -= zz;
      }

      x = i;
      y = j+1;
      {
        GLfloat xx = x*2;
        GLfloat zz = y*2;
        int wi = y*w + x;
        GLfloat yy = wave[wi];
        glVertex3f(xx, yy, zz);
        v2[0] += xx;
        v2[1] += yy;
        v2[2] += zz;
      }
      GLfloat normal[] = {v1[1]*v2[2] - v2[2]*v1[1], v1[2]*v2[0] - v1[0]*v2[2], v1[0]*v2[1]- v1[1]*v2[0]};
      glNormal3fv (normal);
      x = i+1;
      y = j+1;
      {
        GLfloat xx = x*2;
        GLfloat zz = y*2;
        int wi = y*w + x;
        GLfloat yy = wave[wi];
        glVertex3f(xx, yy, zz);
      }
    }
    glEnd();

  }  
  //restoreGLState();
}

6. Что почитать?
http://math.hws.edu/graphicsnotes/c4/s3.html (секция 4.3.4 очень рекомендуется)
http://www.glprogramming.com/red/chapter05.html
http://devernay.free.fr/cours/opengl/materials.html например.
7. Можно еще покрутить коэффициенты, но чтобы была реалистичная сталь, придется делать отражение (cube map например). Ну или текстуру.

Сообщение отредактировал lanz - 27.2.2013, 9:07
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ltise
  опции профиля:
сообщение 27.2.2013, 14:10
Сообщение #5


Студент
*

Группа: Участник
Сообщений: 65
Регистрация: 17.4.2010
Пользователь №: 1636

Спасибо сказали: 0 раз(а)




Репутация:   0  


Цитата(lanz @ 27.2.2013, 9:03) *
Ох с чего же начать :lol:

5. Что самое главное для освещения? Правильно, нормали :lol:



С нормалями все вроде стало понятнее, как-то я их проигнорировал..

Но я так понимаю, что нормаль должна строиться к каждому вертексу ?

Сообщение отредактировал ltise - 27.2.2013, 14:19
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 27.2.2013, 14:56
Сообщение #6


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

Спасибо сказали: 113 раз(а)




Репутация:   8  


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

Сообщение отредактировал lanz - 27.2.2013, 16:32
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ltise
  опции профиля:
сообщение 28.2.2013, 11:08
Сообщение #7


Студент
*

Группа: Участник
Сообщений: 65
Регистрация: 17.4.2010
Пользователь №: 1636

Спасибо сказали: 0 раз(а)




Репутация:   0  


lanz,
Вроде все заработало, осталось разобраться с материалами, но это уже не так критично
Раскрывающийся текст

void GLWidget::iniCam()
{
  rot_x = 152;
  rot_y -1.4;
  rot_z = 0;
  scale = 0.5;
}


void GLWidget::initializeGL()
{
  glEnable(GL_NORMALIZE);
  qglClearColor(Qt::black);
  glShadeModel (GL_SMOOTH);
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_CULL_FACE);

}


void GLWidget::resizeGL(int w , int h)
{
  glViewport(0, 0, w, h);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glMatrixMode  (GL_MODELVIEW);
  updateGL();
}



QVector3D GLWidget::vectorAt(int i, int j) const
{
  double xx = i*2;
  double zz = j*2;
  int wi = j*logo.width() + i;
  double yy = wave[wi];
  return QVector3D(xx, yy, zz);
}



void GLWidget::paintGL()
{
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  const int w = logo.width();
  const int h = logo.height();

  glMatrixMode  ( GL_MODELVIEW );
  glLoadIdentity(              );

  glRotatef(rot_x, 1.0f, 0.0f, 0.0f);
  glRotatef(rot_y, 0.0f, 1.0f, 0.0f);
  glRotatef(rot_z, 0.0f, 0.0f, 1.0f);
  glScalef(scale/w, scale/w, scale/w);

  // Light settings
  glEnable( GL_LIGHTING );

  GLfloat lightDiffuse [ 4 ] = { 0.8 , 0.8  , 0.8 , 1.0 };
  GLfloat lightAmbient [ 4 ] = { 0.8 , 0.8  , 0.8 , 1.0 };
  GLfloat lightSpecular[ 4 ] = { 0.5 , 0.8  , 0 , 1.0 };
  GLfloat lightPosition[ 4 ] = { 0.0 , 0.0 , 100.0 , 0 };

  glLightfv(GL_LIGHT1 , GL_POSITION , lightPosition);
  glLightfv(GL_LIGHT1 , GL_DIFFUSE  , lightDiffuse);
  glLightfv(GL_LIGHT1 , GL_AMBIENT  , lightAmbient);
  glLightfv(GL_LIGHT1 , GL_SPECULAR , lightSpecular);

  glEnable( GL_LIGHT1 );

  glTranslatef(-w, 0, 0.0f);

  for(int j=1; j < h-2; ++j)
  {
    glBegin(GL_TRIANGLE_STRIP);
    for(int i=1; i < w-2; ++i)
    {
      QVector3D v00 = vectorAt(i  , j);
      QVector3D v10 = vectorAt(i+1, j);
      QVector3D v11 = vectorAt(i+1, j+1);
      QVector3D v01 = vectorAt(i  , j+1);

      {
        glVertex3f(v00.x(), v00.y(), v00.z());

        QVector3D v = v00.normal(vectorAt(i+1, j-1), vectorAt(i+1, j+1), vectorAt(i-1, j-1));
        glNormal3f(v.x(), v.y(), v.z());
      }

      {
        glVertex3f(v01.x(), v01.y(), v01.z());

        QVector3D v = v01.normal(vectorAt(i+1, j-1), vectorAt(i+1, j+1), vectorAt(i-1, j-1));
        glNormal3f(v.x(), v.y(), v.z());
      }

      {
        glVertex3f(v10.x(), v10.y(), v10.z());

        QVector3D v = v10.normal(vectorAt(i+1, j-1), vectorAt(i+1, j+1), vectorAt(i-1, j-1));
        glNormal3f(v.x(), v.y(), v.z());
      }

      {
        glVertex3f(v11.x(), v11.y(), v11.z());

        QVector3D v = v11.normal(vectorAt(i+1, j-1), vectorAt(i+1, j+1), vectorAt(i-1, j-1));
        glNormal3f(v.x(), v.y(), v.z());
      }
    }
    glEnd();
  }
  swapBuffers();
}

Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 28.2.2013, 16:14
Сообщение #8


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

Спасибо сказали: 113 раз(а)




Репутация:   8  


Еще несколько мыслей:
1.
glEnable(GL_NORMALIZE);

Можно не использовать, поскольку QVector3D возвращает уже нормализованный вектор.
Будет небольшой прирост производительности.
2.
Раскрывающийся текст
  glEnable( GL_LIGHTING );

  GLfloat lightDiffuse [ 4 ] = { 0.8 , 0.8  , 0.8 , 1.0 };
  GLfloat lightAmbient [ 4 ] = { 0.8 , 0.8  , 0.8 , 1.0 };
  GLfloat lightSpecular[ 4 ] = { 0.5 , 0.8  , 0 , 1.0 };
  GLfloat lightPosition[ 4 ] = { 0.0 , 0.0 , 100.0 , 0 };

  glLightfv(GL_LIGHT1 , GL_POSITION , lightPosition);
  glLightfv(GL_LIGHT1 , GL_DIFFUSE  , lightDiffuse);
  glLightfv(GL_LIGHT1 , GL_AMBIENT  , lightAmbient);
  glLightfv(GL_LIGHT1 , GL_SPECULAR , lightSpecular);

  glEnable( GL_LIGHT1 );


Это необязательно делать каждый кадр (все таки лишнее переключение состояний).
Можно запихнуть в initializeGL.
3.
v00.normal(vectorAt(i+1, j-1), vectorAt(i+1, j+1), vectorAt(i-1, j-1));

Лучше наверное писать QVector3D::normal(...) а то немного запутывает читателя.
4.
swapBuffers();

Необязательно, т.к. QGLWidget сам свапает, после каждого вызова paintGL (если специально не отключать)
5. Ну и конечно шейдеры и VBO. Надо постепенно переходить на них (они не такие сложные как кажутся! :lol:) , с ffp нормальный материал трудно будет сделать.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 28.2.2013, 16:46
Сообщение #9


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

Спасибо сказали: 113 раз(а)




Репутация:   8  


6. Насчет вращений, лучше перемещать позицию камеры а не вращать систему координат.
При реализованном вращении будет очень неестественно - (попробуй повернуть сначала по иксу на 180, потом по игреку на 180, потом опять по иксу).

Вообще это связано с тем что вращения в OpenGL это не совсем то же самое что эйлеровы углы (после каждого вращения оси перемещаются). Еще используют кватернионы, но я делал проще.
Кусок старого кода на шарпе/OpenTK(Qt умеет все то же самое, смотри QMatrix4x4):
Раскрывающийся текст
ArchX/Y - перемещение по дуге параллельной осям экрана.

Раскрывающийся текст
    class Camera
    {
        #region Constructors
        public Camera() { }
        public Camera(Vector3 pos, Vector3 look, Vector3 up)
        {
            pos_ = pos;
            look_at_ = look;
            up_ = up;
        }
        #endregion

        public void Apply()
        {
            Matrix4 mv = Matrix4.LookAt(pos_, look_at_, up_);

            GL.MatrixMode(MatrixMode.Modelview);
            GL.LoadMatrix(ref mv);

        }

        public void ArchY(float angle)
        {
            Vector3 lv = Vector3.Subtract(pos_, look_at_);
            Matrix4 rotation = Matrix4.CreateFromAxisAngle(Vector3.Cross(up_, lv), angle);
            transformAll(rotation);
        }
        public void ArchX(float angle)
        {
            ortogonalizeUp();
            Matrix4 rotation = Matrix4.CreateFromAxisAngle(up_, angle);
            transformAll(rotation);
        }        

        #region Public properties
        public Vector3 Pos
        {
            get { return pos_; }
            set { pos_ = value; }
        }
        public Vector3 Up
        {
            get { return up_; }
            set { up_ = value; }
        }
        public Vector3 LookAt
        {
            get { return look_at_; }
            set { look_at_ = value; }
        }
        #endregion

        #region private helpers
        private void transformAll(Matrix4 rotation)
        {
            up_ = Vector3.TransformVector(up_, rotation);
            Vector3 lv = Vector3.Subtract(pos_, look_at_);
            lv = Vector3.TransformVector(lv, rotation);
            pos_ = Vector3.Add(look_at_, lv);
        }
        private void ortogonalizeUp()
        {
            Vector3 lv = Vector3.Subtract(pos_, look_at_);
            up_ = Vector3.Cross (lv, Vector3.Cross(up_, lv));
            up_.Normalize();
        }
        #endregion


Сообщение отредактировал lanz - 28.2.2013, 16:47
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 7.3.2021, 2:35