1 /****************************************************************************
2 **
3 ** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the Qt3D module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL3$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPLv3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or later as published by the Free
28 ** Software Foundation and appearing in the file LICENSE.GPL included in
29 ** the packaging of this file. Please review the following information to
30 ** ensure the GNU General Public License version 2.0 requirements will be
31 ** met: http://www.gnu.org/licenses/gpl-2.0.html.
32 **
33 ** $QT_END_LICENSE$
34 **
35 ****************************************************************************/
36 
37 #ifndef QT3DANIMATION_ANIMATION_GLTFIMPORTER_H
38 #define QT3DANIMATION_ANIMATION_GLTFIMPORTER_H
39 
40 //
41 //  W A R N I N G
42 //  -------------
43 //
44 // This file is not part of the Qt API.  It exists for the convenience
45 // of other Qt classes.  This header file may change from version to
46 // version without notice, or even be removed.
47 //
48 // We mean it.
49 //
50 
51 #include <QtGlobal>
52 #include <Qt3DAnimation/private/fcurve_p.h>
53 #include <Qt3DRender/qattribute.h>
54 #include <Qt3DCore/private/sqt_p.h>
55 #include <Qt3DCore/private/qmath3d_p.h>
56 
57 #include <QJsonDocument>
58 #include <QJsonObject>
59 #include <QJsonArray>
60 #include <QJsonValue>
61 #include <QVector>
62 
63 QT_BEGIN_NAMESPACE
64 
65 class QIODevice;
66 
67 namespace Qt3DAnimation {
68 namespace Animation {
69 
70 class GLTFImporter
71 {
72 public:
73     class BufferData
74     {
75     public:
76         BufferData();
77         explicit BufferData(const QJsonObject &json);
78 
79         quint64 byteLength;
80         QString path;
81         QByteArray data;
82     };
83 
84     class BufferView
85     {
86     public:
87         BufferView();
88         explicit BufferView(const QJsonObject &json);
89 
90         quint64 byteOffset;
91         quint64 byteLength;
92         int bufferIndex;
93         int target; // Only for per vertex attributes
94     };
95 
96     class AccessorData
97     {
98     public:
99         AccessorData();
100         explicit AccessorData(const QJsonObject &json);
101 
102         int bufferViewIndex;
103         Qt3DRender::QAttribute::VertexBaseType type;
104         uint dataSize;
105         int count;
106         int byteOffset;
107         int byteStride; // Only for per vertex attributes
108 
109         // TODO: Extend to support sparse accessors
110     };
111 
112     class Skin
113     {
114     public:
115         Skin();
116         explicit Skin(const QJsonObject &json);
117 
118         QString name;
119         int inverseBindAccessorIndex;
120         QVector<int> jointNodeIndices;
121     };
122 
123     class Channel
124     {
125     public:
126         Channel();
127         explicit Channel(const QJsonObject &json);
128 
129         int samplerIndex;
130         int targetNodeIndex;
131         QString targetProperty;
132     };
133 
134     class Sampler
135     {
136     public:
137         Sampler();
138         explicit Sampler(const QJsonObject &json);
139 
140         enum InterpolationMode {
141             Linear,
142             Step,
143             CatmullRomSpline,
144             CubicSpline
145         };
146 
147         QString interpolationModeString() const;
148 
149         int inputAccessorIndex;
150         int outputAccessorIndex;
151         InterpolationMode interpolationMode;
152     };
153 
154     class Animation
155     {
156     public:
157         Animation();
158         explicit Animation(const QJsonObject &json);
159 
160         QString name;
161         QVector<Channel> channels;
162         QVector<Sampler> samplers;
163     };
164 
165     class Node
166     {
167     public:
168         Node();
169         explicit Node(const QJsonObject &json);
170 
171         Qt3DCore::Sqt localTransform;
172         QVector<int> childNodeIndices;
173         QString name;
174         int parentNodeIndex;
175         int cameraIndex;
176         int meshIndex;
177         int skinIndex;
178     };
179 
180     GLTFImporter();
181 
182     bool load(QIODevice *ioDev);
animations()183     const QVector<Animation> animations() const { return m_animations; }
184 
185     struct AnimationNameAndChannels
186     {
187         QString name;
188         QVector<Qt3DAnimation::Animation::Channel> channels;
189     };
190     AnimationNameAndChannels createAnimationData(int animationIndex, const QString &animationName = QString()) const;
191 
192 private:
193     static Qt3DRender::QAttribute::VertexBaseType accessorTypeFromJSON(int componentType);
194     static uint accessorTypeSize(Qt3DRender::QAttribute::VertexBaseType componentType);
195     static uint accessorDataSizeFromJson(const QString &type);
196 
197     struct RawData
198     {
199         const char *data;
200         quint64 byteLength;
201     };
202 
203     void setBasePath(const QString &path);
204     bool setJSON(const QJsonDocument &json);
205 
206     bool parse();
207     bool parseGLTF2();
208     void cleanup();
209     QHash<int, int> createNodeIndexToJointIndexMap(const Skin &skin) const;
210 
211     bool processJSONBuffer(const QJsonObject &json);
212     bool processJSONBufferView(const QJsonObject &json);
213     bool processJSONAccessor(const QJsonObject &json);
214     bool processJSONSkin(const QJsonObject &json);
215     bool processJSONAnimation(const QJsonObject &json);
216     bool processJSONNode(const QJsonObject &json);
217     void setupNodeParentLinks();
218     QByteArray resolveLocalData(const QString &path) const;
219 
220     RawData accessorData(int accessorIndex, int index) const;
221 
222     QJsonDocument m_json;
223     QString m_basePath;
224     QVector<BufferData> m_bufferDatas;
225     QVector<BufferView> m_bufferViews;
226     QVector<AccessorData> m_accessors;
227     QVector<Skin> m_skins;
228     QVector<Animation> m_animations;
229     QVector<Node> m_nodes;
230 };
231 
232 } // namespace Animation
233 } // namespace Qt3DAnimation
234 
235 QT_END_NAMESPACE
236 
237 #endif // QT3DANIMATION_ANIMATION_GLTFIMPORTER_H
238