示例#1
0
/*!
    \internal
    Output a string representation of \a section to a debug stream \a dbg.
    \relates QGLSection
*/
QDebug operator<<(QDebug dbg, const QGLSection &section)
{
    dbg.space()
            << "QGLSection(" << &section
            << "- count:" << section.count()
            << "- smoothing mode:" << (section.smoothing() == QGL::Smooth ?
                                       "QGL::Smooth" : "QGL::Faceted") << "\n";
    QGL::IndexArray indices = section.indices();
    for (int i = 0; i < section.count(); ++i)
    {
        int ix = indices[i];
        dbg << section.logicalVertexAt(ix) << "\n";
    }
    dbg << ")\n";
    return dbg.space();
}
示例#2
0
/*!
    Finish the building of this geometry, optimize it for rendering, and return a
    pointer to the detached top-level scene node (root node).

    Since the scene is detached from the builder object, the builder itself
    may be deleted or go out of scope while the scene lives on:

    \code
    void MyView::MyView()
    {
        QGLBuilder builder;
        // construct geometry
        m_thing = builder.finalizedSceneNode();
    }

    void MyView::~MyView()
    {
        delete m_thing;
    }

    void MyView::paintGL()
    {
        m_thing->draw(painter);
    }
    \endcode

    The root node will have a child node for each section that was created
    during geometry building.

    This method must be called exactly once after building the scene.

    \b{Calling code takes ownership of the scene.}  In particular take care
    to either explicitly destroy the scene when it is no longer needed - as shown
    above.

    For more complex applications parent each finalized scene node onto a QObject
    so it will be implictly cleaned up by Qt.  If you use QGLSceneNode::setParent()
    to do this, you can save an explicit call to addNode() since if setParent()
    detects that the new parent is a QGLSceneNode it will call addNode() for you:

    \code
    // here a top level node for the app is created, and parented to the view
    QGLSceneNode *topNode = new QGLSceneNode(this);

    QGLBuilder b1;
    // build geometry

    QGLSceneNode *thing = b1.finalizedSceneNode();

    // does a QObject::setParent() to manage memory, and also adds to the scene
    // graph, so no need to call topNode->addNode(thing)
    thing->setParent(topNode);

    QGLBuilder b2;
    // build more geometry
    QGLSceneNode *anotherThing = b2.finalizedSceneNode();

    // again parent on get addNode for free
    anotherThing->setParent(topNode);
    \endcode

    If this builder is destroyed without calling this method to take
    ownership of the scene, a warning will be printed on the console and the
    scene will be deleted.  If this method is called more than once, on the
    second and subsequent calls a warning is printed and NULL is returned.

    This function does the following:
    \list
        \li packs all geometry data from sections into QGLSceneNode instances
        \li recalculates QGLSceneNode start() and count() for the scene
        \li deletes all QGLBuilder's internal data structures
        \li returns the top level scene node that references the geometry
        \li sets the internal pointer to the top level scene node to NULL
    \endlist

    \sa sceneNode()
*/
QGLSceneNode *QGLBuilder::finalizedSceneNode()
{
    if (dptr->rootNode == 0)
    {
        qWarning("QGLBuilder::finalizedSceneNode() called twice");
        return 0;
    }
    QGeometryData g;
    QMap<quint32, QGeometryData> geos;
    QMap<QGLSection*, int> offsets;
    for (int i = 0; i < dptr->sections.count(); ++i)
    {
        // pack sections that have the same fields into one geometry
        QGLSection *s = dptr->sections.at(i);
        QGL::IndexArray indices = s->indices();
        int icnt = indices.size();
        int ncnt = nodeCount(s->nodes());
        int scnt = s->count();
        if (scnt == 0 || icnt == 0 || ncnt == 0)
        {
            if (!qgetenv("Q_WARN_EMPTY_MESH").isEmpty())
            {
                if (ncnt == 0)
                    warnIgnore(scnt, s, icnt, ncnt, "nodes empty");
                else if (scnt == 0)
                    warnIgnore(scnt, s, icnt, ncnt, "geometry count zero");
                else
                    warnIgnore(scnt, s, icnt, ncnt, "index count zero");
            }
            continue;
        }
        s->normalizeNormals();
        int sectionOffset = 0;
        int sectionIndexOffset = 0;
        if (geos.contains(s->fields()))
        {
            QGeometryData &gd = geos[s->fields()];
            sectionOffset = gd.count();
            sectionIndexOffset = gd.indexCount();
            offsets.insert(s, sectionIndexOffset);
            gd.appendGeometry(*s);
            for (int i = 0; i < icnt; ++i)
                indices[i] += sectionOffset;
            gd.appendIndices(indices);
        }
        else
        {
            g = QGeometryData(*s);
            geos.insert(s->fields(), g);
        }
    }
    while (dptr->sections.count() > 0)
    {
        QGLSection *s = dptr->sections.takeFirst();
        dptr->adjustSectionNodes(s, offsets[s], geos[s->fields()]);
        delete s;
    }
    QGLSceneNode *tmp = dptr->rootNode;
    dptr->rootNode = 0;  // indicates root node detached
    return tmp;
}