lovepsone
08.05.2013, 17:16
Здравствуйте уважаемые пользователи!
Юзаю библиотеку 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_FILTE R,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTE R,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 пока разбираю и опыта нет. Мб кто поможет?
Юзаю библиотеку 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_FILTE R,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTE R,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 пока разбираю и опыта нет. Мб кто поможет?