summaryrefslogtreecommitdiff
path: root/src/threed/scene_ai/qaiscene.cpp
blob: e87c199210c604176e541451f4d576f865795d1d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt3D 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 "qaiscene.h"
#include "qaimesh.h"
#include "qailoader.h"

#include "qglscenenode.h"

QT_BEGIN_NAMESPACE

/*!
    \internal
    \class QAiScene
    \brief The QAiScene class manages and contains an asset importer scene.
    The scene consists of a QGLSceneNode object which is the top-level node
    and references the geometry imported from a file.
*/

/*!
    \internal
    Construct a new QAiScene object using the data in the \a scene,
    and setting the given \a parent.

    The QAiScene object takes ownership of the \a file.
*/

const int g_MaxLevel = 16;
char g_Buffer[1 + g_MaxLevel*2];
void DumpSceneNode(int level, QGLSceneNode* pNode)
{
    if (pNode) {
        if (level > g_MaxLevel)
            level = g_MaxLevel;
        memset(g_Buffer,' ',level*2);
        g_Buffer[level*2] = '\0';
        qDebug("%snode(%p) name='%s'",g_Buffer,pNode,pNode->objectName().toLatin1().constData());
        if (!pNode->localTransform().isIdentity()) {
            qDebug("%s  transform",g_Buffer);
        }
        if (pNode->count() > 0) {
            qDebug("%s  geometry",g_Buffer);
        }
        foreach (QGLSceneNode* pChild, pNode->children()) {
            DumpSceneNode(level+1, pChild);
        }
    }
}

void DumpAnimations(const QList<QGLSceneAnimation *>& rAnimations)
{
    foreach (QGLSceneAnimation* pAnim, rAnimations) {
        qDebug("animation '%s':",pAnim->name().toLatin1().constData());
        QList<QString> nodes = pAnim->affectedNodes();
        foreach (QString node, nodes) {
            qDebug("  affects node '%s'",node.toLatin1().constData());
        }
    }
}

void DumpDefaultTransforms(const QMap<QGLSceneNode*,QGLSceneAnimation::NodeTransform>& rDefaultTransforms)
{
    for (QMap<QGLSceneNode*,QGLSceneAnimation::NodeTransform>::const_iterator It=rDefaultTransforms.begin(); It!=rDefaultTransforms.end(); ++It) {
        qDebug("got default transform for node '%s'",It.key()->objectName().toLatin1().constData());
    }
}

QAiScene::QAiScene(const aiScene *scene, QAiSceneHandler *handler)
    : QGLAbstractScene(0)
{
    Q_ASSERT(handler);
    Q_ASSERT(scene);
    QAiLoader loader(scene, handler);
    m_root = loader.loadMeshes();
    m_root->setParent(this);
    getAnimations() = loader.loadAnimations();
    getDefaultTransformations() = loader.loadDefaultTransformations();
    foreach (QGLSceneAnimation* pAnim, getAnimations()) {
        pAnim->setParent(this);
        QObject::connect(pAnim,SIGNAL(positionChanged()),this,SLOT(processAnimations()));
    }
    qDebug("=======================================");
    qDebug("loaded scene:");
    DumpSceneNode(1,m_root);
    DumpAnimations(getAnimations());
    DumpDefaultTransforms(getDefaultTransformations());
    qDebug("=======================================");
    m_aiLoader = 0;
}

/*!
    \internal
    Construct a new QAiScene object and setting the given \a handler.

    Note that the scene which will be used to generate the QAiScene has
    not been added yet - this is used in the network case and requires
    a later call to the loadScene function to work correctly

    \sa loadScene()
*/
QAiScene::QAiScene(QAiSceneHandler *handler)
    : QGLAbstractScene(0)
{
    Q_ASSERT(handler);
    //create a temporary loader and get a temporary root node for the scene.
    m_aiLoader = new QAiLoader(0, handler);
    m_root=m_aiLoader->m_builder.sceneNode();
}

/*!
    \internal
    \reimp
    Destroy this QAiScene, recovering all resources.
*/
QAiScene::~QAiScene()
{
    delete m_aiLoader;
}

/*!
    \internal
    \reimp
*/
QList<QObject *> QAiScene::objects() const
{
    QList<QObject *> objs;
    if (!m_root)
        return objs;
    objs.append(m_root);
    QList<QGLSceneNode*> children = m_root->allChildren();
    QList<QGLSceneNode*>::const_iterator it = children.constBegin();
    for ( ; it != children.constEnd(); ++it)
        objs.append(*it);
    return objs;
}

/*!
    \internal
    \reimp
*/
QGLSceneNode *QAiScene::mainNode() const
{
    return m_root;
}

/*!
    \internal
    Returns the aiLoader associated with the scene (if any).
*/
QAiLoader * QAiScene::aiLoader() const
{
    return m_aiLoader;
}

/*!
    \internal
    Load the new \a scene and swap the extant palette from the temporary roote
    node into the current root node.

    The QAiScene object takes ownership of the \a file.
*/
void QAiScene::loadScene(const aiScene *scene)
{
    Q_ASSERT(scene);

    //Get the old material information
    QSharedPointer<QGLMaterialCollection>oldPalette= m_aiLoader->m_builder.palette();
    int oldIndex = m_root->materialIndex();

    //Reset the palette for the root node.
    QSharedPointer<QGLMaterialCollection>newPalette = QSharedPointer<QGLMaterialCollection>(new QGLMaterialCollection());
    m_aiLoader->m_builder.sceneNode()->setPalette(newPalette);
    m_aiLoader->m_scene = scene;

    //Commence loading of the mesh.
    m_root = m_aiLoader->loadMeshes(); //this won't actually change the root unless we've messed up.
    delete m_aiLoader;
    m_aiLoader = 0;

    //Swap out the materials palette
    int indexCount=0;
    int materialCount=0;
    QGLMaterial * currentMaterial = NULL;
    do {
        currentMaterial = oldPalette->removeMaterial(indexCount);
        if (currentMaterial) {
            materialCount = m_root->palette()->addMaterial(currentMaterial);
            indexCount++;
        }
    } while (currentMaterial);
    m_root->setMaterialIndex(materialCount-(indexCount-1)+oldIndex);

    //update picking nodes for the whole scene if needed
    if (pickable()) generatePickNodes();

    emit sceneUpdated();
}

QT_END_NAMESPACE