Ru-MaNGOS

Ru-MaNGOS (http://mangos.ytdb.ru/index.php)
-   Языки программирования (http://mangos.ytdb.ru/forumdisplay.php?f=34)
-   -   QT+LIB3DS [QGLViewer] (http://mangos.ytdb.ru/showthread.php?t=7128)

lovepsone 08.05.2013 17:16

QT+LIB3DS [QGLViewer]
 
Вложений: 1
Здравствуйте уважаемые пользователи!
Юзаю библиотеку QGLViewer для загрузки 3ds модели! Модель сама загружается, а текстура нет!
Вот мой код:
Код:

#ifndef _3DSVIEWER_H
#define _3DSVIEWER_H

#include <QtGui>
#include "lib3ds\file.h"
#include "lib3ds\node.h"
#include "QGLViewer\QGLViewer.h"

#define CountTexture 1

class Viewer : public QGLViewer
{
        Q_OBJECT

public:
        Viewer();

protected :
  virtual void draw();
  virtual void animate();
  virtual void init();
  virtual void keyPressEvent(QKeyEvent *e);
  virtual QString helpString() const;

  void renderNode(Lib3dsNode *node);
  void initScene();
  void loadFile();
  QImage loadBMP(QString NameBMP);
  void setTexture();

private :
        Lib3dsFile *file;
        float current_frame;
        char* camera_name;
        GLuint Texture;//[CountTexture];
        // Texture parameters
        float ratio, u_max, v_max;
        float scale_x, scale_y; // scale the texcoords, as OpenGL thinks in TEX_XSIZE and TEX_YSIZE

};

#endif // _3DSVIEWER_H

Код:

#include "3dsViewer.h"

#include "lib3ds\camera.h"
#include "lib3ds\mesh.h"
#include "lib3ds\material.h"
#include "lib3ds\matrix.h"
#include "lib3ds\vector.h"
#include "lib3ds\light.h"
#include <string.h>
#include <math.h>
#include <qfiledialog.h>

using namespace std;
using namespace qglviewer;

#define        TEX_XSIZE        1024
#define        TEX_YSIZE        1024

Viewer::Viewer() : file(NULL), current_frame(0.0), camera_name(NULL)
{
}

void Viewer::keyPressEvent(QKeyEvent *e)
{
  switch (e->key())
    {
    case Qt::Key_L : loadFile(); break;
    default:        QGLViewer::keyPressEvent(e);
    }
}

QString Viewer::helpString() const
{
  QString text("<h2>3 d s V i e w e r</h2>");
  text += "This example uses the lib3ds library to load a 3ds object file.<br><br>";
  text += "Press <b>L</b>(oad) to open a 3ds file.<br><br>";
  text += "Note that certain 3ds files contain animated sequences that can ";
  text += "be played using the <b>Return</b> (animate) key.";
  return text;
}

void Viewer::loadFile()
{
/*#if QT_VERSION < 0x040000
  QString name = QFileDialog::getOpenFileName(".", "3DS files (*.3ds *.3DS);;All files (*)", this, "Choose", "Select a 3ds model");
#else
  QString name = QFileDialog::getOpenFileName(this, "Select a 3ds model", ".", "3DS files (*.3ds *.3DS);;All files (*)");
#endif*/

        QString name("blyak.3DS");
  // In case of Cancel
  if (name.isEmpty())
    return;

#if QT_VERSION < 0x040000
  file = lib3ds_file_load(name.latin1());
#else
  file = lib3ds_file_load(name.toLatin1().constData());
#endif
    if (!file)
    {
      qWarning("Error : Unable to open file ");
      exit(1);
    }
                 
  if (file->cameras)
    camera_name = file->cameras->name;
  else
    camera_name = NULL;

  lib3ds_file_eval(file,0);

  initScene();

  float min[3], max[3];
  lib3ds_file_bounding_box(file, min, max);
  setSceneBoundingBox(Vec(min), Vec(max));
 
  if (!file->cameras)
    camera()->showEntireScene();
  else
    updateGL();
  stopAnimation();
}

QImage Viewer::loadBMP(QString NameBMP)
{
        QImage img(NameBMP);
       
        if (img.isNull())
        {
                qWarning("Unable to load file[bmp]");
                return img;
        }

        QMatrix matr;
    matr = matr.rotate(90);
    QTransform trans(matr);
    img.transformed(trans);
        //img.
        // 1E-3 needed. Just try with width=128 and see !
        /*int newWidth  = 1<<(int)(1+log(img.width() -1+1E-3) / log(2.0));
        int newHeight = 1<<(int)(1+log(img.height()-1+1E-3) / log(2.0));

        u_max = img.width()  / (float)newWidth;
        v_max = img.height() / (float)newHeight;

        if ((img.width()!=newWidth) || (img.height()!=newHeight))
        {
                qWarning("Image size set to %dx%d pixels", newWidth, newHeight);
                img = img.copy(0, 0, newWidth, newHeight);
        }

        ratio = newWidth / float(newHeight);*/

        return QGLWidget::convertToGLFormat(img);  // flipped 32bit RGBA
}

void Viewer::setTexture()
{
        QImage glImg = loadBMP("blyak.bmp");
       
        if(glImg.isNull())
                return;

        Texture = bindTexture(glImg, GL_TEXTURE_2D);
        //glBindTexture(GL_TEXTURE_2D, Texture);
        glTexImage2D(GL_TEXTURE_2D, 0, 4, glImg.width(), glImg.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, glImg.bits());
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
        scale_x = (float)glImg.width()/(float)TEX_XSIZE;
        scale_y = (float)glImg.height()/(float)TEX_YSIZE;
}

void Viewer::init()
{
        // Texture parameters
        u_max = 1.0;
        v_max = 1.0;
        ratio = 1.0;

  glShadeModel(GL_SMOOTH);
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  glDisable(GL_LIGHT1);
  glDepthFunc(GL_LEQUAL);
  glEnable(GL_DEPTH_TEST);
  glDisable(GL_COLOR_MATERIAL);
  glEnable(GL_CULL_FACE);
  glCullFace(GL_BACK);
  //glEnable(GL_TEXTURE_2D);

        // Enable GL textures
        //glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        //glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glEnable(GL_TEXTURE_2D);
       
        // Nice texture coordinate interpolation
        glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );

  setKeyDescription(Qt::Key_L, "Loads a new 3ds file");

  restoreStateFromFile();
  //help();
  setTexture();
  loadFile();
}

void Viewer::initScene()
{
  if (!file)
    return;

  // Lights
  GLfloat amb[] = {0.0, 0.0, 0.0, 1.0};
  GLfloat dif[] = {1.0, 1.0, 1.0, 1.0};
  GLfloat spe[] = {1.0, 1.0, 1.0, 1.0};
  GLfloat pos[] = {0.0, 0.0, 0.0, 1.0};
  int li=GL_LIGHT0;
  for (Lib3dsLight* l=file->lights; l; l=l->next)
    {
      glEnable(li);

      glLightfv(li, GL_AMBIENT,  amb);
      glLightfv(li, GL_DIFFUSE,  dif);
      glLightfv(li, GL_SPECULAR, spe);

      pos[0] = l->position[0];
      pos[1] = l->position[1];
      pos[2] = l->position[2];
      glLightfv(li, GL_POSITION, pos);

      if (!l->spot_light)
          continue;

      pos[0] = l->spot[0] - l->position[0];
      pos[1] = l->spot[1] - l->position[1];
      pos[2] = l->spot[2] - l->position[2];
      glLightfv(li, GL_SPOT_DIRECTION, pos);
      ++li;
    }

  // Camera
  Lib3dsNode* c = lib3ds_file_node_by_name(file, camera_name, LIB3DS_CAMERA_NODE);
  Lib3dsNode* t = lib3ds_file_node_by_name(file, camera_name, LIB3DS_TARGET_NODE);
  if (!c || !t)
    return;

  Lib3dsMatrix M;
  lib3ds_matrix_camera(M, c->data.camera.pos, t->data.target.pos, c->data.camera.roll);

  // cout << "Pos = " << Vec(c->data.camera.pos) << endl;
  // cout << "Tar = " << Vec(t->data.target.pos) << endl;
  // cout << "Rol = " << c->data.camera.roll << endl;

  camera()->setPosition(Vec(c->data.camera.pos));
  camera()->lookAt(Vec(t->data.target.pos));
  Vec up=camera()->frame()->transformOf(Vec(0.0, 0.0, 1.0));
  float angle=atan2(up.x, up.y);
  Quaternion q(Vec(0.0, 0.0, 1.0), c->data.camera.roll-angle);
  camera()->frame()->rotate(q);
  camera()->setFieldOfView(M_PI/180.0*c->data.camera.fov);
  glRotatef(-90, 1.0,0,0);
}

void Viewer::renderNode(Lib3dsNode *node)
{
  for (Lib3dsNode* p=node->childs; p!=0; p=p->next)
    renderNode(p);

  if (node->type == LIB3DS_OBJECT_NODE)
    {
      if (strcmp(node->name,"$$$DUMMY")==0)
        return;

      if (!node->user.d)
        {
          Lib3dsMesh *mesh=lib3ds_file_mesh_by_name(file, node->name);
          if (!mesh)
            return;

          node->user.d = glGenLists(1);
          glNewList(node->user.d, GL_COMPILE);

          Lib3dsVector *normalL = new Lib3dsVector[3*mesh->faces];

          Lib3dsMatrix M;
          lib3ds_matrix_copy(M, mesh->matrix);
          lib3ds_matrix_inv(M);
          glMultMatrixf(&M[0][0]);

          lib3ds_mesh_calculate_normals(mesh, normalL);

          for (unsigned int p=0; p<mesh->faces; ++p)
            {
              Lib3dsFace *f=&mesh->faceL[p];
              Lib3dsMaterial *mat=0;
              if (f->material[0])
                mat=lib3ds_file_material_by_name(file, f->material);

              if (mat)
                {
                  static GLfloat a[4]={0,0,0,1};
                  float s;
                  glMaterialfv(GL_FRONT, GL_AMBIENT, a);
                  glMaterialfv(GL_FRONT, GL_DIFFUSE, mat->diffuse);
                  glMaterialfv(GL_FRONT, GL_SPECULAR, mat->specular);
                  s = pow(2, 10.0*mat->shininess);
                  if (s>128.0)
                    s=128.0;
                  glMaterialf(GL_FRONT, GL_SHININESS, s);
                }
              else
                {
                  Lib3dsRgba a={0.2, 0.2, 0.2, 1.0};
                  Lib3dsRgba d={0.8, 0.8, 0.8, 1.0};
                  Lib3dsRgba s={0.0, 0.0, 0.0, 1.0};
                  glMaterialfv(GL_FRONT, GL_AMBIENT, a);
                  glMaterialfv(GL_FRONT, GL_DIFFUSE, d);
                  glMaterialfv(GL_FRONT, GL_SPECULAR, s);
                }

                glBindTexture(GL_TEXTURE_2D, Texture);
              glBegin(GL_TRIANGLES);
              glNormal3fv(f->normal);
              for (int i=0; i<3; ++i)
                {
                  glNormal3fv(normalL[3*p+i]);

                        glTexCoord2f(mesh->texelL[f->points[i]][1]*scale_x, scale_y - mesh->texelL[f->points[i]][0]*scale_y);
        //glTexCoord2f(mesh->texelL[f->points[i]][1], mesh->texelL[f->points[i]][0]);
                  glVertex3fv(mesh->pointL[f->points[i]].pos);
                }
              glEnd();
            }

          delete[] normalL;

          glEndList();
        }

      if (node->user.d)
        {
          glPushMatrix();
          Lib3dsObjectData* d = &node->data.object;
          glMultMatrixf(&node->matrix[0][0]);
          glTranslatef(-d->pivot[0], -d->pivot[1], -d->pivot[2]);
          glCallList(node->user.d);
          glPopMatrix();
        }
    }
}

void Viewer::draw()
{
  if (!file)
    return;

  glBindTexture(GL_TEXTURE_2D, Texture);
  /*glNormal3f(0.0, 0.0, 1.0);
  glBegin(GL_QUADS);
  glTexCoord2f(0.0,  1.0-v_max);
  //glVertex2f(-u_max*ratio,-v_max);
  glTexCoord2f(0.0,  1.0);
  //glVertex2f(-u_max*ratio, v_max);
  glTexCoord2f(u_max, 1.0);
  //glVertex2f( u_max*ratio, v_max);
  glTexCoord2f(u_max, 1.0-v_max);
  //glVertex2f( u_max*ratio,-v_max);
  glEnd();*/

        for (Lib3dsNode* p=file->nodes; p!=0; p=p->next)
                renderNode(p);
}


void Viewer::animate()
{
  current_frame++;
  if (current_frame > file->frames)
    current_frame=0;
  lib3ds_file_eval(file, current_frame);
  initScene();
}


Opengl пока разбираю и опыта нет. Мб кто поможет?

Sid 09.05.2013 14:32

Чувак, я твой фанат теперь :D Я давно эту идею вынашиваю, написать собственый модельвивер на qt :)

lovepsone 09.05.2013 18:03

Цитата:

Сообщение от Sid (Сообщение 31353)
Чувак, я твой фанат теперь :D Я давно эту идею вынашиваю, написать собственый модельвивер на qt :)

