summaryrefslogtreecommitdiffstats
path: root/src/plugins/sceneformats/3ds/qgl3dsmesh.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/sceneformats/3ds/qgl3dsmesh.cpp')
-rw-r--r--src/plugins/sceneformats/3ds/qgl3dsmesh.cpp755
1 files changed, 0 insertions, 755 deletions
diff --git a/src/plugins/sceneformats/3ds/qgl3dsmesh.cpp b/src/plugins/sceneformats/3ds/qgl3dsmesh.cpp
deleted file mode 100644
index 97b72f71..00000000
--- a/src/plugins/sceneformats/3ds/qgl3dsmesh.cpp
+++ /dev/null
@@ -1,755 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtQuick3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qgl3dsmesh.h"
-#include "qglmaterialcollection.h"
-#include "qglsection_p.h"
-#include "qarray.h"
-#include "qvector_utils_p.h"
-
-#include <lib3ds/mesh.h>
-#include <lib3ds/material.h>
-#include <lib3ds/vector.h>
-#include <lib3ds/types.h>
-
-#include <QtGui/qmatrix4x4.h>
-#include <QtCore/qmath.h>
-
-// Faceted meshes look terrible when they have more than a small number
-// of faces. Usually if large meshes are faceted its some kind of error
-// in the model, or in importing of the model by lib3ds. Force on
-// smoothing when greater than this many faces are detected.
-#define FACETED_THRESHOLD 1000
-
-// Two faces that have an angle between their plane vectors with a cosine
-// less than this are judged to form a sharp (acute) angle.
-// -ve cosine (less than 0.0f) means 90 degrees or sharper like the sides
-// of a rectangular prism so this is a good value.
-#define ACUTE -0.0001f
-
-// Two vectors that have an angle between them with a cosine less than this
-// value are judged to be approximately the inverse of each other, for the
-// purposes of determining whether a normal has been inverted or not
-#define INVERSE -0.20f
-
-// Only try to correct normals if this many neighbour faces contribute to
-// the assessment. 2 or 3 are good values. 4 or greater is the same as
-// defining DO_NORMAL_CORRECT false
-#define AVG_CNT 2
-
-// make a QVector3D from a Lib3dsVector - by a hard cast. Its required
-// that QVector3D behave like a POD type - float[3] - for all of the
-// OpenGL stuff
-static inline QVector3D &l2v(Lib3dsVector &vec)
-{
- return reinterpret_cast<QVector3D&>(vec);
-}
-
-// is this a null 3ds vector - same as QVector3D::isNull()
-static inline bool qIsNull(const Lib3dsVector &vec)
-{
- return (qIsNull(vec[0]) && qIsNull(vec[1]) && qIsNull(vec[2]));
-}
-
-static inline bool qFskCompare(const Lib3dsVector &a, const Lib3dsVector &b)
-{
- return (qFskCompare(a[0], b[0]) && qFskCompare(a[1], b[1]) && qFskCompare(a[2], b[2]));
-}
-
-// find the normalized plane vector, that is a unit vector perpendicular
-// to the plane of the face. this is the same thing as the default normal
-static inline void planeVec(Lib3dsFace *face, Lib3dsPoint *pointList, Lib3dsVector result)
-{
- Lib3dsVector &l3a = pointList[face->points[0]].pos;
- Lib3dsVector &l3b = pointList[face->points[1]].pos;
- Lib3dsVector &l3c = pointList[face->points[2]].pos;
- lib3ds_vector_normal(result, l3a, l3b, l3c);
-}
-
-struct ModulateRecord
-{
- bool disabled;
- bool keyFresh;
- int facesProcessed;
- int numModulated;
- Lib3dsDword altKey;
- Lib3dsDword key;
-};
-
-QGL3dsMesh::QGL3dsMesh(Lib3dsMesh *mesh, QGLMaterialCollection *materials)
- : QGLBuilder(materials)
- , m_mesh(mesh)
- , m_texFlip(false)
- , m_hasZeroSmoothing(false)
- , m_faceMap(0)
-{
-}
-
-QGL3dsMesh::~QGL3dsMesh()
-{
- delete[] m_faceMap;
-}
-
-void QGL3dsMesh::processNodeForMaterial(int matIx, QGLSceneNode *node)
-{
- QGLSceneNode *s = sceneNode();
- QString baseName = s->objectName();
- node->setMaterialIndex(matIx);
- node->setObjectName(baseName + QLatin1String("::") +
- ((matIx == -1)
- ? QLatin1String("No_Material")
- : s->palette()->materialName(matIx)));
- checkTextures(matIx);
- generateVertices();
- s->palette()->markMaterialAsUsed(matIx);
-}
-
-void QGL3dsMesh::initAdjacencyMap()
-{
- Lib3dsFace *face;
- m_faceMap = new FacePtr[m_mesh->faces * 3];
- qMemSet(m_faceMap, 0, sizeof(m_faceMap));
- for (Lib3dsDword f = 0; f < m_mesh->faces; ++f)
- {
- face = &m_mesh->faceL[f];
- planeVec(face, m_mesh->pointL, face->normal);
- m_mesh->faceL[f].user.p = &m_faceMap[f*3];
- }
-}
-
-void QGL3dsMesh::initialize()
-{
- QGLSceneNode *s = sceneNode();
- s->setObjectName(QString::fromLatin1(m_mesh->name));
- if ((m_options & QGL::ForceSmooth) && (m_options & QGL::ForceFaceted))
- {
- if (m_options & QGL::ShowWarnings)
- qWarning("Both smooth and faceted forced on for %s: forcing smooth\n",
- m_mesh->name);
- m_options &= ~QGL::ForceFaceted;
- }
- initAdjacencyMap();
- if (m_options & (QGL::CorrectNormals | QGL::CorrectAcute))
- modulateMesh();
- analyzeMesh();
-
- if (m_smoothingGroups == 0)
- {
- bool forceSmooth = (m_options & QGL::ForceSmooth);
- if (!forceSmooth && m_mesh->faces > FACETED_THRESHOLD)
- {
- if (m_options & QGL::ShowWarnings)
- qWarning("Mesh %s has %d faces (threshold is %d):"
- "forcing smooth render", m_mesh->name, m_mesh->faces,
- FACETED_THRESHOLD);
- forceSmooth = true;
- }
- if (forceSmooth)
- {
- for (Lib3dsDword f = 0; f < m_mesh->faces; ++f)
- m_mesh->faceL[f].smoothing = 1;
- analyzeMesh();
- }
- }
-
- bool mixedTexturedAndPlain = m_plainMaterials.count() > 0 &&
- m_textureMaterials.count() > 0;
-
- s->setLocalTransform(meshMatrix());
-
- // start a new section and node
- newSection(m_smoothingGroups ? QGL::Smooth : QGL::Faceted);
- QGLSceneNode *node = currentNode();
-
- // process all the plain materials first, then textured to avoid effect swapping
- QList<int> matList = m_plainMaterials.toList();
- if (mixedTexturedAndPlain)
- {
- node->setEffect(QGL::LitMaterial);
- node->setObjectName(s->objectName() + QLatin1String("::Materials"));
- //qDebug() << ">>> mixed:" << node;
- pushNode();
- //qDebug() << " pushed - current now:" << currentNode();
- }
- else
- {
- s->setEffect(m_textureMaterials.count() > 0 ? QGL::LitModulateTexture2D : QGL::LitMaterial);
- }
- //qDebug() << "processing:" << matList.count() << "materials";
- while (matList.count() > 0)
- {
- int matIx = matList.takeFirst();
- processNodeForMaterial(matIx, node);
- if (matList.count() > 0)
- node = newNode();
- }
- matList = m_textureMaterials.toList();
- if (mixedTexturedAndPlain)
- {
- //qDebug() << "<<< mixed:" << currentNode();
- popNode();
- //qDebug() << " popped - current now:" << currentNode();
- node = currentNode();
- node->setEffect(QGL::LitModulateTexture2D);
- node->setObjectName(s->objectName() + QLatin1String("::Textures"));
- }
- while (matList.count() > 0)
- {
- int matIx = matList.takeFirst();
- processNodeForMaterial(matIx, node);
- if (matList.count() > 0)
- node = newNode();
- }
-}
-
-// Build a linked list, in a QArray: the first N*2 entries correspond
-// to the N vertices: for each n'th vertex, n*2 is the face number,
-// n*2+1is the index of the next entry for that vertex, or -1 if there
-// is no next entry.
-//
-// While on the job find the smoothing keys and store in allKeys.
-//
-// And zero out the user data pointer for each face, and calculate the
-// smoothing group count.
-QArray<int> QGL3dsMesh::mapFacesToVerts(Lib3dsDword *allKeys)
-{
- Lib3dsFace *face;
- QArray<int> vlist(m_mesh->points * 2, -1);
- int nx = 2 * m_mesh->points;
- m_smoothingGroupCount = 0;
- for (Lib3dsDword f = 0; f < m_mesh->faces; ++f)
- {
- face = &m_mesh->faceL[f];
- if (face->smoothing)
- {
- if (!(face->smoothing & *allKeys))
- {
- *allKeys |= face->smoothing;
- m_smoothingGroupCount += 1;
- }
- }
- for (int i = 0; i < 3; ++i)
- {
- int v = face->points[i];
- int ptr = v*2;
- int prv = -1;
- if (vlist[ptr] != -1)
- {
- prv = ptr;
- while (vlist[ptr+1] != -1)
- {
- ptr = vlist[ptr+1];
- prv = ptr;
- }
- ptr = nx;
- vlist.extend(2);
- nx += 2;
- }
- vlist[ptr] = f;
- vlist[ptr+1] = -1;
- if (prv != -1)
- vlist[prv+1] = ptr;
- }
- }
- return vlist;
-}
-
-void QGL3dsMesh::addToAdjacencyMap(Lib3dsFace *face, Lib3dsFace *neighbour)
-{
- Q_ASSERT(face);
- Q_ASSERT(face->user.p);
- Q_ASSERT(neighbour);
- FacePtr *h = static_cast<FacePtr*>(face->user.p);
- while (*h != 0)
- ++h;
- *h = neighbour;
-}
-
-// add to each face a linked list of its <= 3 neighbouring faces
-// and also ensure each face knows is own normal. Rather than doing
-// lots of small allocs, just assume every face has 3 neighbours
-// and allocate the list nodes in one big lump - the m_faceMap.
-// use the user data pointer in the lib3ds face struct to point
-// to the first node in the list.
-void QGL3dsMesh::buildAdjacencyMap(const QArray<int> &vlist)
-{
- Lib3dsFace *face;
- Lib3dsFace *nbr;
- for (Lib3dsDword f = 0; f < m_mesh->faces; ++f)
- {
- // for each edge (where an edge is a pair of verts) find ones
- // adjacent, ie both verts in edge have same face (which is
- // not this face).
- face = &m_mesh->faceL[f];
- for (int i = 0; i < 3; ++i)
- {
- Q_ASSERT(face->points[i] < m_mesh->points);
- int vi = 2 * face->points[i];
- int neighbouri = -1;
- while (true)
- {
- neighbouri = vlist[vi];
- if (neighbouri != (int)f)
- {
- Q_ASSERT(face->points[(i + 1) % 3] < m_mesh->points);
- int vj = 2 * face->points[(i + 1) % 3];
- int neighbourj = -1;
- while (true)
- {
- neighbourj = vlist[vj];
- if (neighbourj == neighbouri)
- {
- nbr = &m_mesh->faceL[neighbouri];
- // only add as neighbour if at least one smoothing group
- // is shared - still have to test again below for each group
- if (nbr->smoothing & face->smoothing)
- addToAdjacencyMap(face, nbr);
- break;
- }
- if (vlist[vj+1] == -1)
- break;
- vj = vlist[vj+1];
- }
- }
- if (vlist[vi+1] == -1)
- break;
- else
- vi = vlist[vi+1];
- }
- }
- }
-}
-
-static inline void incOrWarn(ModulateRecord *mod)
-{
- if (mod->altKey != 0x80000000)
- {
- mod->altKey <<= 1;
- }
- else
- {
- qWarning("Overflowed smoothing keys - modulation disabled.");
- mod->disabled = true;
- }
-}
-
-static inline void nextUnusedKey(ModulateRecord *mod, const Lib3dsDword &allKeys)
-{
- if (!mod->disabled)
- {
- if (mod->altKey != 0)
- incOrWarn(mod);
- else
- {
- mod->altKey = 1; // initialize
- }
- while ((mod->altKey & allKeys) && !mod->disabled)
- {
- incOrWarn(mod);
- }
- mod->keyFresh = true;
- }
-}
-
-static int numCorrected = 0;
-static int numWindingCorrected = 0;
-
-static inline void doNormalCorrect(Lib3dsFace *face)
-{
- QGL3dsMesh::FacePtr *n = reinterpret_cast<QGL3dsMesh::FacePtr*>(face->user.p);
- int acnt = 0;
- Lib3dsVector avgn = { 0 };
- for (; *n; ++n)
- {
- if ((*n)->smoothing & face->smoothing)
- {
- lib3ds_vector_add(avgn, avgn, (*n)->normal);
- ++acnt;
- }
- }
- if (acnt >= AVG_CNT)
- {
- lib3ds_vector_normalize(avgn);
- float na = lib3ds_vector_dot(face->normal, avgn);
- if (na < INVERSE)
- {
- //qWarning("corrected: %p - %d, %d, %d", face,
- // face->points[0], face->points[1], face->points[2]);
- //lib3ds_vector_dump(face->normal);
- lib3ds_vector_neg(face->normal);
- numWindingCorrected++;
- qSwap(face->points[1], face->points[2]);
- }
- }
-}
-
-static inline void modFace(Lib3dsFace *face, ModulateRecord *mod)
-{
- ++mod->numModulated;
- face->smoothing &= ~mod->key; // remove old key
- face->smoothing |= mod->altKey; // add in new key
- ::strncpy(face->material, "bright-red", 60); //debug
-}
-
-static inline void doModulate(Lib3dsFace *face, ModulateRecord *mod)
-{
- QGL3dsMesh::FacePtr *n = reinterpret_cast<QGL3dsMesh::FacePtr*>(face->user.p);
- ++mod->facesProcessed;
- for ( ; *n; ++n)
- {
- QGL3dsMesh::FacePtr neighbour = *n;
- if (neighbour->smoothing & face->smoothing)
- {
- if (lib3ds_vector_dot(face->normal, neighbour->normal) < ACUTE)
- {
- qWarning("Modulated due to ACUTE\n");
- modFace(neighbour, mod);
- mod->keyFresh = false;
- }
- }
- }
-}
-
-bool operator<(const QVector3D &a, const QVector3D &b)
-{
- if (qFskCompare(a.x(), b.x()))
- {
- if (qFskCompare(a.y(), b.y()))
- {
- if (qFskCompare(a.z(), b.z()))
- {
- return false; // they're equal a is not less than b
- }
- else
- {
- return a.z() < b.z();
- }
- }
- else
- {
- return a.y() < b.y();
- }
- }
- else
- {
- return a.x() < b.x();
- }
-}
-
-// Go thru each smoothing group - we don't care about the zero group since
-// they're already faceted. In each group process all connected faces
-// starting the queue off with a seed face (the first face in the group).
-// Set the alternate group to be the first unused smoothing group key.
-//
-// To process a face: add the face to the processed set; for each adjacent
-// face if its in this same smoothing group, add it to the queue.
-//
-// Modulate smoothing mode: if an adjacent face is at an acute angle to this
-// face, move it to the alternate group. Note that the alternate groups are
-// not further iterated since they are not in "each smoothing group"
-// (the allKeys variable).
-//
-// When the queue is empty, go to the next smoothing group in the mesh.
-
-// Normal repair mode: if a face normal is flipped in error, ie a mistake
-// in model building (typically points specified in the wrong order)
-// this can be detected and repaired. The normal is flipped if the inverse
-// of the normal is at an acute angle to the average of neighbour normals.
-// If detected the normals is corrected and the winding is also checked to
-// see if it needs to be corrected also.
-void QGL3dsMesh::modulateMesh()
-{
- if (!(m_options & (QGL::CorrectNormals | QGL::CorrectAcute)))
- return;
- FacePtr face;
- Lib3dsDword allKeys = 0;
- QArray<int> vlist = mapFacesToVerts(&allKeys);
- buildAdjacencyMap(vlist);
- QSet<FacePtr> processed;
- ModulateRecord mod;
- qMemSet(&mod, 0, sizeof(struct ModulateRecord));
- mod.key = 1;
- while ((mod.key < allKeys) && !mod.disabled && mod.key)
- {
- if (!(allKeys & mod.key))
- {
- ++mod.key;
- continue;
- }
- QArray<FacePtr> queue;
- Lib3dsDword fptr = 0;
- int head = 0;
- while (true)
- {
- if (head >= queue.size()) // seed another island of faces
- {
- if (!mod.keyFresh && head > 0) // if not first time thru, did we use last key?
- allKeys = allKeys | mod.altKey;
- FacePtr qf = 0;
- for ( ; fptr < m_mesh->faces; ++fptr)
- {
- qf = &m_mesh->faceL[fptr];
- if ((mod.key & qf->smoothing) && !processed.contains(qf))
- break;
- }
- if (fptr == m_mesh->faces)
- break;
- queue.append(qf);
- if (!mod.keyFresh)
- {
- nextUnusedKey(&mod, allKeys);
- if (mod.disabled)
- break;
- }
- }
- face = queue.at(head++);
- processed.insert(face);
- doNormalCorrect(face);
- doModulate(face, &mod);
- FacePtr *n = reinterpret_cast<FacePtr*>(face->user.p);
- for ( ; *n; ++n)
- if ((mod.key & (*n)->smoothing) && !processed.contains(*n))
- queue.append(*n);
- }
- }
- if ((m_options & QGL::CorrectNormals) && (m_options & QGL::ShowWarnings))
- qDebug() << "CorrectNormals mode:" << numCorrected << "normals corrected.";
- if ((m_options & QGL::CorrectAcute) && (m_options & QGL::ShowWarnings))
- qDebug() << "CorrectAcute mode:" << mod.numModulated << "normals corrected";
-}
-
-int QGL3dsMesh::cachedMaterialLookup(const char *material)
-{
- static bool initialized = false;
- static int lastLookup = -1;
- static char lastName[512];
- if (!initialized)
- {
- ::memset(lastName, 0, 512);
- initialized = true;
- }
- if (qstrncmp(lastName, material, 510) != 0)
- {
- lastLookup = sceneNode()->palette()->indexOf(QString::fromLatin1(material));
- qstrncpy(lastName, material, 510);
- }
- return lastLookup;
-}
-
-/*!
- \internal
- Find material indexes and smoothing groups used in this mesh. If any
- face has no material assigned then a -1 index will be listed.
- Also figures out how complex the mesh is, by finding the count of
- smoothing groups for the material with the greatest number of groups.
- If the mesh is faceted (no smoothing) but has greater than FACETED_THRESHOLD
- faces then smoothing is forced on and the mesh rescanned.
-
-*/
-void QGL3dsMesh::analyzeMesh()
-{
- QGLMaterialCollection *pal = sceneNode()->palette();
- Lib3dsFace *face;
- Lib3dsDword allKeys = 0;
- m_smoothingGroupCount = 0;
- m_hasZeroSmoothing = false;
- m_plainMaterials.clear();
- m_textureMaterials.clear();
- for (Lib3dsDword f = 0; f < m_mesh->faces; ++f)
- {
- face = &m_mesh->faceL[f];
- int matIx = cachedMaterialLookup(face->material);
-#ifndef QT_NO_DEBUG_STREAM
- if (matIx == -1 && strlen(face->material) != 0 && (m_options & QGL::ShowWarnings))
- qDebug("Bad .3ds file: no material %s! (Referenced in mesh %s)\n",
- face->material, m_mesh->name);
-#endif
- if (face->smoothing)
- {
- if ((face->smoothing & allKeys) != face->smoothing)
- {
- Lib3dsDword key = 1;
- while (key)
- {
- if ((key & face->smoothing) && !(allKeys & key))
- {
- allKeys = allKeys | key;
- m_smoothingGroupCount += 1;
- }
- key <<= 1;
- }
- }
- }
- else
- {
- m_hasZeroSmoothing = true;
- }
- if (!m_plainMaterials.contains(matIx) && !m_textureMaterials.contains(matIx))
- {
- QGLMaterial *mat = pal->material(matIx);
- if (mat && mat->texture())
- m_textureMaterials.insert(matIx);
- else
- m_plainMaterials.insert(matIx);
- }
- }
- m_smoothingGroups = allKeys;
-}
-
-/*!
- \internal
- Check the meshes textures and update the record of whether this mesh
- has textures or not. In debug mode issue a warning if the textures are
- corrupt (number of texels and vertices not equal).
-*/
-void QGL3dsMesh::checkTextures(int material)
-{
- QGLMaterial *mat = sceneNode()->palette()->material(material);
- QGLTexture2D *tex = (mat ? mat->texture() : 0);
- m_hasTextures = false;
- if (tex)
- {
- m_hasTextures = true;
-#ifndef QT_NO_DEBUG_STREAM
- if (m_mesh->points != m_mesh->texels)
- qWarning("Mesh %s has unequal number of texels (%d) and vertices (%d)",
- m_mesh->name, m_mesh->texels, m_mesh->points);
-#endif
- // all texture coordinates from 3ds have to be flipped because
- // 3ds uses the correct coordinate system, whilst qt uses
- // upside-down coordinates
- m_texFlip = (tex->bindOptions() & QGLContext::InvertedYBindOption) == 0;
- }
-}
-
-/*!
- \internal
- Returns any local transformation matrix for the mesh.
-*/
-QMatrix4x4 QGL3dsMesh::meshMatrix() const
-{
- Lib3dsMatrix &m = m_mesh->matrix; // typedef for float[4][4]
- QMatrix4x4 mat;
- for (int col = 0; col < 4; ++col)
- for (int row = 0; row < 4; ++row) {
- float e = m[col][row];
- if (qFuzzyIsNull(e))
- mat(row, col) = 0.0f;
- else
- mat(row, col) = e;
- }
- mat.optimize(); // setup to use optimizations
- if (mat.isIdentity())
- return mat;
- // The reverse transform is what we apply to model-view in order
- // to draw the underlying geometry
- bool invertible = true;
- mat = mat.inverted(&invertible);
- if (invertible)
- return mat;
- if (m_options & QGL::ShowWarnings)
- qWarning("Could not invert matrix for mesh %s", m_mesh->name);
- return QMatrix4x4();
-}
-
-/*!
- \internal
- Generate the vertices for the faces based on their smoothing keys and
- the current nodes material.
-*/
-void QGL3dsMesh::generateVertices()
-{
- int matIx = currentNode()->materialIndex();
- int keyCount = m_smoothingGroupCount;
- if (m_hasZeroSmoothing)
- ++keyCount;
- QString baseName = currentNode()->objectName();
- Lib3dsDword key = 0;
- while (key <= m_smoothingGroups)
- {
- if ((key & m_smoothingGroups) || ((key == 0) && m_hasZeroSmoothing))
- {
- if (key == 0)
- currentSection()->setSmoothing(QGL::Faceted);
- keyCount -= 1;
- currentNode()->setMaterialIndex(matIx);
- currentNode()->setObjectName(baseName + QLatin1String("::") + QString::number(key));
- QGeometryData tri;
- int cur = 0;
- for (Lib3dsDword f = 0; f < m_mesh->faces; ++f)
- {
- Lib3dsFace *face = &m_mesh->faceL[f];
- int faceMat = cachedMaterialLookup(face->material);
- if (faceMat == matIx &&
- ((key & face->smoothing) || (key == 0 && face->smoothing == 0)))
- {
- QVector3D norm = l2v(face->normal);
- for (int i = 0; i < 3; ++i)
- {
- int a = face->points[i];
- Lib3dsVector &l3a = m_mesh->pointL[a].pos;
- tri.appendVertex(l2v(l3a));
- tri.appendNormal(norm);
- if (m_hasTextures)
- {
- Lib3dsTexel &t0 = m_mesh->texelL[a];
- tri.appendTexCoord(QVector2D(t0[0], m_texFlip ? 1.0f - t0[1] : t0[1]));
- }
- if (m_options & QGL::NativeIndices)
- currentSection()->appendSmooth(tri.logicalVertexAt(cur++), a);
- }
- }
- }
- if (m_options & QGL::NativeIndices)
- currentNode()->setCount(cur);
- else
- addTriangles(tri);
- if (keyCount > 0)
- newSection(QGL::Smooth);
- else
- break;
- }
- if (key == 0)
- key = 1;
- else
- key <<= 1;
- }
-}