<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>libQGLViewer 3dsViewer example</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <link href="../qglviewer.css" rel="stylesheet" type="text/css" /> <link rel="shortcut icon" href="../images/qglviewer.ico" type="image/x-icon" /> <link rel="icon" href="../images/qglviewer.icon.png" type="image/png" /> </head> <body> <table class="banner"> <tr> <td align="center"><a href="../index.html"><b>Home</b></a></td> <td align="center"><a href="../refManual/hierarchy.html"><b>Documentation</b></a></td> <td align="center"><a href="../download.html"><b>Download</b></a></td> <td align="center" class="qindexHL"><a href="index.html"><b>Screenshots</b></a></td> <td align="center"><a href="../developer.html"><b>Developer</b></a></td> </tr> </table> <h1>The 3dsViewer example</h1> <center> <img src="../images/3dsViewer.jpg" width="300" height="200" alt="3dsViewer"/> </center> <p> The LGPL lib3ds library is used to load and display a 3ds scene. </p> <p> You need to install the lib3ds library (version 1.2) in order to compile this file. See <a href="http://lib3ds.sourceforge.net/">http://lib3ds.sourceforge.net/</a>. </p> <p> The current version (Ver 1.2, Dec 2002) of the lib3ds library is flawed and a patched version is available on the <a href="../rpm.html">libQGLViewer rpm page</a>. </p> <p> Alternately, you can add the following line in <code>lib3ds/file.h</code> : extern LIB3DSAPI void lib3ds_file_bounding_box(Lib3dsFile *file, Lib3dsVector min, Lib3dsVector max); </p> <p> Once this is done, edit <code>3dsViewer.pro</code>, set <code>LIB3DS_IS_INSTALLED</code> to <code>yes</code> and set <code>INCLUDEPATH</code> and <code>LIBS</code> to the path where you installed lib3ds. </p> <p> Press '<b>L</b>' (load) to load a new 3DS scene. </p> <h2>3dsViewer.h</h2> <pre> <span class="dir">#include <QGLViewer/qglviewer.h> </span> <span class="dir">#include <lib3ds/file.h> </span><span class="dir">#include <lib3ds/node.h> </span> <span class="key">class </span>Viewer : <span class="key">public </span>QGLViewer { <span class="key">public </span>: Viewer() : file(NULL), current_frame(<span class="num">0.0</span>), camera_name(NULL) {}; <span class="key">protected </span>: <span class="key">virtual </span><span class="typ">void </span>draw(); <span class="key">virtual </span><span class="typ">void </span>animate(); <span class="key">virtual </span><span class="typ">void </span>init(); <span class="key">virtual </span><span class="typ">void </span>keyPressEvent(QKeyEvent *e); <span class="key">virtual </span>QString helpString() <span class="typ">const</span>; <span class="typ">void </span>renderNode(Lib3dsNode *node); <span class="typ">void </span>loadFile(); <span class="typ">void </span>initScene(); <span class="key">private </span>: Lib3dsFile *file; <span class="typ">float </span>current_frame; <span class="typ">char</span>* camera_name; };</pre> <h2>3dsViewer.cpp</h2> <pre> <span class="dir">#include </span><span class="dstr">"3dsViewer.h"</span><span class="dir"> </span> <span class="dir">#include <lib3ds/camera.h> </span><span class="dir">#include <lib3ds/mesh.h> </span><span class="dir">#include <lib3ds/material.h> </span><span class="dir">#include <lib3ds/matrix.h> </span><span class="dir">#include <lib3ds/vector.h> </span><span class="dir">#include <lib3ds/light.h> </span><span class="dir">#include <string.h> </span><span class="dir">#include <stdlib.h> </span><span class="dir">#include <math.h> </span><span class="dir">#include <qfiledialog.h> </span> <span class="key">using namespace </span>std; <span class="key">using namespace </span>qglviewer; <span class="typ">void </span>Viewer::keyPressEvent(QKeyEvent *e) { <span class="key">switch </span>(e->key()) { <span class="key">case </span>Qt::Key_L : loadFile(); <span class="key">break</span>; <span class="key">default</span>: QGLViewer::keyPressEvent(e); } } QString Viewer::helpString() <span class="typ">const </span>{ QString text(<span class="str">"<h2>3 d s V i e w e r</h2>"</span>); text += <span class="str">"This example uses the lib3ds library to load a 3ds object file. "</span>; text += <span class="str">"Press <b>L</b>(oad) to open a 3ds file. "</span>; text += <span class="str">"Note that certain 3ds files contain animated sequences that can "</span>; text += <span class="str">"be played using the <b>Return</b> (animate) key."</span>; <span class="key">return </span>text; } <span class="typ">void </span>Viewer::loadFile() { QString name = QFileDialog::getOpenFileName(<span class="str">""</span>, <span class="str">"3DS files (*.3ds *.3DS);;All files (*)"</span>, <span class="key">this</span>); <span class="com">// In case of Cancel </span> <span class="key">if </span>(name.isEmpty()) <span class="key">return</span>; file = lib3ds_file_load(name.latin1()); <span class="key">if </span>(!file) { cout << <span class="str">"Error : Unable to open file "</span> << name << endl; exit(<span class="num">1</span>); } <span class="key">if </span>(file->cameras) camera_name = file->cameras->name; <span class="key">else </span>camera_name = NULL; lib3ds_file_eval(file,<span class="num">0</span>); initScene(); <span class="typ">float </span>min[<span class="num">3</span>], max[<span class="num">3</span>]; lib3ds_file_bounding_box(file, min, max); setSceneBoundingBox(Vec(min), Vec(max)); <span class="key">if </span>(!file->cameras) camera()->showEntireScene(); <span class="key">else </span>updateGL(); stopAnimation(); } <span class="typ">void </span>Viewer::init() { 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); restoreFromFile(); help(); loadFile(); } <span class="typ">void </span>Viewer::initScene() { <span class="key">if </span>(!file) <span class="key">return</span>; <span class="com">// Lights </span> GLfloat amb[] = {<span class="num">0.0</span>, <span class="num">0.0</span>, <span class="num">0.0</span>, <span class="num">1.0</span>}; GLfloat dif[] = {<span class="num">1.0</span>, <span class="num">1.0</span>, <span class="num">1.0</span>, <span class="num">1.0</span>}; GLfloat spe[] = {<span class="num">1.0</span>, <span class="num">1.0</span>, <span class="num">1.0</span>, <span class="num">1.0</span>}; GLfloat pos[] = {<span class="num">0.0</span>, <span class="num">0.0</span>, <span class="num">0.0</span>, <span class="num">1.0</span>}; <span class="typ">int </span>li=GL_LIGHT0; <span class="key">for </span>(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[<span class="num">0</span>] = l->position[<span class="num">0</span>]; pos[<span class="num">1</span>] = l->position[<span class="num">1</span>]; pos[<span class="num">2</span>] = l->position[<span class="num">2</span>]; glLightfv(li, GL_POSITION, pos); <span class="key">if </span>(!l->spot_light) <span class="key">continue</span>; pos[<span class="num">0</span>] = l->spot[<span class="num">0</span>] - l->position[<span class="num">0</span>]; pos[<span class="num">1</span>] = l->spot[<span class="num">1</span>] - l->position[<span class="num">1</span>]; pos[<span class="num">2</span>] = l->spot[<span class="num">2</span>] - l->position[<span class="num">2</span>]; glLightfv(li, GL_SPOT_DIRECTION, pos); ++li; } <span class="com">// Camera </span> 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); <span class="key">if </span>(!c || !t) <span class="key">return</span>; <span class="com">// Lib3dsMatrix M; </span> <span class="com">// lib3ds_matrix_camera(M, c->data.camera.pos, t->data.target.pos, c->data.camera.roll); </span> <span class="com">// cout << "Pos = " << Vec(c->data.camera.pos) << endl; </span> <span class="com">// cout << "Tar = " << Vec(t->data.target.pos) << endl; </span> <span class="com">// cout << "Rol = " << c->data.camera.roll << endl; </span> camera()->setPosition(Vec(c->data.camera.pos)); camera()->lookAt(Vec(t->data.target.pos)); Vec up=camera()->frame()->transformOf(Vec(<span class="num">0.0</span>, <span class="num">0.0</span>, <span class="num">1.0</span>)); <span class="typ">float </span>angle=atan2(up.x, up.y); Quaternion q(Vec(<span class="num">0.0</span>, <span class="num">0.0</span>, <span class="num">1.0</span>), c->data.camera.roll-angle); camera()->frame()->rotate(q); camera()->setFieldOfView(M_PI/<span class="num">180.0</span>*c->data.camera.fov); } <span class="typ">void </span>Viewer::renderNode(Lib3dsNode *node) { <span class="key">for </span>(Lib3dsNode* p=node->childs; p!=<span class="num">0</span>; p=p->next) renderNode(p); <span class="key">if </span>(node->type == LIB3DS_OBJECT_NODE) { <span class="key">if </span>(strcmp(node->name,<span class="str">"$$$DUMMY"</span>)==<span class="num">0</span>) <span class="key">return</span>; <span class="key">if </span>(!node->user.d) { Lib3dsMesh *mesh=lib3ds_file_mesh_by_name(file, node->name); <span class="key">if </span>(!mesh) <span class="key">return</span>; node->user.d = glGenLists(<span class="num">1</span>); glNewList(node->user.d, GL_COMPILE); Lib3dsVector *normalL = <span class="key">new </span>Lib3dsVector[<span class="num">3</span>*mesh->faces]; Lib3dsMatrix M; lib3ds_matrix_copy(M, mesh->matrix); lib3ds_matrix_inv(M); glMultMatrixf(&M[<span class="num">0</span>][<span class="num">0</span>]); lib3ds_mesh_calculate_normals(mesh, normalL); <span class="key">for </span>(<span class="typ">unsigned int </span>p=<span class="num">0</span>; p<mesh->faces; ++p) { Lib3dsFace *f=&mesh->faceL[p]; Lib3dsMaterial *mat=<span class="num">0</span>; <span class="key">if </span>(f->material[<span class="num">0</span>]) mat=lib3ds_file_material_by_name(file, f->material); <span class="key">if </span>(mat) { <span class="typ">static </span>GLfloat a[<span class="num">4</span>]={<span class="num">0</span>,<span class="num">0</span>,<span class="num">0</span>,<span class="num">1</span>}; <span class="typ">float </span>s; glMaterialfv(GL_FRONT, GL_AMBIENT, a); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat->diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat->specular); s = pow(<span class="num">2</span>, <span class="num">10.0</span>*mat->shininess); <span class="key">if </span>(s><span class="num">128.0</span>) s=<span class="num">128.0</span>; glMaterialf(GL_FRONT, GL_SHININESS, s); } <span class="key">else </span>{ Lib3dsRgba a={<span class="num">0.2</span>, <span class="num">0.2</span>, <span class="num">0.2</span>, <span class="num">1.0</span>}; Lib3dsRgba d={<span class="num">0.8</span>, <span class="num">0.8</span>, <span class="num">0.8</span>, <span class="num">1.0</span>}; Lib3dsRgba s={<span class="num">0.0</span>, <span class="num">0.0</span>, <span class="num">0.0</span>, <span class="num">1.0</span>}; glMaterialfv(GL_FRONT, GL_AMBIENT, a); glMaterialfv(GL_FRONT, GL_DIFFUSE, d); glMaterialfv(GL_FRONT, GL_SPECULAR, s); } glBegin(GL_TRIANGLES); glNormal3fv(f->normal); <span class="key">for </span>(<span class="typ">int </span>i=<span class="num">0</span>; i<<span class="num">3</span>; ++i) { glNormal3fv(normalL[<span class="num">3</span>*p+i]); glVertex3fv(mesh->pointL[f->points[i]].pos); } glEnd(); } <span class="key">delete</span>[] normalL; glEndList(); } <span class="key">if </span>(node->user.d) { glPushMatrix(); Lib3dsObjectData* d = &node->data.object; glMultMatrixf(&node->matrix[<span class="num">0</span>][<span class="num">0</span>]); glTranslatef(-d->pivot[<span class="num">0</span>], -d->pivot[<span class="num">1</span>], -d->pivot[<span class="num">2</span>]); glCallList(node->user.d); glPopMatrix(); } } } <span class="typ">void </span>Viewer::draw() { <span class="key">if </span>(!file) <span class="key">return</span>; <span class="key">for </span>(Lib3dsNode* p=file->nodes; p!=<span class="num">0</span>; p=p->next) renderNode(p); } <span class="typ">void </span>Viewer::animate() { current_frame++; <span class="key">if </span>(current_frame > file->frames) current_frame=<span class="num">0</span>; lib3ds_file_eval(file, current_frame); initScene(); }</pre> <h2>main.cpp</h2> <pre> <span class="dir">#include </span><span class="dstr">"3dsViewer.h"</span><span class="dir"> </span><span class="dir">#include <qapplication.h> </span> <span class="typ">int </span>main(<span class="typ">int </span>argc, <span class="typ">char</span>** argv) { <span class="com">// Read command lines arguments. </span> QApplication application(argc,argv); <span class="com">// Instantiate the viewer, show it on screen. </span> Viewer viewer; viewer.show(); <span class="com">// Set the viewer as the application main widget. </span> application.setMainWidget(&viewer); <span class="com">// Run main loop. </span> <span class="key">return </span>application.exec(); }</pre> <p> <a href="index.html">Go back</a> to the examples main page </p> <p> <a href="http://validator.w3.org/check/referer"><img src="../images/xhtml.png" alt="Valid XHTML 1.0!" height="31" width="88" border="0"/></a> <a href="http://jigsaw.w3.org/css-validator/check/referer"><img src="../images/css.png" width="88" height="31" alt="Valid CSS!" border="0"/></a> <i>Last modified on Thursday, February 5, 2004.</i> </p> </body> </html>