Да вот пока с Opengl изучаю + в Qt интегрирую! Вот тока пока проблем выше крыши!

Evgeniy 10.05.2013 10:21

glBindTexture после glGenLists...не?
Даже не после а внутри блока....и тестурку выбрать клетчатую салатовую, что бы наверняка знать грузится-нет.

lovepsone 11.05.2013 17:40

Обновил первый пост!Вроде теперь текстура загружается, но моделька отображается черным цветом!
Смотрите скрин ниже в первом посте!

Я даже нарисовал куб и попытался наложить текстуру, но нечего не вышло! Значит я чего-то не знаю... Буду думать.

Sid 11.05.2013 20:00

Альфа канал указал верно? Я помню когда делал для m2 то текстура blp в RGBA не отображалась, потом выставил альфа на максимум и все появилось :) Долго ломал тогда голову )

lovepsone 15.05.2013 21:59

Текстуру удалось наложить, но есть некоторые проблемы!
Я поворачиваю камеру на 90 градусов( Что бы модель стояла правильно по координатам х,у.z, т.е стояла ровно)! При таком раскладе я налаживаю текстуру и... Текстура ложится прямо а не по вершинам указанных в 3ds файле! Далее пришлось посчитать вершины текстуры, в итоге по коду вышло так:
Код:

glBindTexture(GL_TEXTURE_2D, Texture);
glBegin(GL_TRIANGLES);
glNormal3fv(f->normal);
for (int i=0; i<3; ++i)
{
    glNormal3fv(normalL[3*p+i]);

    glTexCoord2f(mesh->texelL[f->points[i]][1]*scale_x, scale_y - mesh->texelL[f->points[i]][0]*scale_y);
    glVertex3fv(mesh->pointL[f->points[i]].pos);
}
glEnd();

И что вы думаете? Не получилось... Далее я полез в фотошоп и повернул текстуру на 90 градусов по часовой... Все ок! Текстура легла как надо!!!
Меня это не устроило и попробовал поворачивать текстуру перед наложением на модель(в самом коде). Сделал так:
Код:

QImage Viewer::loadBMP(QString NameBMP)
{
    QImage img(NameBMP);
       
    if (img.isNull())
    {
        qWarning("Unable to load file[bmp]");
        return img;
    }

    QMatrix matr;
    matr = matr.rotate(90);
    QTransform trans(matr);
    img.transformed(trans); // переменная img типа QImage, в которой помещена текстура формата .bmp

    return QGLWidget::convertToGLFormat(img);  // flipped 32bit RGBA

}

Но текстура так и не повернулась... Код в первом посте обновлен!

Evgeniy 15.05.2013 22:55

Код:

glPushMatrix();
glTranslatef
glRotatef
Draw()
glPopMatrix();

Всегда вращай и двигай объект, а не камеру ...тогда не надо пересчитывать все координаты (всмысле тектурные, нормали и т.п.)...

lovepsone 16.05.2013 13:21

Завтра буду дома, постараюсь доделать! Код вполне рабочий, но нужно оптимизировать... Всем спасибо!


Текущее время: 12:32. Часовой пояс GMT +3.

ru-mangos.ru - Русское сообщество MaNGOS