summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntti Määttä <antti.maatta@qt.io>2016-09-16 14:10:01 +0300
committerSean Harmer <sean.harmer@kdab.com>2017-01-31 11:41:59 +0000
commit59f8fec8a41606b3185fe3a4e276978e3e1ed5ef (patch)
treef939c83813794a78157bf488a459ac57fe9ab1c2
parent79ec93e56d9067674c108544ef3af041644318d7 (diff)
Animation support for Qt3D
Modded assimp loader to load animations and to load submeshes into child entities. Added keyframeanimation for node animations and morphing mesh. Also added animation group for controlling multiple nodes as one animation and animation controller to select and play animations. Assimp loader adds QKeyFrameAnimations targeting an entity as child objects of that entity, the QAnimationController finds them when the entity is set and creates QAnimationGroups from based on the animation name. Change-Id: I7e2e7a4479af49f8023b4a359b2b3118efdaa0da Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
-rw-r--r--src/extras/animations/animations.pri26
-rw-r--r--src/extras/animations/qabstractanimation.cpp112
-rw-r--r--src/extras/animations/qabstractanimation.h93
-rw-r--r--src/extras/animations/qabstractanimation_p.h75
-rw-r--r--src/extras/animations/qanimationcontroller.cpp252
-rw-r--r--src/extras/animations/qanimationcontroller.h105
-rw-r--r--src/extras/animations/qanimationcontroller_p.h84
-rw-r--r--src/extras/animations/qanimationgroup.cpp125
-rw-r--r--src/extras/animations/qanimationgroup.h89
-rw-r--r--src/extras/animations/qanimationgroup_p.h77
-rw-r--r--src/extras/animations/qkeyframeanimation.cpp262
-rw-r--r--src/extras/animations/qkeyframeanimation.h112
-rw-r--r--src/extras/animations/qkeyframeanimation_p.h89
-rw-r--r--src/extras/animations/qmorphinganimation.cpp280
-rw-r--r--src/extras/animations/qmorphinganimation.h116
-rw-r--r--src/extras/animations/qmorphinganimation_p.h93
-rw-r--r--src/extras/animations/qmorphtarget.cpp120
-rw-r--r--src/extras/animations/qmorphtarget.h83
-rw-r--r--src/extras/animations/qmorphtarget_p.h76
-rw-r--r--src/extras/animations/qvertexblendanimation.cpp234
-rw-r--r--src/extras/animations/qvertexblendanimation.h96
-rw-r--r--src/extras/animations/qvertexblendanimation_p.h86
-rw-r--r--src/extras/defaults/defaults.pri9
-rw-r--r--src/extras/defaults/qmorphphongmaterial.cpp291
-rw-r--r--src/extras/defaults/qmorphphongmaterial.h92
-rw-r--r--src/extras/defaults/qmorphphongmaterial_p.h108
-rw-r--r--src/extras/extras.pro1
-rw-r--r--src/extras/extras.qrc2
-rw-r--r--src/extras/shaders/es2/morphphong.vert32
-rw-r--r--src/extras/shaders/gl3/morphphong.vert34
-rw-r--r--src/plugins/sceneparsers/assimp/assimpimporter.cpp349
-rw-r--r--src/plugins/sceneparsers/assimp/assimpimporter.h8
-rw-r--r--src/quick3d/imports/extras/defaults.qrc21
-rw-r--r--src/quick3d/imports/extras/importsextras.pro2
-rw-r--r--src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp20
-rw-r--r--src/quick3d/quick3dextras/items/items.pri15
-rw-r--r--src/quick3d/quick3dextras/items/quick3danimationcontroller.cpp95
-rw-r--r--src/quick3d/quick3dextras/items/quick3danimationcontroller_p.h89
-rw-r--r--src/quick3d/quick3dextras/items/quick3danimationgroup.cpp99
-rw-r--r--src/quick3d/quick3dextras/items/quick3danimationgroup_p.h91
-rw-r--r--src/quick3d/quick3dextras/items/quick3dkeyframeanimation.cpp101
-rw-r--r--src/quick3d/quick3dextras/items/quick3dkeyframeanimation_p.h92
-rw-r--r--src/quick3d/quick3dextras/items/quick3dmorphinganimation.cpp97
-rw-r--r--src/quick3d/quick3dextras/items/quick3dmorphinganimation_p.h92
-rw-r--r--src/quick3d/quick3dextras/items/quick3dmorphtarget.cpp93
-rw-r--r--src/quick3d/quick3dextras/items/quick3dmorphtarget_p.h85
-rw-r--r--src/quick3d/quick3dextras/quick3dextras.pro4
-rw-r--r--tests/manual/anim-viewer/anim-viewer.pro13
-rw-r--r--tests/manual/anim-viewer/assets/blendshapeanimation.dae1281
-rw-r--r--tests/manual/anim-viewer/assets/gears.dae873
-rw-r--r--tests/manual/anim-viewer/main.cpp51
-rw-r--r--tests/manual/anim-viewer/main.qml240
-rw-r--r--tests/manual/anim-viewer/qml.qrc7
-rw-r--r--tests/manual/manual.pro4
-rw-r--r--tests/manual/mesh-morphing/main.cpp180
-rw-r--r--tests/manual/mesh-morphing/mesh-morphing.pro10
-rw-r--r--tests/manual/mesh-morphing/mesh-morphing.qrc1
57 files changed, 7254 insertions, 13 deletions
diff --git a/src/extras/animations/animations.pri b/src/extras/animations/animations.pri
new file mode 100644
index 000000000..71d6099fc
--- /dev/null
+++ b/src/extras/animations/animations.pri
@@ -0,0 +1,26 @@
+HEADERS += \
+ $$PWD/qanimationcontroller.h \
+ $$PWD/qanimationcontroller_p.h \
+ $$PWD/qanimationgroup.h \
+ $$PWD/qanimationgroup_p.h \
+ $$PWD/qkeyframeanimation.h \
+ $$PWD/qkeyframeanimation_p.h \
+ $$PWD/qmorphinganimation.h \
+ $$PWD/qmorphinganimation_p.h \
+ $$PWD/qabstractanimation.h \
+ $$PWD/qabstractanimation_p.h \
+ $$PWD/qmorphtarget.h \
+ $$PWD/qmorphtarget_p.h \
+ $$PWD/qvertexblendanimation.h \
+ $$PWD/qvertexblendanimation_p.h
+
+SOURCES += \
+ $$PWD/qanimationcontroller.cpp \
+ $$PWD/qanimationgroup.cpp \
+ $$PWD/qkeyframeanimation.cpp \
+ $$PWD/qmorphinganimation.cpp \
+ $$PWD/qabstractanimation.cpp \
+ $$PWD/qmorphtarget.cpp \
+ $$PWD/qvertexblendanimation.cpp
+
+INCLUDEPATH += $$PWD
diff --git a/src/extras/animations/qabstractanimation.cpp b/src/extras/animations/qabstractanimation.cpp
new file mode 100644
index 000000000..f87455c18
--- /dev/null
+++ b/src/extras/animations/qabstractanimation.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qabstractanimation.h"
+#include "Qt3DExtras/private/qabstractanimation_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+QAbstractAnimationPrivate::QAbstractAnimationPrivate(QAbstractAnimation::AnimationType type)
+ : QObjectPrivate()
+ , m_animationType(type)
+ , m_position(0.0f)
+ , m_duration(0.0f)
+{
+
+}
+
+QAbstractAnimation::QAbstractAnimation(QAbstractAnimationPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+
+}
+
+QString QAbstractAnimation::animationName() const
+{
+ Q_D(const QAbstractAnimation);
+ return d->m_animationName;
+}
+
+QAbstractAnimation::AnimationType QAbstractAnimation::animationType() const
+{
+ Q_D(const QAbstractAnimation);
+ return d->m_animationType;
+}
+
+float QAbstractAnimation::position() const
+{
+ Q_D(const QAbstractAnimation);
+ return d->m_position;
+}
+
+float QAbstractAnimation::duration() const
+{
+ Q_D(const QAbstractAnimation);
+ return d->m_duration;
+}
+
+void QAbstractAnimation::setAnimationName(const QString &name)
+{
+ Q_D(QAbstractAnimation);
+ if (name != d->m_animationName) {
+ d->m_animationName = name;
+ emit animationNameChanged(name);
+ }
+}
+
+void QAbstractAnimation::setPosition(float position)
+{
+ Q_D(QAbstractAnimation);
+ if (!qFuzzyCompare(position, d->m_position)) {
+ d->m_position = position;
+ emit positionChanged(position);
+ }
+}
+
+void QAbstractAnimation::setDuration(float duration)
+{
+ Q_D(QAbstractAnimation);
+ if (!qFuzzyCompare(duration, d->m_duration)) {
+ d->m_duration = duration;
+ emit durationChanged(duration);
+ }
+}
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
diff --git a/src/extras/animations/qabstractanimation.h b/src/extras/animations/qabstractanimation.h
new file mode 100644
index 000000000..242fe293a
--- /dev/null
+++ b/src/extras/animations/qabstractanimation.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QABSTRACTANIMATION_H
+#define QT3DEXTRAS_QABSTRACTANIMATION_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qvector.h>
+
+#include <Qt3DExtras/qt3dextras_global.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+class QAbstractAnimationPrivate;
+
+class QT3DEXTRASSHARED_EXPORT QAbstractAnimation : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString animationName READ animationName WRITE setAnimationName NOTIFY animationNameChanged)
+ Q_PROPERTY(QAbstractAnimation::AnimationType animationType READ animationType CONSTANT)
+ Q_PROPERTY(float position READ position WRITE setPosition NOTIFY positionChanged)
+ Q_PROPERTY(float duration READ duration NOTIFY durationChanged)
+
+public:
+ enum AnimationType {
+ KeyframeAnimation = 1,
+ MorphingAnimation = 2,
+ VertexBlendAnimation = 3,
+ };
+
+ QString animationName() const;
+ QAbstractAnimation::AnimationType animationType() const;
+ float position() const;
+ float duration() const;
+
+public Q_SLOTS:
+ void setAnimationName(const QString &name);
+ void setPosition(float position);
+
+protected:
+ explicit QAbstractAnimation(QAbstractAnimationPrivate &dd, QObject *parent = nullptr);
+
+ void setDuration(float duration);
+
+Q_SIGNALS:
+ void animationNameChanged(const QString &name);
+ void positionChanged(float position);
+ void durationChanged(float duration);
+
+private:
+ Q_DECLARE_PRIVATE(QAbstractAnimation)
+};
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QABSTRACTANIMATION_H
diff --git a/src/extras/animations/qabstractanimation_p.h b/src/extras/animations/qabstractanimation_p.h
new file mode 100644
index 000000000..1370ef2c7
--- /dev/null
+++ b/src/extras/animations/qabstractanimation_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QABSTRACTANIMATION_P_H
+#define QT3DEXTRAS_QABSTRACTANIMATION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qobject_p.h>
+#include <Qt3DExtras/QAbstractAnimation>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+class QAbstractAnimationPrivate : public QObjectPrivate
+{
+public:
+ QAbstractAnimationPrivate(QAbstractAnimation::AnimationType type);
+
+ QString m_animationName;
+ QAbstractAnimation::AnimationType m_animationType;
+ float m_position;
+ float m_duration;
+
+ Q_DECLARE_PUBLIC(QAbstractAnimation)
+};
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QANIMATIONCONTROLLER_P_H
diff --git a/src/extras/animations/qanimationcontroller.cpp b/src/extras/animations/qanimationcontroller.cpp
new file mode 100644
index 000000000..adef3d45c
--- /dev/null
+++ b/src/extras/animations/qanimationcontroller.cpp
@@ -0,0 +1,252 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qanimationcontroller.h"
+#include "qanimationgroup.h"
+
+#include <private/qanimationcontroller_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+QAnimationControllerPrivate::QAnimationControllerPrivate()
+ : QObjectPrivate()
+ , m_activeAnimationGroup(0)
+ , m_position(0.0f)
+ , m_positionScale(1.0f)
+ , m_positionOffset(0.0f)
+ , m_entity(nullptr)
+ , m_recursive(true)
+{
+
+}
+
+void QAnimationControllerPrivate::updatePosition(float position)
+{
+ m_position = position;
+ if (m_activeAnimationGroup >= 0 && m_activeAnimationGroup < m_animationGroups.size()) {
+ const float pos = m_positionScale * position + m_positionOffset;
+ m_animationGroups[m_activeAnimationGroup]->setPosition(pos);
+ }
+}
+
+QAnimationGroup *QAnimationControllerPrivate::findGroup(const QString &name)
+{
+ for (QAnimationGroup *g : m_animationGroups) {
+ if (g->name() == name)
+ return g;
+ }
+ return nullptr;
+}
+
+void QAnimationControllerPrivate::extractAnimations()
+{
+ Q_Q(QAnimationController);
+ if (!m_entity)
+ return;
+ QList<Qt3DExtras::QAbstractAnimation *> animations
+ = m_entity->findChildren<Qt3DExtras::QAbstractAnimation *>(QString(),
+ m_recursive ? Qt::FindChildrenRecursively : Qt::FindDirectChildrenOnly);
+ if (animations.size() > 0) {
+ for (Qt3DExtras::QAbstractAnimation *a : animations) {
+ QAnimationGroup *group = findGroup(a->animationName());
+ if (!group) {
+ group = new QAnimationGroup(q);
+ group->setName(a->animationName());
+ m_animationGroups.push_back(group);
+ }
+ group->addAnimation(a);
+ }
+ }
+}
+void QAnimationControllerPrivate::clearAnimations()
+{
+ for (Qt3DExtras::QAnimationGroup *a : m_animationGroups)
+ a->deleteLater();
+ m_animationGroups.clear();
+ m_activeAnimationGroup = 0;
+}
+
+QAnimationController::QAnimationController(QObject *parent)
+ : QObject(*new QAnimationControllerPrivate, parent)
+{
+
+}
+
+QVector<QAnimationGroup *> QAnimationController::animationGroupList()
+{
+ Q_D(QAnimationController);
+ return d->m_animationGroups;
+}
+
+int QAnimationController::activeAnimationGroup() const
+{
+ Q_D(const QAnimationController);
+ return d->m_activeAnimationGroup;
+}
+
+float QAnimationController::position() const
+{
+ Q_D(const QAnimationController);
+ return d->m_position;
+}
+
+float QAnimationController::positionScale() const
+{
+ Q_D(const QAnimationController);
+ return d->m_positionScale;
+}
+
+float QAnimationController::positionOffset() const
+{
+ Q_D(const QAnimationController);
+ return d->m_positionOffset;
+}
+
+Qt3DCore::QEntity *QAnimationController::entity() const
+{
+ Q_D(const QAnimationController);
+ return d->m_entity;
+}
+
+bool QAnimationController::recursive() const
+{
+ Q_D(const QAnimationController);
+ return d->m_recursive;
+}
+
+void QAnimationController::setAnimationGroups(const QVector<QAnimationGroup *> &animationGroups)
+{
+ Q_D(QAnimationController);
+ d->m_animationGroups = animationGroups;
+ if (d->m_activeAnimationGroup >= d->m_animationGroups.size())
+ d->m_activeAnimationGroup = 0;
+ d->updatePosition(d->m_position);
+}
+
+void QAnimationController::addAnimationGroup(Qt3DExtras::QAnimationGroup *animationGroup)
+{
+ Q_D(QAnimationController);
+ if (!d->m_animationGroups.contains(animationGroup))
+ d->m_animationGroups.push_back(animationGroup);
+}
+
+void QAnimationController::removeAnimationGroup(Qt3DExtras::QAnimationGroup *animationGroup)
+{
+ Q_D(QAnimationController);
+ if (d->m_animationGroups.contains(animationGroup))
+ d->m_animationGroups.removeAll(animationGroup);
+ if (d->m_activeAnimationGroup >= d->m_animationGroups.size())
+ d->m_activeAnimationGroup = 0;
+}
+
+void QAnimationController::setActiveAnimationGroup(int index)
+{
+ Q_D(QAnimationController);
+ if (d->m_activeAnimationGroup != index) {
+ d->m_activeAnimationGroup = index;
+ d->updatePosition(d->m_position);
+ emit activeAnimationGroupChanged(index);
+ }
+}
+void QAnimationController::setPosition(float position)
+{
+ Q_D(QAnimationController);
+ if (!qFuzzyCompare(d->m_position, position)) {
+ d->updatePosition(position);
+ emit positionChanged(position);
+ }
+}
+
+void QAnimationController::setPositionScale(float scale)
+{
+ Q_D(QAnimationController);
+ if (!qFuzzyCompare(d->m_positionScale, scale)) {
+ d->m_positionScale = scale;
+ emit positionScaleChanged(scale);
+ }
+}
+
+void QAnimationController::setPositionOffset(float offset)
+{
+ Q_D(QAnimationController);
+ if (!qFuzzyCompare(d->m_positionOffset, offset)) {
+ d->m_positionOffset = offset;
+ emit positionOffsetChanged(offset);
+ }
+}
+
+void QAnimationController::setEntity(Qt3DCore::QEntity *entity)
+{
+ Q_D(QAnimationController);
+ if (d->m_entity != entity) {
+ d->clearAnimations();
+ d->m_entity = entity;
+ d->extractAnimations();
+ d->updatePosition(d->m_position);
+ emit entityChanged(entity);
+ }
+}
+
+void QAnimationController::setRecursive(bool recursive)
+{
+ Q_D(QAnimationController);
+ if (d->m_recursive != recursive) {
+ d->m_recursive = recursive;
+ emit recursiveChanged(recursive);
+ }
+}
+
+int QAnimationController::getAnimationIndex(const QString &name) const
+{
+ Q_D(const QAnimationController);
+ for (int i = 0; i < d->m_animationGroups.size(); ++i) {
+ if (d->m_animationGroups[i]->name() == name)
+ return i;
+ }
+ return -1;
+}
+
+QAnimationGroup *QAnimationController::getGroup(int index) const
+{
+ Q_D(const QAnimationController);
+ return d->m_animationGroups.at(index);
+}
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
diff --git a/src/extras/animations/qanimationcontroller.h b/src/extras/animations/qanimationcontroller.h
new file mode 100644
index 000000000..4ee32dd8b
--- /dev/null
+++ b/src/extras/animations/qanimationcontroller.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QANIMATIONCONTROLLER_H
+#define QT3DEXTRAS_QANIMATIONCONTROLLER_H
+
+#include <Qt3DExtras/qkeyframeanimation.h>
+#include <Qt3DExtras/qanimationgroup.h>
+#include <Qt3DCore/qentity.h>
+
+#include <Qt3DExtras/qt3dextras_global.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+class QAnimationControllerPrivate;
+
+class QT3DEXTRASSHARED_EXPORT QAnimationController : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int activeAnimationGroup READ activeAnimationGroup WRITE setActiveAnimationGroup NOTIFY activeAnimationGroupChanged)
+ Q_PROPERTY(float position READ position WRITE setPosition NOTIFY positionChanged)
+ Q_PROPERTY(float positionScale READ positionScale WRITE setPositionScale NOTIFY positionScaleChanged)
+ Q_PROPERTY(float positionOffset READ positionOffset WRITE setPositionOffset NOTIFY positionOffsetChanged)
+ Q_PROPERTY(Qt3DCore::QEntity *entity READ entity WRITE setEntity NOTIFY entityChanged)
+ Q_PROPERTY(bool recursive READ recursive WRITE setRecursive NOTIFY recursiveChanged)
+
+public:
+ QAnimationController(QObject *parent = nullptr);
+
+ QVector<Qt3DExtras::QAnimationGroup *> animationGroupList();
+
+ int activeAnimationGroup() const;
+ float position() const;
+ float positionScale() const;
+ float positionOffset() const;
+ Qt3DCore::QEntity *entity() const;
+ bool recursive() const;
+
+ void setAnimationGroups(const QVector<Qt3DExtras::QAnimationGroup *> &animationGroups);
+ void addAnimationGroup(Qt3DExtras::QAnimationGroup *animationGroups);
+ void removeAnimationGroup(Qt3DExtras::QAnimationGroup *animationGroups);
+
+ Q_INVOKABLE int getAnimationIndex(const QString &name) const;
+ Q_INVOKABLE Qt3DExtras::QAnimationGroup *getGroup(int index) const;
+
+public Q_SLOTS:
+ void setActiveAnimationGroup(int index);
+ void setPosition(float position);
+ void setPositionScale(float scale);
+ void setPositionOffset(float offset);
+ void setEntity(Qt3DCore::QEntity *entity);
+ void setRecursive(bool recursive);
+
+Q_SIGNALS:
+ void activeAnimationGroupChanged(int index);
+ void positionChanged(float position);
+ void positionScaleChanged(float scale);
+ void positionOffsetChanged(float offset);
+ void entityChanged(Qt3DCore::QEntity *entity);
+ void recursiveChanged(bool recursive);
+
+private:
+ Q_DECLARE_PRIVATE(QAnimationController)
+};
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QANIMATIONCONTROLLER_H
diff --git a/src/extras/animations/qanimationcontroller_p.h b/src/extras/animations/qanimationcontroller_p.h
new file mode 100644
index 000000000..dd5079ef5
--- /dev/null
+++ b/src/extras/animations/qanimationcontroller_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QANIMATIONCONTROLLER_P_H
+#define QT3DEXTRAS_QANIMATIONCONTROLLER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qobject_p.h>
+#include <Qt3DExtras/QAnimationGroup>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+class QAnimationControllerPrivate : public QObjectPrivate
+{
+public:
+ QAnimationControllerPrivate();
+
+ QString m_name;
+ int m_activeAnimationGroup;
+ QVector<QAnimationGroup *> m_animationGroups;
+ float m_position;
+ float m_positionScale;
+ float m_positionOffset;
+ Qt3DCore::QEntity *m_entity;
+ bool m_recursive;
+
+ void updatePosition(float position);
+ void extractAnimations();
+ void clearAnimations();
+ QAnimationGroup *findGroup(const QString &name);
+
+ Q_DECLARE_PUBLIC(QAnimationController)
+};
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QANIMATIONCONTROLLER_P_H
diff --git a/src/extras/animations/qanimationgroup.cpp b/src/extras/animations/qanimationgroup.cpp
new file mode 100644
index 000000000..e9febe811
--- /dev/null
+++ b/src/extras/animations/qanimationgroup.cpp
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qanimationgroup.h"
+#include "Qt3DExtras/private/qanimationgroup_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+QAnimationGroupPrivate::QAnimationGroupPrivate()
+ : QObjectPrivate()
+ , m_position(0.0f)
+ , m_duration(0.0f)
+{
+
+}
+
+void QAnimationGroupPrivate::updatePosition(float position)
+{
+ m_position = position;
+ for (QAbstractAnimation *aa : m_animations)
+ aa->setPosition(position);
+}
+
+QAnimationGroup::QAnimationGroup(QObject *parent)
+ : QObject(*new QAnimationGroupPrivate, parent)
+{
+
+}
+
+QString QAnimationGroup::name() const
+{
+ Q_D(const QAnimationGroup);
+ return d->m_name;
+}
+
+QVector<Qt3DExtras::QAbstractAnimation *> QAnimationGroup::animationList()
+{
+ Q_D(QAnimationGroup);
+ return d->m_animations;
+}
+
+float QAnimationGroup::position() const
+{
+ Q_D(const QAnimationGroup);
+ return d->m_position;
+}
+
+float QAnimationGroup::duration() const
+{
+ Q_D(const QAnimationGroup);
+ return d->m_duration;
+}
+
+void QAnimationGroup::setName(const QString &name)
+{
+ Q_D(QAnimationGroup);
+ if (d->m_name != name) {
+ d->m_name = name;
+ emit nameChanged(name);
+ }
+}
+
+void QAnimationGroup::setAnimations(const QVector<Qt3DExtras::QAbstractAnimation *> &animations)
+{
+ Q_D(QAnimationGroup);
+ d->m_animations = animations;
+ d->m_duration = 0.0f;
+ for (const Qt3DExtras::QAbstractAnimation *a : animations)
+ d->m_duration = qMax(d->m_duration, a->duration());
+}
+
+void QAnimationGroup::addAnimation(QAbstractAnimation *animation)
+{
+ Q_D(QAnimationGroup);
+ d->m_animations.push_back(animation);
+ d->m_duration = qMax(d->m_duration, animation->duration());
+}
+
+void QAnimationGroup::setPosition(float position)
+{
+ Q_D(QAnimationGroup);
+ if (!qFuzzyCompare(d->m_position, position)) {
+ d->updatePosition(position);
+ emit positionChanged(position);
+ }
+}
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
diff --git a/src/extras/animations/qanimationgroup.h b/src/extras/animations/qanimationgroup.h
new file mode 100644
index 000000000..4595a2082
--- /dev/null
+++ b/src/extras/animations/qanimationgroup.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QANIMATIONGROUP_H
+#define QT3DEXTRAS_QANIMATIONGROUP_H
+
+#include <qobject.h>
+
+#include <Qt3DExtras/qabstractanimation.h>
+
+#include <Qt3DExtras/qt3dextras_global.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+class QAnimationGroupPrivate;
+
+class QT3DEXTRASSHARED_EXPORT QAnimationGroup : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+ Q_PROPERTY(float position READ position WRITE setPosition NOTIFY positionChanged)
+ Q_PROPERTY(float duration READ duration NOTIFY durationChanged)
+
+public:
+ explicit QAnimationGroup(QObject *parent = nullptr);
+
+ QString name() const;
+ QVector<Qt3DExtras::QAbstractAnimation *> animationList();
+ float position() const;
+ float duration() const;
+
+ void setAnimations(const QVector<Qt3DExtras::QAbstractAnimation *> &animations);
+ void addAnimation(Qt3DExtras::QAbstractAnimation *animation);
+ void removeAnimation(Qt3DExtras::QAbstractAnimation *animation);
+
+public Q_SLOTS:
+ void setName(const QString &name);
+ void setPosition(float position);
+
+Q_SIGNALS:
+ void nameChanged(const QString &name);
+ void positionChanged(float position);
+ void durationChanged(float duration);
+
+private:
+
+ Q_DECLARE_PRIVATE(QAnimationGroup)
+};
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QANIMATIONGROUP_H
diff --git a/src/extras/animations/qanimationgroup_p.h b/src/extras/animations/qanimationgroup_p.h
new file mode 100644
index 000000000..cffe44636
--- /dev/null
+++ b/src/extras/animations/qanimationgroup_p.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QANIMATIONGROUP_P_H
+#define QT3DEXTRAS_QANIMATIONGROUP_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qobject_p.h>
+#include <Qt3DExtras/QAnimationGroup>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+class QAnimationGroupPrivate : public QObjectPrivate
+{
+public:
+ QAnimationGroupPrivate();
+
+ QString m_name;
+ QVector<Qt3DExtras::QAbstractAnimation *> m_animations;
+ float m_position;
+ float m_duration;
+
+ void updatePosition(float position);
+
+ Q_DECLARE_PUBLIC(QAnimationGroup)
+};
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QANIMATIONGROUP_P_H
diff --git a/src/extras/animations/qkeyframeanimation.cpp b/src/extras/animations/qkeyframeanimation.cpp
new file mode 100644
index 000000000..425cbe0df
--- /dev/null
+++ b/src/extras/animations/qkeyframeanimation.cpp
@@ -0,0 +1,262 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qkeyframeanimation.h"
+#include "Qt3DExtras/private/qkeyframeanimation_p.h"
+
+#include <cmath>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+QKeyframeAnimationPrivate::QKeyframeAnimationPrivate()
+ : QAbstractAnimationPrivate(QAbstractAnimation::KeyframeAnimation)
+ , m_minposition(0.0f)
+ , m_maxposition(0.0f)
+ , m_prevPosition(-1.0f)
+ , m_target(nullptr)
+ , m_startMode(QKeyframeAnimation::Constant)
+ , m_endMode(QKeyframeAnimation::Constant)
+{
+
+}
+
+QKeyframeAnimation::QKeyframeAnimation(QObject *parent)
+ : QAbstractAnimation(*new QKeyframeAnimationPrivate(), parent)
+{
+ Q_D(QKeyframeAnimation);
+ d->m_positionConnection = QObject::connect(this, &QAbstractAnimation::positionChanged,
+ this, &QKeyframeAnimation::updateAnimation);
+}
+
+
+void QKeyframeAnimation::setFramePositions(const QVector<float> &positions)
+{
+ Q_D(QKeyframeAnimation);
+ d->m_framePositions = positions;
+ d->m_prevPosition = -1.0f;
+ if (d->m_framePositions.size() == 0) {
+ d->m_minposition = d->m_maxposition = 0.0f;
+ return;
+ }
+ d->m_minposition = d->m_framePositions.first();
+ d->m_maxposition = d->m_framePositions.last();
+ float lastPos = d->m_minposition;
+ for (float p : d->m_framePositions) {
+ if (p < lastPos || p > d->m_maxposition)
+ qWarning() << "positions not ordered correctly";
+ lastPos = p;
+ }
+ setDuration(d->m_maxposition);
+}
+
+void QKeyframeAnimation::setKeyframes(const QVector<Qt3DCore::QTransform *> &keyframes)
+{
+ Q_D(QKeyframeAnimation);
+ d->m_keyframes = keyframes;
+}
+
+// slerp which allows long path
+QQuaternion lslerp(QQuaternion q1, QQuaternion q2, float t)
+{
+ QQuaternion ret;
+ // Handle the easy cases first.
+ if (t <= 0.0f)
+ return q1;
+ else if (t >= 1.0f)
+ return q2;
+
+ float cos = qBound(-1.0f, QQuaternion::dotProduct(q1, q2), 1.0f);
+ float angle = std::acos(cos);
+ float sin = std::sin(angle);
+ if (!qFuzzyIsNull(sin)) {
+ float a = std::sin((1.0 - t) * angle) / sin;
+ float b = std::sin(t * angle) / sin;
+ ret = (q1 * a + q2 * b).normalized();
+ } else {
+ ret = q1 * (1.0f-t) + q2 * t;
+ }
+ return ret;
+}
+
+void QKeyframeAnimationPrivate::calculateFrame(float position)
+{
+ if (m_target && m_framePositions.size() > 0
+ && m_keyframes.size() == m_framePositions.size()
+ && m_prevPosition != m_position) {
+ if (m_position >= m_minposition && m_position < m_maxposition) {
+ for (int i = 0; i < m_framePositions.size() - 1; i++) {
+ if (position >= m_framePositions.at(i)
+ && position < m_framePositions.at(i+1)) {
+ float ip = (position - m_framePositions.at(i))
+ / (m_framePositions.at(i+1) - m_framePositions.at(i));
+ float eIp = m_easing.valueForProgress(ip);
+ float eIip = 1.0f - eIp;
+
+ Qt3DCore::QTransform *a = m_keyframes.at(i);
+ Qt3DCore::QTransform *b = m_keyframes.at(i+1);
+
+ QVector3D s = a->scale3D() * eIip + b->scale3D() * eIp;
+ QVector3D t = a->translation() * eIip + b->translation() * eIp;
+ QQuaternion r = QQuaternion::slerp(a->rotation(), b->rotation(), eIp);
+
+ m_target->setRotation(r);
+ m_target->setScale3D(s);
+ m_target->setTranslation(t);
+ return;
+ }
+ }
+ } else if (position < m_minposition) {
+ m_target->setRotation(m_keyframes.first()->rotation());
+ m_target->setScale3D(m_keyframes.first()->scale3D());
+ m_target->setTranslation(m_keyframes.first()->translation());
+ } else {
+ m_target->setRotation(m_keyframes.last()->rotation());
+ m_target->setScale3D(m_keyframes.last()->scale3D());
+ m_target->setTranslation(m_keyframes.last()->translation());
+ }
+ m_prevPosition = m_position;
+ }
+}
+
+void QKeyframeAnimation::updateAnimation(float position)
+{
+ Q_D(QKeyframeAnimation);
+ d->calculateFrame(position);
+}
+
+QVector<float> QKeyframeAnimation::framePositions() const
+{
+ Q_D(const QKeyframeAnimation);
+ return d->m_framePositions;
+}
+
+QVector<Qt3DCore::QTransform *> QKeyframeAnimation::keyframeList() const
+{
+ Q_D(const QKeyframeAnimation);
+ return d->m_keyframes;
+}
+
+void QKeyframeAnimation::setTarget(Qt3DCore::QTransform *target)
+{
+ Q_D(QKeyframeAnimation);
+ if (d->m_target != target) {
+ d->m_target = target;
+ emit targetChanged(d->m_target);
+ d->m_prevPosition = -1.0f;
+
+ if (target) {
+ d->m_baseScale = target->scale3D();
+ d->m_baseTranslation = target->translation();
+ d->m_baseRotation = target->rotation();
+ }
+ }
+}
+
+QKeyframeAnimation::RepeatMode QKeyframeAnimation::startMode() const
+{
+ Q_D(const QKeyframeAnimation);
+ return d->m_startMode;
+}
+
+QKeyframeAnimation::RepeatMode QKeyframeAnimation::endMode() const
+{
+ Q_D(const QKeyframeAnimation);
+ return d->m_endMode;
+}
+
+void QKeyframeAnimation::setEasing(QEasingCurve::Type easing)
+{
+ Q_D(QKeyframeAnimation);
+ if (d->m_easing.type() != easing) {
+ d->m_easing.setType(easing);
+ emit easingChanged(easing);
+ }
+}
+
+void QKeyframeAnimation::setTargetName(const QString &name)
+{
+ Q_D(QKeyframeAnimation);
+ d->m_targetName = name;
+ emit targetNameChanged(name);
+}
+
+void QKeyframeAnimation::setStartMode(QKeyframeAnimation::RepeatMode mode)
+{
+ Q_D(QKeyframeAnimation);
+ if (d->m_startMode != mode) {
+ d->m_startMode = mode;
+ emit startModeChanged(mode);
+ }
+}
+
+void QKeyframeAnimation::setEndMode(QKeyframeAnimation::RepeatMode mode)
+{
+ Q_D(QKeyframeAnimation);
+ if (mode != d->m_endMode) {
+ d->m_endMode = mode;
+ emit endModeChanged(mode);
+ }
+}
+
+void QKeyframeAnimation::addKeyframe(Qt3DCore::QTransform *keyframe)
+{
+ Q_D(QKeyframeAnimation);
+ d->m_keyframes.push_back(keyframe);
+}
+
+QString QKeyframeAnimation::targetName() const
+{
+ Q_D(const QKeyframeAnimation);
+ return d->m_targetName;
+}
+
+QEasingCurve::Type QKeyframeAnimation::easing() const
+{
+ Q_D(const QKeyframeAnimation);
+ return d->m_easing.type();
+}
+
+Qt3DCore::QTransform *QKeyframeAnimation::target() const
+{
+ Q_D(const QKeyframeAnimation);
+ return d->m_target;
+}
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
diff --git a/src/extras/animations/qkeyframeanimation.h b/src/extras/animations/qkeyframeanimation.h
new file mode 100644
index 000000000..178c9dbf1
--- /dev/null
+++ b/src/extras/animations/qkeyframeanimation.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QKEYFRAMEANIMATION_H
+#define QT3DEXTRAS_QKEYFRAMEANIMATION_H
+
+#include <Qt3DCore/qtransform.h>
+
+#include <Qt3DExtras/qabstractanimation.h>
+#include <Qt3DExtras/qt3dextras_global.h>
+
+#include <QtCore/qeasingcurve.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+class QKeyframeAnimationPrivate;
+
+class QT3DEXTRASSHARED_EXPORT QKeyframeAnimation : public QAbstractAnimation
+{
+ Q_OBJECT
+ Q_PROPERTY(QVector<float> framePositions READ framePositions WRITE setFramePositions NOTIFY framePositionsChanged)
+ Q_PROPERTY(Qt3DCore::QTransform *target READ target WRITE setTarget NOTIFY targetChanged)
+ Q_PROPERTY(QEasingCurve::Type easing READ easing WRITE setEasing NOTIFY easingChanged)
+ Q_PROPERTY(QString targetName READ targetName WRITE setTargetName NOTIFY targetNameChanged)
+ Q_PROPERTY(QKeyframeAnimation::RepeatMode startMode READ startMode WRITE setStartMode NOTIFY startModeChanged)
+ Q_PROPERTY(QKeyframeAnimation::RepeatMode endMode READ endMode WRITE setEndMode NOTIFY endModeChanged)
+
+public:
+ explicit QKeyframeAnimation(QObject *parent = nullptr);
+
+ enum RepeatMode
+ {
+ None,
+ Constant,
+ Repeat,
+ };
+ Q_ENUM(RepeatMode)
+
+ QVector<float> framePositions() const;
+ QVector<Qt3DCore::QTransform *> keyframeList() const;
+ Qt3DCore::QTransform *target() const;
+ QEasingCurve::Type easing() const;
+ QString targetName() const;
+ RepeatMode startMode() const;
+ RepeatMode endMode() const;
+
+ void setKeyframes(const QVector<Qt3DCore::QTransform *> &keyframes);
+ void addKeyframe(Qt3DCore::QTransform *keyframe);
+ void removeKeyframe(Qt3DCore::QTransform *keyframe);
+
+public Q_SLOTS:
+ void setFramePositions(const QVector<float> &positions);
+ void setTarget(Qt3DCore::QTransform *target);
+ void setEasing(QEasingCurve::Type easing);
+ void setTargetName(const QString &name);
+ void setStartMode(RepeatMode mode);
+ void setEndMode(RepeatMode mode);
+
+Q_SIGNALS:
+ void framePositionsChanged(const QVector<float> &positions);
+ void targetChanged(Qt3DCore::QTransform *target);
+ void easingChanged(QEasingCurve::Type easing);
+ void targetNameChanged(const QString &name);
+ void startModeChanged(RepeatMode startMode);
+ void endModeChanged(RepeatMode endMode);
+
+private:
+ void updateAnimation(float position);
+
+ Q_DECLARE_PRIVATE(QKeyframeAnimation)
+};
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QKEYFRAMEANIMATION_H
diff --git a/src/extras/animations/qkeyframeanimation_p.h b/src/extras/animations/qkeyframeanimation_p.h
new file mode 100644
index 000000000..0095b9432
--- /dev/null
+++ b/src/extras/animations/qkeyframeanimation_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QKEYFRAMEANIMATION_P_H
+#define QT3DEXTRAS_QKEYFRAMEANIMATION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qobject_p.h>
+#include <Qt3DExtras/qkeyframeanimation.h>
+#include <private/qabstractanimation_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+class QKeyframeAnimationPrivate : public QAbstractAnimationPrivate
+{
+public:
+ QKeyframeAnimationPrivate();
+
+ void calculateFrame(float position);
+
+ float m_prevPosition;
+ QVector<float> m_framePositions;
+ QVector<Qt3DCore::QTransform *> m_keyframes;
+ Qt3DCore::QTransform *m_target;
+ QEasingCurve m_easing;
+ QString m_animationName;
+ QString m_targetName;
+ float m_minposition;
+ float m_maxposition;
+ QKeyframeAnimation::RepeatMode m_startMode;
+ QKeyframeAnimation::RepeatMode m_endMode;
+ QVector3D m_baseScale;
+ QVector3D m_baseTranslation;
+ QQuaternion m_baseRotation;
+ QMetaObject::Connection m_positionConnection;
+
+ Q_DECLARE_PUBLIC(QKeyframeAnimation)
+};
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QKEYFRAMEANIMATION_P_H
diff --git a/src/extras/animations/qmorphinganimation.cpp b/src/extras/animations/qmorphinganimation.cpp
new file mode 100644
index 000000000..e7fe05147
--- /dev/null
+++ b/src/extras/animations/qmorphinganimation.cpp
@@ -0,0 +1,280 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmorphinganimation.h"
+#include <private/qmorphinganimation_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+QMorphingAnimationPrivate::QMorphingAnimationPrivate()
+ : QAbstractAnimationPrivate(QAbstractAnimation::MorphingAnimation)
+ , m_flattened(nullptr)
+ , m_method(QMorphingAnimation::Relative)
+ , m_interpolator(0.0f)
+ , m_target(nullptr)
+ , m_currentTarget(nullptr)
+{
+ m_easing.setType(QEasingCurve::InOutCubic);
+}
+
+QMorphingAnimationPrivate::~QMorphingAnimationPrivate()
+{
+ for (QVector<float> *weights : m_weights)
+ delete weights;
+}
+
+void QMorphingAnimationPrivate::updateAnimation(float position)
+{
+ Q_Q(QMorphingAnimation);
+ if (!m_target || !m_target->geometry())
+ return;
+
+ m_morphKey.resize(m_morphTargets.size());
+
+ for (int i = 0; i < m_targetPositions.size() - 1; ++i) {
+ if (position > m_targetPositions.at(i) && position <= m_targetPositions.at(i + 1)) {
+ float interpolator = (position - m_targetPositions.at(i))
+ / (m_targetPositions.at(i + 1) - m_targetPositions.at(i));
+ interpolator = m_easing.valueForProgress(interpolator);
+ float iip = 1.0f - interpolator;
+ float sum = 0.0f;
+ QVector<int> relevantValues;
+ for (int j = 0; j < m_morphTargets.size(); ++j) {
+ m_morphKey[j] = interpolator * m_weights.at(i + 1)->at(j)
+ + iip * m_weights.at(i)->at(j);
+ sum += m_morphKey[j];
+ if (!qFuzzyIsNull(m_morphKey[j]))
+ relevantValues.push_back(j);
+ }
+
+ if (relevantValues.size() == 0 || qFuzzyIsNull(sum)) {
+ // only base is used
+ interpolator = 0.0f;
+ } else if (relevantValues.size() == 1) {
+ // one morph target has non-zero weight
+ setTargetInterpolated(relevantValues[0]);
+ interpolator = sum;
+ } else {
+ // more than one morph target has non-zero weight
+ // flatten morph targets to one
+ qWarning() << Q_FUNC_INFO << "Flattening required";
+ }
+ if (!qFuzzyCompare(interpolator, m_interpolator)) {
+ if (m_method == QMorphingAnimation::Normalized)
+ m_interpolator = interpolator;
+ else
+ m_interpolator = -interpolator;
+ emit q->interpolatorChanged(m_interpolator);
+ }
+ return;
+ }
+ }
+}
+
+void QMorphingAnimationPrivate::setTargetInterpolated(int morphTarget)
+{
+ QMorphTarget *target = m_morphTargets[morphTarget];
+ Qt3DRender::QGeometry *geometry = m_target->geometry();
+
+ // remove attributes from previous frame
+ if (m_currentTarget && (target != m_currentTarget)) {
+ const QVector<Qt3DRender::QAttribute *> targetAttributes = m_currentTarget->attributeList();
+ for (int i = 0; i < targetAttributes.size(); ++i)
+ geometry->removeAttribute(targetAttributes.at(i));
+ }
+
+ const QVector<Qt3DRender::QAttribute *> targetAttributes = target->attributeList();
+
+ // add attributes from current frame to the geometry
+ if (target != m_currentTarget) {
+ for (int i = 0; i < m_attributeNames.size(); ++i) {
+ QString targetName = m_attributeNames.at(i);
+ targetName.append("Target");
+ targetAttributes[i]->setName(targetName);
+ geometry->addAttribute(targetAttributes.at(i));
+ }
+ }
+ m_currentTarget = target;
+}
+
+QMorphingAnimation::QMorphingAnimation(QObject *parent)
+ : QAbstractAnimation(*new QMorphingAnimationPrivate, parent)
+{
+ Q_D(QMorphingAnimation);
+ d->m_positionConnection = QObject::connect(this, &QAbstractAnimation::positionChanged,
+ this, &QMorphingAnimation::updateAnimation);
+}
+
+QVector<float> QMorphingAnimation::targetPositions() const
+{
+ Q_D(const QMorphingAnimation);
+ return d->m_targetPositions;
+}
+
+float QMorphingAnimation::interpolator() const
+{
+ Q_D(const QMorphingAnimation);
+ return d->m_interpolator;
+}
+
+Qt3DRender::QGeometryRenderer *QMorphingAnimation::target() const
+{
+ Q_D(const QMorphingAnimation);
+ return d->m_target;
+}
+
+QString QMorphingAnimation::targetName() const
+{
+ Q_D(const QMorphingAnimation);
+ return d->m_targetName;
+}
+
+QMorphingAnimation::Method QMorphingAnimation::method() const
+{
+ Q_D(const QMorphingAnimation);
+ return d->m_method;
+}
+
+QEasingCurve::Type QMorphingAnimation::easing() const
+{
+ Q_D(const QMorphingAnimation);
+ return d->m_easing.type();
+}
+
+void QMorphingAnimation::setMorphTargets(const QVector<Qt3DExtras::QMorphTarget *> &targets)
+{
+ Q_D(QMorphingAnimation);
+ d->m_morphTargets = targets;
+ d->m_attributeNames = targets[0]->attributeNames();
+}
+
+void QMorphingAnimation::addMorphTarget(Qt3DExtras::QMorphTarget *target)
+{
+ Q_D(QMorphingAnimation);
+ if (!d->m_morphTargets.contains(target))
+ d->m_morphTargets.push_back(target);
+}
+
+void QMorphingAnimation::removeMorphTarget(Qt3DExtras::QMorphTarget *target)
+{
+ Q_D(QMorphingAnimation);
+ d->m_morphTargets.removeAll(target);
+}
+
+void QMorphingAnimation::setTargetPositions(const QVector<float> &targetPositions)
+{
+ Q_D(QMorphingAnimation);
+ d->m_targetPositions = targetPositions;
+ emit targetPositionsChanged(targetPositions);
+ setDuration(d->m_targetPositions.last());
+ if (d->m_weights.size() < targetPositions.size()) {
+ d->m_weights.resize(targetPositions.size());
+ for (int i = 0; i < d->m_weights.size(); ++i) {
+ if (d->m_weights[i] == nullptr)
+ d->m_weights[i] = new QVector<float>();
+ }
+ }
+}
+
+void QMorphingAnimation::setTarget(Qt3DRender::QGeometryRenderer *target)
+{
+ Q_D(QMorphingAnimation);
+ if (d->m_target != target) {
+ d->m_target = target;
+ emit targetChanged(target);
+ }
+}
+
+void QMorphingAnimation::setWeights(int positionIndex, const QVector<float> &weights)
+{
+ Q_D(QMorphingAnimation);
+ if (d->m_weights.size() < positionIndex)
+ d->m_weights.resize(positionIndex + 1);
+ if (d->m_weights[positionIndex] == nullptr)
+ d->m_weights[positionIndex] = new QVector<float>();
+ *d->m_weights[positionIndex] = weights;
+}
+
+QVector<float> QMorphingAnimation::getWeights(int positionIndex)
+{
+ Q_D(QMorphingAnimation);
+ return *d->m_weights[positionIndex];
+}
+
+QVector<Qt3DExtras::QMorphTarget *> QMorphingAnimation::morphTargetList()
+{
+ Q_D(QMorphingAnimation);
+ return d->m_morphTargets;
+}
+
+void QMorphingAnimation::setTargetName(const QString name)
+{
+ Q_D(QMorphingAnimation);
+ if (d->m_targetName != name) {
+ d->m_targetName = name;
+ emit targetNameChanged(name);
+ }
+}
+
+void QMorphingAnimation::setMethod(QMorphingAnimation::Method method)
+{
+ Q_D(QMorphingAnimation);
+ if (d->m_method != method) {
+ d->m_method = method;
+ emit methodChanged(method);
+ }
+}
+
+void QMorphingAnimation::setEasing(QEasingCurve::Type easing)
+{
+ Q_D(QMorphingAnimation);
+ if (d->m_easing.type() != easing) {
+ d->m_easing.setType(easing);
+ emit easingChanged(easing);
+ }
+}
+
+void QMorphingAnimation::updateAnimation(float position)
+{
+ Q_D(QMorphingAnimation);
+ d->updateAnimation(position);
+}
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
diff --git a/src/extras/animations/qmorphinganimation.h b/src/extras/animations/qmorphinganimation.h
new file mode 100644
index 000000000..f8ca71ec9
--- /dev/null
+++ b/src/extras/animations/qmorphinganimation.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QMORPHINGANIMATION_H
+#define QT3DEXTRAS_QMORPHINGANIMATION_H
+
+#include <Qt3DRender/qgeometryrenderer.h>
+
+#include <Qt3DExtras/qabstractanimation.h>
+#include <Qt3DExtras/qmorphtarget.h>
+#include <Qt3DExtras/qt3dextras_global.h>
+
+#include <QtCore/qeasingcurve.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+class QMorphingAnimationPrivate;
+
+class QT3DEXTRASSHARED_EXPORT QMorphingAnimation : public QAbstractAnimation
+{
+ Q_OBJECT
+ Q_PROPERTY(QVector<float> targetPositions READ targetPositions WRITE setTargetPositions NOTIFY targetPositionsChanged)
+ Q_PROPERTY(float interpolator READ interpolator NOTIFY interpolatorChanged)
+ Q_PROPERTY(Qt3DRender::QGeometryRenderer *target READ target WRITE setTarget NOTIFY targetChanged)
+ Q_PROPERTY(QString targetName READ targetName WRITE setTargetName NOTIFY targetNameChanged)
+ Q_PROPERTY(QMorphingAnimation::Method method READ method WRITE setMethod NOTIFY methodChanged)
+ Q_PROPERTY(QEasingCurve::Type easing READ easing WRITE setEasing NOTIFY easingChanged)
+
+public:
+ enum Method
+ {
+ Normalized,
+ Relative
+ };
+ Q_ENUM(Method)
+
+ explicit QMorphingAnimation(QObject *parent = nullptr);
+
+ QVector<float> targetPositions() const;
+ float interpolator() const;
+ Qt3DRender::QGeometryRenderer *target() const;
+ QString targetName() const;
+ QMorphingAnimation::Method method() const;
+ QEasingCurve::Type easing() const;
+
+ void setMorphTargets(const QVector<Qt3DExtras::QMorphTarget *> &targets);
+ void addMorphTarget(Qt3DExtras::QMorphTarget *target);
+ void removeMorphTarget(Qt3DExtras::QMorphTarget *target);
+
+ void setWeights(int positionIndex, const QVector<float> &weights);
+ QVector<float> getWeights(int positionIndex);
+
+ QVector<Qt3DExtras::QMorphTarget *> morphTargetList();
+
+public Q_SLOTS:
+ void setTargetPositions(const QVector<float> &targetPositions);
+ void setTarget(Qt3DRender::QGeometryRenderer *target);
+ void setTargetName(const QString name);
+ void setMethod(QMorphingAnimation::Method method);
+ void setEasing(QEasingCurve::Type easing);
+
+Q_SIGNALS:
+ void targetPositionsChanged(const QVector<float> &targetPositions);
+ void interpolatorChanged(float interpolator);
+ void targetChanged(Qt3DRender::QGeometryRenderer *target);
+ void targetNameChanged(const QString &name);
+ void methodChanged(QMorphingAnimation::Method method);
+ void easingChanged(QEasingCurve::Type easing);
+
+private:
+
+ void updateAnimation(float position);
+
+ Q_DECLARE_PRIVATE(QMorphingAnimation)
+};
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QMORPHINGANIMATION_H
diff --git a/src/extras/animations/qmorphinganimation_p.h b/src/extras/animations/qmorphinganimation_p.h
new file mode 100644
index 000000000..e4a18f199
--- /dev/null
+++ b/src/extras/animations/qmorphinganimation_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QMORPHINGANIMATION_P_H
+#define QT3DEXTRAS_QMORPHINGANIMATION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qeasingcurve.h>
+#include <Qt3DExtras/qmorphinganimation.h>
+
+#include <private/qobject_p.h>
+#include <private/qabstractanimation_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+class QMorphingAnimationPrivate : public QAbstractAnimationPrivate
+{
+public:
+ QMorphingAnimationPrivate();
+ ~QMorphingAnimationPrivate();
+
+ void updateAnimation(float position);
+ void setTargetInterpolated(int morphTarget);
+
+ QVector<float> m_targetPositions;
+ QVector<QVector<float>*> m_weights;
+ QVector<float> m_morphKey;
+ QStringList m_attributeNames;
+ QVector<Qt3DExtras::QMorphTarget *> m_morphTargets;
+ QMorphTarget *m_flattened;
+ QMorphingAnimation::Method m_method;
+ QEasingCurve m_easing;
+ float m_interpolator;
+ Qt3DRender::QGeometryRenderer *m_target;
+ QString m_targetName;
+
+ QMorphTarget *m_currentTarget;
+
+ QMetaObject::Connection m_positionConnection;
+
+ Q_DECLARE_PUBLIC(QMorphingAnimation)
+};
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QMORPHINGANIMATION_P_H
diff --git a/src/extras/animations/qmorphtarget.cpp b/src/extras/animations/qmorphtarget.cpp
new file mode 100644
index 000000000..0c327a490
--- /dev/null
+++ b/src/extras/animations/qmorphtarget.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmorphtarget.h"
+#include "Qt3DExtras/private/qmorphtarget_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+QMorphTargetPrivate::QMorphTargetPrivate()
+ : QObjectPrivate()
+{
+
+}
+
+void QMorphTargetPrivate::updateAttributeNames()
+{
+ m_attributeNames.clear();
+ for (const Qt3DRender::QAttribute *attr : m_targetAttributes)
+ m_attributeNames.push_back(attr->name());
+}
+
+QMorphTarget::QMorphTarget(QObject *parent)
+ : QObject(*new QMorphTargetPrivate, parent)
+{
+
+}
+
+QVector<Qt3DRender::QAttribute *> QMorphTarget::attributeList() const
+{
+ Q_D(const QMorphTarget);
+ return d->m_targetAttributes;
+}
+
+QStringList QMorphTarget::attributeNames() const
+{
+ Q_D(const QMorphTarget);
+ return d->m_attributeNames;
+}
+
+void QMorphTarget::setAttributes(const QVector<Qt3DRender::QAttribute *> &attributes)
+{
+ Q_D(QMorphTarget);
+ d->m_targetAttributes = attributes;
+ d->m_attributeNames.clear();
+ for (const Qt3DRender::QAttribute *attr : attributes)
+ d->m_attributeNames.push_back(attr->name());
+
+ emit attributeNamesChanged(d->m_attributeNames);
+}
+
+void QMorphTarget::addAttribute(Qt3DRender::QAttribute *attribute)
+{
+ Q_D(QMorphTarget);
+ for (const Qt3DRender::QAttribute *attr : d->m_targetAttributes) {
+ if (attr->name() == attribute->name())
+ return;
+ }
+ d->m_targetAttributes.push_back(attribute);
+ d->m_attributeNames.push_back(attribute->name());
+ emit attributeNamesChanged(d->m_attributeNames);
+}
+
+void QMorphTarget::removeAttribute(Qt3DRender::QAttribute *attribute)
+{
+ Q_D(QMorphTarget);
+ if (d->m_targetAttributes.contains(attribute)) {
+ d->m_targetAttributes.removeAll(attribute);
+ d->updateAttributeNames();
+ emit attributeNamesChanged(d->m_attributeNames);
+ }
+}
+
+QMorphTarget *QMorphTarget::fromGeometry(Qt3DRender::QGeometry *geometry, const QStringList &attributes)
+{
+ QMorphTarget *target = new QMorphTarget();
+ for (Qt3DRender::QAttribute *attr : geometry->attributes()) {
+ if (attributes.contains(attr->name()))
+ target->addAttribute(attr);
+ }
+ return target;
+}
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
diff --git a/src/extras/animations/qmorphtarget.h b/src/extras/animations/qmorphtarget.h
new file mode 100644
index 000000000..64c3037cb
--- /dev/null
+++ b/src/extras/animations/qmorphtarget.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QMORPHTARGET_H
+#define QT3DEXTRAS_QMORPHTARGET_H
+
+#include <Qt3DRender/qattribute.h>
+#include <Qt3DRender/qgeometry.h>
+
+#include <QtCore/qstringlist.h>
+
+#include <Qt3DExtras/qt3dextras_global.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+class QMorphTargetPrivate;
+
+class QT3DEXTRASSHARED_EXPORT QMorphTarget : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QStringList attributeNames READ attributeNames NOTIFY attributeNamesChanged)
+
+public:
+ explicit QMorphTarget(QObject *parent = nullptr);
+
+ QVector<Qt3DRender::QAttribute *> attributeList() const;
+ QStringList attributeNames() const;
+
+ void setAttributes(const QVector<Qt3DRender::QAttribute *> &attributes);
+ void addAttribute(Qt3DRender::QAttribute *attribute);
+ void removeAttribute(Qt3DRender::QAttribute *attribute);
+
+ Q_INVOKABLE static QMorphTarget *fromGeometry(Qt3DRender::QGeometry *geometry,
+ const QStringList &attributes);
+
+Q_SIGNALS:
+ void attributeNamesChanged(const QStringList &attributeNames);
+
+private:
+
+ Q_DECLARE_PRIVATE(QMorphTarget)
+};
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QMORPHTARGET_H
diff --git a/src/extras/animations/qmorphtarget_p.h b/src/extras/animations/qmorphtarget_p.h
new file mode 100644
index 000000000..7d42f8eb4
--- /dev/null
+++ b/src/extras/animations/qmorphtarget_p.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QMORPHTARGET_P_H
+#define QT3DEXTRAS_QMORPHTARGET_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DExtras/qmorphtarget.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+class QMorphTargetPrivate : public QObjectPrivate
+{
+public:
+ QMorphTargetPrivate();
+
+ void updateAttributeNames();
+
+ QStringList m_attributeNames;
+ QVector<Qt3DRender::QAttribute *> m_targetAttributes;
+
+ Q_DECLARE_PUBLIC(QMorphTarget)
+};
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QMORPHTARGET_P_H
diff --git a/src/extras/animations/qvertexblendanimation.cpp b/src/extras/animations/qvertexblendanimation.cpp
new file mode 100644
index 000000000..1b45992fe
--- /dev/null
+++ b/src/extras/animations/qvertexblendanimation.cpp
@@ -0,0 +1,234 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvertexblendanimation.h"
+
+#include <private/qvertexblendanimation_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+QVertexBlendAnimationPrivate::QVertexBlendAnimationPrivate()
+ : QAbstractAnimationPrivate(QAbstractAnimation::VertexBlendAnimation)
+ , m_currentBase(nullptr)
+ , m_currentTarget(nullptr)
+{
+
+}
+
+void QVertexBlendAnimationPrivate::getAttributesInPosition(float position, int *target0,
+ int *target1, float *interpolator)
+{
+ if (position < m_targetPositions.first()) {
+ *target0 = 0;
+ *target1 = qMin(1, m_targetPositions.size());
+ *interpolator = 0.0f;
+ } else if (position > m_targetPositions.last()) {
+ *target0 = qMax(m_targetPositions.size() - 2, 0);
+ *target1 = qMax(m_targetPositions.size() - 1, 0);
+ *interpolator = 1.0f;
+ } else {
+ for (int i = 0; i < m_targetPositions.size() - 1; i++) {
+ if (position >= m_targetPositions[i] && position < m_targetPositions[i + 1]) {
+ *target0 = i;
+ *target1 = i + 1;
+ float a = (position - m_targetPositions[i])
+ / (m_targetPositions[i + 1] - m_targetPositions[i]);
+ *interpolator = a;
+ }
+ }
+ }
+}
+
+static Qt3DRender::QAttribute *findAttribute(QVector<Qt3DRender::QAttribute *> &attributes,
+ QString name)
+{
+ for (Qt3DRender::QAttribute *gattr : attributes) {
+ if (gattr->name() == name)
+ return gattr;
+ }
+ return nullptr;
+}
+
+void QVertexBlendAnimationPrivate::updateAnimation(float position)
+{
+ Q_Q(QVertexBlendAnimation);
+ if (!m_target || !m_target->geometry())
+ return;
+
+ Qt3DExtras::QMorphTarget *base;
+ Qt3DExtras::QMorphTarget *target;
+ int target0, target1;
+ float interpolator;
+ getAttributesInPosition(position, &target0, &target1, &interpolator);
+
+ base = m_morphTargets.at(target0);
+ target = m_morphTargets.at(target1);
+
+ Qt3DRender::QGeometry *geometry = m_target->geometry();
+
+ // remove attributes from previous frame
+ if ((m_currentBase && (base != m_currentBase))
+ || (m_currentTarget && (target != m_currentTarget))) {
+ const QVector<Qt3DRender::QAttribute *> baseAttributes = m_currentBase->attributeList();
+ const QVector<Qt3DRender::QAttribute *> targetAttributes = m_currentTarget->attributeList();
+ for (int i = 0; i < baseAttributes.size(); ++i) {
+ geometry->removeAttribute(baseAttributes.at(i));
+ geometry->removeAttribute(targetAttributes.at(i));
+ }
+ }
+
+ const QVector<Qt3DRender::QAttribute *> baseAttributes = base->attributeList();
+ const QVector<Qt3DRender::QAttribute *> targetAttributes = target->attributeList();
+ const QStringList attributeNames = base->attributeNames();
+
+ // add attributes from current frame to the geometry
+ if (base != m_currentBase || target != m_currentTarget) {
+ for (int i = 0; i < baseAttributes.size(); ++i) {
+ const QString baseName = attributeNames.at(i);
+ QString targetName = baseName;
+ targetName.append("Target");
+
+ baseAttributes[i]->setName(baseName);
+ geometry->addAttribute(baseAttributes.at(i));
+ targetAttributes[i]->setName(targetName);
+ geometry->addAttribute(targetAttributes.at(i));
+ }
+ }
+ m_currentBase = base;
+ m_currentTarget = target;
+
+ if (!qFuzzyCompare(interpolator, m_interpolator)) {
+ m_interpolator = interpolator;
+ emit q->interpolatorChanged(interpolator);
+ }
+}
+
+QVertexBlendAnimation::QVertexBlendAnimation(QObject *parent)
+ : QAbstractAnimation(*new QVertexBlendAnimationPrivate, parent)
+{
+ Q_D(QVertexBlendAnimation);
+ d->m_positionConnection = QObject::connect(this, &QAbstractAnimation::positionChanged,
+ this, &QVertexBlendAnimation::updateAnimation);
+}
+
+QVector<float> QVertexBlendAnimation::targetPositions() const
+{
+ Q_D(const QVertexBlendAnimation);
+ return d->m_targetPositions;
+}
+
+float QVertexBlendAnimation::interpolator() const
+{
+ Q_D(const QVertexBlendAnimation);
+ return d->m_interpolator;
+}
+
+Qt3DRender::QGeometryRenderer *QVertexBlendAnimation::target() const
+{
+ Q_D(const QVertexBlendAnimation);
+ return d->m_target;
+}
+
+QString QVertexBlendAnimation::targetName() const
+{
+ Q_D(const QVertexBlendAnimation);
+ return d->m_targetName;
+}
+
+void QVertexBlendAnimation::setMorphTargets(const QVector<Qt3DExtras::QMorphTarget *> &targets)
+{
+ Q_D(QVertexBlendAnimation);
+ d->m_morphTargets = targets;
+}
+
+void QVertexBlendAnimation::addMorphTarget(Qt3DExtras::QMorphTarget *target)
+{
+ Q_D(QVertexBlendAnimation);
+ if (!d->m_morphTargets.contains(target))
+ d->m_morphTargets.push_back(target);
+}
+
+void QVertexBlendAnimation::removeMorphTarget(Qt3DExtras::QMorphTarget *target)
+{
+ Q_D(QVertexBlendAnimation);
+ d->m_morphTargets.removeAll(target);
+}
+
+void QVertexBlendAnimation::setTargetPositions(const QVector<float> &targetPositions)
+{
+ Q_D(QVertexBlendAnimation);
+ if (d->m_targetPositions == targetPositions)
+ return;
+ d->m_targetPositions = targetPositions;
+ emit targetPositionsChanged(targetPositions);
+ setDuration(d->m_targetPositions.last());
+}
+
+void QVertexBlendAnimation::setTarget(Qt3DRender::QGeometryRenderer *target)
+{
+ Q_D(QVertexBlendAnimation);
+ if (d->m_target != target) {
+ d->m_target = target;
+ emit targetChanged(target);
+ }
+}
+
+QVector<Qt3DExtras::QMorphTarget *> QVertexBlendAnimation::morphTargetList()
+{
+ Q_D(QVertexBlendAnimation);
+ return d->m_morphTargets;
+}
+
+void QVertexBlendAnimation::setTargetName(const QString name)
+{
+ Q_D(QVertexBlendAnimation);
+ if (d->m_targetName != name) {
+ d->m_targetName = name;
+ emit targetNameChanged(name);
+ }
+}
+
+void QVertexBlendAnimation::updateAnimation(float position)
+{
+ Q_D(QVertexBlendAnimation);
+ d->updateAnimation(position);
+}
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
diff --git a/src/extras/animations/qvertexblendanimation.h b/src/extras/animations/qvertexblendanimation.h
new file mode 100644
index 000000000..ebd313e83
--- /dev/null
+++ b/src/extras/animations/qvertexblendanimation.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QVERTEXBLENDANIMATION_H
+#define QT3DEXTRAS_QVERTEXBLENDANIMATION_H
+
+#include <Qt3DRender/qgeometryrenderer.h>
+#include <Qt3DExtras/qabstractanimation.h>
+#include <Qt3DExtras/qmorphtarget.h>
+
+#include <Qt3DExtras/qt3dextras_global.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+class QVertexBlendAnimationPrivate;
+
+class QT3DEXTRASSHARED_EXPORT QVertexBlendAnimation : public QAbstractAnimation
+{
+ Q_OBJECT
+ Q_PROPERTY(QVector<float> targetPositions READ targetPositions WRITE setTargetPositions NOTIFY targetPositionsChanged)
+ Q_PROPERTY(float interpolator READ interpolator NOTIFY interpolatorChanged)
+ Q_PROPERTY(Qt3DRender::QGeometryRenderer *target READ target WRITE setTarget NOTIFY targetChanged)
+ Q_PROPERTY(QString targetName READ targetName WRITE setTargetName NOTIFY targetNameChanged)
+
+public:
+ explicit QVertexBlendAnimation(QObject *parent = nullptr);
+
+ QVector<float> targetPositions() const;
+ float interpolator() const;
+ Qt3DRender::QGeometryRenderer *target() const;
+ QString targetName() const;
+
+ void setMorphTargets(const QVector<Qt3DExtras::QMorphTarget *> &targets);
+ void addMorphTarget(Qt3DExtras::QMorphTarget *target);
+ void removeMorphTarget(Qt3DExtras::QMorphTarget *target);
+
+ QVector<Qt3DExtras::QMorphTarget *> morphTargetList();
+
+public Q_SLOTS:
+ void setTargetPositions(const QVector<float> &targetPositions);
+ void setTarget(Qt3DRender::QGeometryRenderer *target);
+ void setTargetName(const QString name);
+
+Q_SIGNALS:
+ void targetPositionsChanged(const QVector<float> &targetPositions);
+ void interpolatorChanged(float interpolator);
+ void targetChanged(Qt3DRender::QGeometryRenderer *target);
+ void targetNameChanged(const QString &name);
+
+private:
+
+ void updateAnimation(float position);
+
+ Q_DECLARE_PRIVATE(QVertexBlendAnimation)
+};
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QVERTEXBLENDANIMATION_H
diff --git a/src/extras/animations/qvertexblendanimation_p.h b/src/extras/animations/qvertexblendanimation_p.h
new file mode 100644
index 000000000..812953e04
--- /dev/null
+++ b/src/extras/animations/qvertexblendanimation_p.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QVERTEXBLENDANIMATION_P_H
+#define QT3DEXTRAS_QVERTEXBLENDANIMATION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+
+#include <Qt3DExtras/qvertexblendanimation.h>
+
+#include <private/qobject_p.h>
+#include <private/qabstractanimation_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+class QVertexBlendAnimationPrivate : public QAbstractAnimationPrivate
+{
+public:
+ QVertexBlendAnimationPrivate();
+
+ void getAttributesInPosition(float position, int *target0, int *target1, float *interpolator);
+ void updateAnimation(float position);
+
+ QVector<float> m_targetPositions;
+ QVector<Qt3DExtras::QMorphTarget *> m_morphTargets;
+ float m_interpolator;
+ Qt3DRender::QGeometryRenderer *m_target;
+ QString m_targetName;
+ QMorphTarget *m_currentBase;
+ QMorphTarget *m_currentTarget;
+
+ QMetaObject::Connection m_positionConnection;
+
+ Q_DECLARE_PUBLIC(QVertexBlendAnimation)
+};
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QVertexBlendANIMATION_P_H
diff --git a/src/extras/defaults/defaults.pri b/src/extras/defaults/defaults.pri
index 04cd87246..21ef6fef6 100644
--- a/src/extras/defaults/defaults.pri
+++ b/src/extras/defaults/defaults.pri
@@ -4,7 +4,6 @@ HEADERS += \
$$PWD/qphongmaterial.h \
$$PWD/qphongmaterial_p.h \
$$PWD/qdiffusemapmaterial_p.h \
- $$PWD/qdiffusemapmaterial.h \
$$PWD/qnormaldiffusespecularmapmaterial.h \
$$PWD/qnormaldiffusespecularmapmaterial_p.h \
$$PWD/qnormaldiffusemapmaterial.h \
@@ -27,7 +26,10 @@ HEADERS += \
$$PWD/qfirstpersoncameracontroller.h \
$$PWD/qfirstpersoncameracontroller_p.h \
$$PWD/qorbitcameracontroller.h \
- $$PWD/qorbitcameracontroller_p.h
+ $$PWD/qorbitcameracontroller_p.h \
+ $$PWD/qmorphphongmaterial.h \
+ $$PWD/qmorphphongmaterial_p.h \
+ $$PWD/qdiffusemapmaterial.h
SOURCES += \
$$PWD/qphongmaterial.cpp \
@@ -43,5 +45,6 @@ SOURCES += \
$$PWD/qphongalphamaterial.cpp \
$$PWD/qt3dwindow.cpp \
$$PWD/qfirstpersoncameracontroller.cpp \
- $$PWD/qorbitcameracontroller.cpp
+ $$PWD/qorbitcameracontroller.cpp \
+ $$PWD/qmorphphongmaterial.cpp
diff --git a/src/extras/defaults/qmorphphongmaterial.cpp b/src/extras/defaults/qmorphphongmaterial.cpp
new file mode 100644
index 000000000..22f520de5
--- /dev/null
+++ b/src/extras/defaults/qmorphphongmaterial.cpp
@@ -0,0 +1,291 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmorphphongmaterial.h"
+#include "qmorphphongmaterial_p.h"
+#include <Qt3DRender/qfilterkey.h>
+#include <Qt3DRender/qmaterial.h>
+#include <Qt3DRender/qeffect.h>
+#include <Qt3DRender/qtechnique.h>
+#include <Qt3DRender/qshaderprogram.h>
+#include <Qt3DRender/qparameter.h>
+#include <Qt3DRender/qrenderpass.h>
+#include <Qt3DRender/qgraphicsapifilter.h>
+#include <QUrl>
+#include <QVector3D>
+#include <QVector4D>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt3DRender;
+
+namespace Qt3DExtras {
+
+QMorphPhongMaterialPrivate::QMorphPhongMaterialPrivate()
+ : QMaterialPrivate()
+ , m_phongEffect(new QEffect())
+ , m_ambientParameter(new QParameter(QStringLiteral("ka"), QColor::fromRgbF(0.05f, 0.05f, 0.05f, 1.0f)))
+ , m_diffuseParameter(new QParameter(QStringLiteral("kd"), QColor::fromRgbF(0.7f, 0.7f, 0.7f, 1.0f)))
+ , m_specularParameter(new QParameter(QStringLiteral("ks"), QColor::fromRgbF(0.01f, 0.01f, 0.01f, 1.0f)))
+ , m_shininessParameter(new QParameter(QStringLiteral("shininess"), 150.0f))
+ , m_interpolatorParameter(new QParameter(QStringLiteral("interpolator"), 0.0f))
+ , m_phongGL3Technique(new QTechnique())
+ , m_phongGL2Technique(new QTechnique())
+ , m_phongES2Technique(new QTechnique())
+ , m_phongGL3RenderPass(new QRenderPass())
+ , m_phongGL2RenderPass(new QRenderPass())
+ , m_phongES2RenderPass(new QRenderPass())
+ , m_phongGL3Shader(new QShaderProgram())
+ , m_phongGL2ES2Shader(new QShaderProgram())
+ , m_filterKey(new QFilterKey)
+{
+}
+
+void QMorphPhongMaterialPrivate::init()
+{
+ connect(m_ambientParameter, &Qt3DRender::QParameter::valueChanged,
+ this, &QMorphPhongMaterialPrivate::handleAmbientChanged);
+ connect(m_diffuseParameter, &Qt3DRender::QParameter::valueChanged,
+ this, &QMorphPhongMaterialPrivate::handleDiffuseChanged);
+ connect(m_specularParameter, &Qt3DRender::QParameter::valueChanged,
+ this, &QMorphPhongMaterialPrivate::handleSpecularChanged);
+ connect(m_shininessParameter, &Qt3DRender::QParameter::valueChanged,
+ this, &QMorphPhongMaterialPrivate::handleShininessChanged);
+ connect(m_interpolatorParameter, &Qt3DRender::QParameter::valueChanged,
+ this, &QMorphPhongMaterialPrivate::handleInterpolatorChanged);
+
+ m_phongGL3Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/morphphong.vert"))));
+ m_phongGL3Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/phong.frag"))));
+ m_phongGL2ES2Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/morphphong.vert"))));
+ m_phongGL2ES2Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/phong.frag"))));
+
+ m_phongGL3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL);
+ m_phongGL3Technique->graphicsApiFilter()->setMajorVersion(3);
+ m_phongGL3Technique->graphicsApiFilter()->setMinorVersion(1);
+ m_phongGL3Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::CoreProfile);
+
+ m_phongGL2Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL);
+ m_phongGL2Technique->graphicsApiFilter()->setMajorVersion(2);
+ m_phongGL2Technique->graphicsApiFilter()->setMinorVersion(0);
+ m_phongGL2Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::NoProfile);
+
+ m_phongES2Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGLES);
+ m_phongES2Technique->graphicsApiFilter()->setMajorVersion(2);
+ m_phongES2Technique->graphicsApiFilter()->setMinorVersion(0);
+ m_phongES2Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::NoProfile);
+
+ m_phongGL3RenderPass->setShaderProgram(m_phongGL3Shader);
+ m_phongGL2RenderPass->setShaderProgram(m_phongGL2ES2Shader);
+ m_phongES2RenderPass->setShaderProgram(m_phongGL2ES2Shader);
+
+ m_phongGL3Technique->addRenderPass(m_phongGL3RenderPass);
+ m_phongGL2Technique->addRenderPass(m_phongGL2RenderPass);
+ m_phongES2Technique->addRenderPass(m_phongES2RenderPass);
+
+ Q_Q(QMorphPhongMaterial);
+ m_filterKey->setParent(q);
+ m_filterKey->setName(QStringLiteral("renderingStyle"));
+ m_filterKey->setValue(QStringLiteral("forward"));
+
+ m_phongGL3Technique->addFilterKey(m_filterKey);
+ m_phongGL2Technique->addFilterKey(m_filterKey);
+ m_phongES2Technique->addFilterKey(m_filterKey);
+
+ m_phongEffect->addTechnique(m_phongGL3Technique);
+ m_phongEffect->addTechnique(m_phongGL2Technique);
+ m_phongEffect->addTechnique(m_phongES2Technique);
+
+ m_phongEffect->addParameter(m_ambientParameter);
+ m_phongEffect->addParameter(m_diffuseParameter);
+ m_phongEffect->addParameter(m_specularParameter);
+ m_phongEffect->addParameter(m_shininessParameter);
+ m_phongEffect->addParameter(m_interpolatorParameter);
+
+ q->setEffect(m_phongEffect);
+}
+
+void QMorphPhongMaterialPrivate::handleAmbientChanged(const QVariant &var)
+{
+ Q_Q(QMorphPhongMaterial);
+ emit q->ambientChanged(var.value<QColor>());
+}
+
+void QMorphPhongMaterialPrivate::handleDiffuseChanged(const QVariant &var)
+{
+ Q_Q(QMorphPhongMaterial);
+ emit q->diffuseChanged(var.value<QColor>());
+}
+
+void QMorphPhongMaterialPrivate::handleSpecularChanged(const QVariant &var)
+{
+ Q_Q(QMorphPhongMaterial);
+ emit q->specularChanged(var.value<QColor>());
+}
+
+void QMorphPhongMaterialPrivate::handleShininessChanged(const QVariant &var)
+{
+ Q_Q(QMorphPhongMaterial);
+ emit q->shininessChanged(var.toFloat());
+}
+
+void QMorphPhongMaterialPrivate::handleInterpolatorChanged(const QVariant &var)
+{
+ Q_Q(QMorphPhongMaterial);
+ emit q->interpolatorChanged(var.toFloat());
+}
+
+/*!
+ \class Qt3DExtras::QMorphPhongMaterial
+ \brief The QMorphPhongMaterial class provides a default implementation of the phong lighting effect.
+ \inmodule Qt3DExtras
+ \since 5.7
+ \inherits Qt3DRender::QMaterial
+
+ The phong lighting effect is based on the combination of 3 lighting components ambient, diffuse
+ and specular. The relative strengths of these components are controlled by means of their
+ reflectivity coefficients which are modelled as RGB triplets:
+
+ \list
+ \li Ambient is the color that is emitted by an object without any other light source.
+ \li Diffuse is the color that is emitted for rought surface reflections with the lights.
+ \li Specular is the color emitted for shiny surface reflections with the lights.
+ \li The shininess of a surface is controlled by a float property.
+ \endlist
+
+ This material uses an effect with a single render pass approach and performs per fragment
+ lighting. Techniques are provided for OpenGL 2, OpenGL 3 or above as well as OpenGL ES 2.
+*/
+
+/*!
+ Constructs a new QMorphPhongMaterial instance with parent object \a parent.
+*/
+QMorphPhongMaterial::QMorphPhongMaterial(QNode *parent)
+ : QMaterial(*new QMorphPhongMaterialPrivate, parent)
+{
+ Q_D(QMorphPhongMaterial);
+ d->init();
+}
+
+/*!
+ Destroys the QMorphPhongMaterial.
+*/
+QMorphPhongMaterial::~QMorphPhongMaterial()
+{
+}
+
+/*!
+ \property QMorphPhongMaterial::ambient
+
+ Holds the ambient color.
+*/
+QColor QMorphPhongMaterial::ambient() const
+{
+ Q_D(const QMorphPhongMaterial);
+ return d->m_ambientParameter->value().value<QColor>();
+}
+
+/*!
+ \property QMorphPhongMaterial::diffuse
+
+ Holds the diffuse color.
+*/
+QColor QMorphPhongMaterial::diffuse() const
+{
+ Q_D(const QMorphPhongMaterial);
+ return d->m_diffuseParameter->value().value<QColor>();
+}
+
+/*!
+ \property QMorphPhongMaterial::specular
+
+ Holds the specular color.
+*/
+QColor QMorphPhongMaterial::specular() const
+{
+ Q_D(const QMorphPhongMaterial);
+ return d->m_specularParameter->value().value<QColor>();
+}
+
+/*!
+ \property QMorphPhongMaterial::shininess
+
+ Holds the shininess exponent.
+*/
+float QMorphPhongMaterial::shininess() const
+{
+ Q_D(const QMorphPhongMaterial);
+ return d->m_shininessParameter->value().toFloat();
+}
+
+float QMorphPhongMaterial::interpolator() const
+{
+ Q_D(const QMorphPhongMaterial);
+ return d->m_interpolatorParameter->value().toFloat();
+}
+
+void QMorphPhongMaterial::setAmbient(const QColor &ambient)
+{
+ Q_D(QMorphPhongMaterial);
+ d->m_ambientParameter->setValue(ambient);
+}
+
+void QMorphPhongMaterial::setDiffuse(const QColor &diffuse)
+{
+ Q_D(QMorphPhongMaterial);
+ d->m_diffuseParameter->setValue(diffuse);
+}
+
+void QMorphPhongMaterial::setSpecular(const QColor &specular)
+{
+ Q_D(QMorphPhongMaterial);
+ d->m_specularParameter->setValue(specular);
+}
+
+void QMorphPhongMaterial::setShininess(float shininess)
+{
+ Q_D(QMorphPhongMaterial);
+ d->m_shininessParameter->setValue(shininess);
+}
+
+void QMorphPhongMaterial::setInterpolator(float interpolator)
+{
+ Q_D(QMorphPhongMaterial);
+ d->m_interpolatorParameter->setValue(interpolator);
+}
+
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
diff --git a/src/extras/defaults/qmorphphongmaterial.h b/src/extras/defaults/qmorphphongmaterial.h
new file mode 100644
index 000000000..3b65088b1
--- /dev/null
+++ b/src/extras/defaults/qmorphphongmaterial.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QMORPHPHONGMATERIAL_H
+#define QT3DEXTRAS_QMORPHPHONGMATERIAL_H
+
+#include <Qt3DExtras/qt3dextras_global.h>
+#include <Qt3DRender/qmaterial.h>
+#include <QColor>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+class QMorphPhongMaterialPrivate;
+
+class QT3DEXTRASSHARED_EXPORT QMorphPhongMaterial : public Qt3DRender::QMaterial
+{
+ Q_OBJECT
+ Q_PROPERTY(QColor ambient READ ambient WRITE setAmbient NOTIFY ambientChanged)
+ Q_PROPERTY(QColor diffuse READ diffuse WRITE setDiffuse NOTIFY diffuseChanged)
+ Q_PROPERTY(QColor specular READ specular WRITE setSpecular NOTIFY specularChanged)
+ Q_PROPERTY(float shininess READ shininess WRITE setShininess NOTIFY shininessChanged)
+ Q_PROPERTY(float interpolator READ interpolator WRITE setInterpolator NOTIFY interpolatorChanged)
+
+public:
+ explicit QMorphPhongMaterial(Qt3DCore::QNode *parent = nullptr);
+ ~QMorphPhongMaterial();
+
+ QColor ambient() const;
+ QColor diffuse() const;
+ QColor specular() const;
+ float shininess() const;
+ float interpolator() const;
+
+public Q_SLOTS:
+ void setAmbient(const QColor &ambient);
+ void setDiffuse(const QColor &diffuse);
+ void setSpecular(const QColor &specular);
+ void setShininess(float shininess);
+ void setInterpolator(float interpolator);
+
+Q_SIGNALS:
+ void ambientChanged(const QColor &ambient);
+ void diffuseChanged(const QColor &diffuse);
+ void specularChanged(const QColor &specular);
+ void shininessChanged(float shininess);
+ void interpolatorChanged(float interpolator);
+
+private:
+ Q_DECLARE_PRIVATE(QMorphPhongMaterial)
+};
+
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QMORPHPHONGMATERIAL_H
+
diff --git a/src/extras/defaults/qmorphphongmaterial_p.h b/src/extras/defaults/qmorphphongmaterial_p.h
new file mode 100644
index 000000000..25bff9042
--- /dev/null
+++ b/src/extras/defaults/qmorphphongmaterial_p.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QMORPHPHONGMATERIAL_P_H
+#define QT3DEXTRAS_QMORPHPHONGMATERIAL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DRender/private/qmaterial_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+class QFilterKey;
+class QEffect;
+class QTechnique;
+class QParameter;
+class QShaderProgram;
+class QRenderPass;
+
+} // namespace Qt3DRender
+
+namespace Qt3DExtras {
+
+class QMorphPhongMaterial;
+
+class QMorphPhongMaterialPrivate : public Qt3DRender::QMaterialPrivate
+{
+public:
+ QMorphPhongMaterialPrivate();
+
+ void init();
+
+ void handleAmbientChanged(const QVariant &var);
+ void handleDiffuseChanged(const QVariant &var);
+ void handleSpecularChanged(const QVariant &var);
+ void handleShininessChanged(const QVariant &var);
+ void handleInterpolatorChanged(const QVariant &var);
+
+ Qt3DRender::QEffect *m_phongEffect;
+ Qt3DRender::QParameter *m_ambientParameter;
+ Qt3DRender::QParameter *m_diffuseParameter;
+ Qt3DRender::QParameter *m_specularParameter;
+ Qt3DRender::QParameter *m_shininessParameter;
+ Qt3DRender::QParameter *m_interpolatorParameter;
+ Qt3DRender::QTechnique *m_phongGL3Technique;
+ Qt3DRender::QTechnique *m_phongGL2Technique;
+ Qt3DRender::QTechnique *m_phongES2Technique;
+ Qt3DRender::QRenderPass *m_phongGL3RenderPass;
+ Qt3DRender::QRenderPass *m_phongGL2RenderPass;
+ Qt3DRender::QRenderPass *m_phongES2RenderPass;
+ Qt3DRender::QShaderProgram *m_phongGL3Shader;
+ Qt3DRender::QShaderProgram *m_phongGL2ES2Shader;
+ Qt3DRender::QFilterKey *m_filterKey;
+
+ Q_DECLARE_PUBLIC(QMorphPhongMaterial)
+};
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QPHONGMATERIAL_P_H
+
+
diff --git a/src/extras/extras.pro b/src/extras/extras.pro
index d723554ca..d11172005 100644
--- a/src/extras/extras.pro
+++ b/src/extras/extras.pro
@@ -9,6 +9,7 @@ DEFINES += QT_NO_FOREACH
load(qt_module)
+include (animations/animations.pri)
include (geometries/geometries.pri)
include (3dtext/3dtext.pri)
include (defaults/defaults.pri)
diff --git a/src/extras/extras.qrc b/src/extras/extras.qrc
index e7b1c1d9a..121bfd029 100644
--- a/src/extras/extras.qrc
+++ b/src/extras/extras.qrc
@@ -39,5 +39,7 @@
<file>shaders/gl3/unlittexture.frag</file>
<file>shaders/es2/unlittexture.frag</file>
<file>shaders/es2/unlittexture.vert</file>
+ <file>shaders/gl3/morphphong.vert</file>
+ <file>shaders/es2/morphphong.vert</file>
</qresource>
</RCC>
diff --git a/src/extras/shaders/es2/morphphong.vert b/src/extras/shaders/es2/morphphong.vert
new file mode 100644
index 000000000..d091e87c0
--- /dev/null
+++ b/src/extras/shaders/es2/morphphong.vert
@@ -0,0 +1,32 @@
+attribute vec3 vertexPosition;
+attribute vec3 vertexNormal;
+attribute vec3 vertexPositionTarget;
+attribute vec3 vertexNormalTarget;
+
+varying vec3 worldPosition;
+varying vec3 worldNormal;
+
+uniform mat4 modelMatrix;
+uniform mat3 modelNormalMatrix;
+uniform mat4 modelViewProjection;
+uniform float interpolator;
+
+void main()
+{
+ vec3 morphPos;
+ vec3 morphNormal;
+ if (interpolator > 0.0) {
+ // normalized
+ morphPos = mix(vertexPosition, vertexPositionTarget, interpolator);
+ morphNormal = normalize(mix(vertexNormal, vertexNormalTarget, interpolator));
+ } else {
+ // relative
+ morphPos = vertexPosition + vertexPositionTarget * abs(interpolator);
+ morphNormal = normalize(vertexNormal + vertexNormalTarget * abs(interpolator));
+ }
+
+ worldNormal = normalize( modelNormalMatrix * morphPos );
+ worldPosition = vec3( modelMatrix * vec4( morphPos, 1.0 ) );
+
+ gl_Position = modelViewProjection * vec4( morphPos, 1.0 );
+}
diff --git a/src/extras/shaders/gl3/morphphong.vert b/src/extras/shaders/gl3/morphphong.vert
new file mode 100644
index 000000000..c74fbdcff
--- /dev/null
+++ b/src/extras/shaders/gl3/morphphong.vert
@@ -0,0 +1,34 @@
+#version 150 core
+
+in vec3 vertexPosition;
+in vec3 vertexNormal;
+in vec3 vertexPositionTarget;
+in vec3 vertexNormalTarget;
+
+out vec3 worldPosition;
+out vec3 worldNormal;
+
+uniform mat4 modelMatrix;
+uniform mat3 modelNormalMatrix;
+uniform mat4 modelViewProjection;
+uniform float interpolator;
+
+void main()
+{
+ vec3 morphPos;
+ vec3 morphNormal;
+ if (interpolator > 0.0) {
+ // normalized
+ morphPos = mix(vertexPosition, vertexPositionTarget, interpolator);
+ morphNormal = normalize(mix(vertexNormal, vertexNormalTarget, interpolator));
+ } else {
+ // relative
+ morphPos = vertexPosition + vertexPositionTarget * abs(interpolator);
+ morphNormal = normalize(vertexNormal + vertexNormalTarget * abs(interpolator));
+ }
+
+ worldNormal = normalize( modelNormalMatrix * morphPos );
+ worldPosition = vec3( modelMatrix * vec4( morphPos, 1.0 ) );
+
+ gl_Position = modelViewProjection * vec4( morphPos, 1.0 );
+}
diff --git a/src/plugins/sceneparsers/assimp/assimpimporter.cpp b/src/plugins/sceneparsers/assimp/assimpimporter.cpp
index dba13a291..66c219fe9 100644
--- a/src/plugins/sceneparsers/assimp/assimpimporter.cpp
+++ b/src/plugins/sceneparsers/assimp/assimpimporter.cpp
@@ -51,9 +51,12 @@
#include <Qt3DRender/qattribute.h>
#include <Qt3DRender/qtexture.h>
#include <Qt3DRender/qtextureimagedatagenerator.h>
+#include <Qt3DExtras/qmorphphongmaterial.h>
#include <Qt3DExtras/qdiffusemapmaterial.h>
#include <Qt3DExtras/qdiffusespecularmapmaterial.h>
#include <Qt3DExtras/qphongmaterial.h>
+#include <Qt3DExtras/qkeyframeanimation.h>
+#include <Qt3DExtras/qmorphinganimation.h>
#include <QFileInfo>
#include <QColor>
#include <qmath.h>
@@ -413,7 +416,15 @@ Qt3DCore::QEntity *AssimpImporter::scene(const QString &id)
// Builds the Qt3D scene using the Assimp aiScene
// and the various dicts filled previously by parse
- return node(rootNode);
+ Qt3DCore::QEntity *n = node(rootNode);
+ if (m_scene->m_animations.size() > 0) {
+ qWarning() << "No target found for " << m_scene->m_animations.size() << " animations!";
+
+ for (Qt3DExtras::QKeyframeAnimation *anim : m_scene->m_animations)
+ delete anim;
+ m_scene->m_animations.clear();
+ }
+ return n;
}
/*!
@@ -429,6 +440,17 @@ Qt3DCore::QEntity *AssimpImporter::node(const QString &id)
return node(n);
}
+template <typename T>
+void findAnimationsForNode(QVector<T *> &animations, QVector<T *> &result, const QString &name)
+{
+ for (T *anim : animations) {
+ if (anim->targetName() == name) {
+ result.push_back(anim);
+ animations.removeAll(anim);
+ }
+ }
+}
+
/*!
* Returns a Node from an Assimp aiNode \a node.
*/
@@ -442,13 +464,54 @@ Qt3DCore::QEntity *AssimpImporter::node(aiNode *node)
// Add Meshes to the node
for (uint i = 0; i < node->mNumMeshes; i++) {
uint meshIdx = node->mMeshes[i];
+ QMaterial *material = nullptr;
QGeometryRenderer *mesh = m_scene->m_meshes[meshIdx];
// mesh material
uint materialIndex = m_scene->m_aiScene->mMeshes[meshIdx]->mMaterialIndex;
+
if (m_scene->m_materials.contains(materialIndex))
- entityNode->addComponent(m_scene->m_materials[materialIndex]);
- // mesh
- entityNode->addComponent(mesh);
+ material = m_scene->m_materials[materialIndex];
+
+ QList<Qt3DExtras::QMorphingAnimation *> morphingAnimations
+ = mesh->findChildren<Qt3DExtras::QMorphingAnimation *>();
+ if (morphingAnimations.size() > 0) {
+ material = new Qt3DExtras::QMorphPhongMaterial(entityNode);
+
+ QVector<Qt3DExtras::QMorphingAnimation *> animations;
+ findAnimationsForNode<Qt3DExtras::QMorphingAnimation>(m_scene->m_morphAnimations,
+ animations,
+ aiStringToQString(node->mName));
+ const auto morphTargetList = morphingAnimations.at(0)->morphTargetList();
+ for (Qt3DExtras::QMorphingAnimation *anim : animations) {
+ anim->setParent(entityNode);
+ anim->setTarget(mesh);
+ anim->setMorphTargets(morphTargetList);
+ }
+
+ for (int j = 0; j < animations.size(); ++j) {
+ QObject::connect(animations[j], &Qt3DExtras::QMorphingAnimation::interpolatorChanged,
+ (Qt3DExtras::QMorphPhongMaterial *)material,
+ &Qt3DExtras::QMorphPhongMaterial::setInterpolator);
+ }
+ morphingAnimations[0]->deleteLater();
+ }
+
+ if (node->mNumMeshes == 1) {
+ if (material)
+ entityNode->addComponent(material);
+ // mesh
+ entityNode->addComponent(mesh);
+ } else {
+ QEntity *childEntity = QAbstractNodeFactory::createNode<Qt3DCore::QEntity>("QEntity");
+ if (material)
+ childEntity->addComponent(material);
+ childEntity->addComponent(mesh);
+ childEntity->setParent(entityNode);
+
+ Qt3DCore::QTransform *transform
+ = QAbstractNodeFactory::createNode<Qt3DCore::QTransform>("QTransform");
+ childEntity->addComponent(transform);
+ }
}
// Add Children to Node
@@ -467,6 +530,16 @@ Qt3DCore::QEntity *AssimpImporter::node(aiNode *node)
transform->setMatrix(qTransformMatrix);
entityNode->addComponent(transform);
+ QVector<Qt3DExtras::QKeyframeAnimation *> animations;
+ findAnimationsForNode<Qt3DExtras::QKeyframeAnimation>(m_scene->m_animations,
+ animations,
+ aiStringToQString(node->mName));
+
+ for (Qt3DExtras::QKeyframeAnimation *anim : animations) {
+ anim->setTarget(transform);
+ anim->setParent(entityNode);
+ }
+
// Add Camera
if (m_scene->m_cameras.contains(node))
m_scene->m_cameras[node]->setParent(entityNode);
@@ -497,7 +570,6 @@ void AssimpImporter::readSceneFile(const QString &path)
m_scene->m_aiScene = m_scene->m_importer->ReadFile(path.toUtf8().constData(),
aiProcess_SortByPType|
aiProcess_Triangulate|
- aiProcess_JoinIdenticalVertices|
aiProcess_GenSmoothNormals|
aiProcess_FlipUVs);
if (m_scene->m_aiScene == nullptr) {
@@ -713,8 +785,136 @@ void AssimpImporter::loadMesh(uint meshIndex)
m_scene->m_meshes[meshIndex] = geometryRenderer;
+ if (mesh->mNumAnimMeshes > 0) {
+
+ aiAnimMesh *animesh = mesh->mAnimMeshes[0];
+
+ if (animesh->mNumVertices != mesh->mNumVertices)
+ return;
+
+ Qt3DExtras::QMorphingAnimation *morphingAnimation
+ = new Qt3DExtras::QMorphingAnimation(geometryRenderer);
+ QVector<QString> names;
+ QVector<Qt3DExtras::QMorphTarget *> targets;
+ uint voff = 0;
+ uint noff = 0;
+ uint tanoff = 0;
+ uint texoff = 0;
+ uint coloff = 0;
+ uint offset = 0;
+ if (animesh->mVertices) {
+ names.push_back(VERTICES_ATTRIBUTE_NAME);
+ offset += 3;
+ }
+ if (animesh->mNormals) {
+ names.push_back(NORMAL_ATTRIBUTE_NAME);
+ noff = offset;
+ offset += 3;
+ }
+ if (animesh->mTangents) {
+ names.push_back(TANGENT_ATTRIBUTE_NAME);
+ tanoff = offset;
+ offset += 3;
+ }
+ if (animesh->mTextureCoords[0]) {
+ names.push_back(TEXTCOORD_ATTRIBUTE_NAME);
+ texoff = offset;
+ offset += 2;
+ }
+ if (animesh->mColors[0]) {
+ names.push_back(COLOR_ATTRIBUTE_NAME);
+ coloff = offset;
+ }
+
+ ushort clumpSize = (animesh->mVertices ? 3 : 0)
+ + (animesh->mNormals ? 3 : 0)
+ + (animesh->mTangents ? 3 : 0)
+ + (animesh->mColors[0] ? 4 : 0)
+ + (animesh->mTextureCoords[0] ? 2 : 0);
+
+
+ for (uint i = 0; i < mesh->mNumAnimMeshes; i++) {
+ aiAnimMesh *animesh = mesh->mAnimMeshes[i];
+ Qt3DExtras::QMorphTarget *target = new Qt3DExtras::QMorphTarget(geometryRenderer);
+ targets.push_back(target);
+ QVector<QAttribute *> attributes;
+ QByteArray targetBufferArray;
+ targetBufferArray.resize(clumpSize * mesh->mNumVertices * sizeof(float));
+ float *dst = reinterpret_cast<float *>(targetBufferArray.data());
+
+ for (uint j = 0; j < mesh->mNumVertices; j++) {
+ if (animesh->mVertices) {
+ *dst++ = animesh->mVertices[j].x;
+ *dst++ = animesh->mVertices[j].y;
+ *dst++ = animesh->mVertices[j].z;
+ }
+ if (animesh->mNormals) {
+ *dst++ = animesh->mNormals[j].x;
+ *dst++ = animesh->mNormals[j].y;
+ *dst++ = animesh->mNormals[j].z;
+ }
+ if (animesh->mTangents) {
+ *dst++ = animesh->mTangents[j].x;
+ *dst++ = animesh->mTangents[j].y;
+ *dst++ = animesh->mTangents[j].z;
+ }
+ if (animesh->mTextureCoords[0]) {
+ *dst++ = animesh->mTextureCoords[0][j].x;
+ *dst++ = animesh->mTextureCoords[0][j].y;
+ }
+ if (animesh->mColors[0]) {
+ *dst++ = animesh->mColors[0][j].r;
+ *dst++ = animesh->mColors[0][j].g;
+ *dst++ = animesh->mColors[0][j].b;
+ *dst++ = animesh->mColors[0][j].a;
+ }
+ }
+
+ Qt3DRender::QBuffer *targetBuffer
+ = QAbstractNodeFactory::createNode<Qt3DRender::QBuffer>("QBuffer");
+ targetBuffer->setData(targetBufferArray);
+ targetBuffer->setParent(meshGeometry);
+
+ if (animesh->mVertices) {
+ attributes.push_back(createAttribute(targetBuffer, VERTICES_ATTRIBUTE_NAME,
+ QAttribute::Float, 3,
+ animesh->mNumVertices, voff * sizeof(float),
+ clumpSize * sizeof(float), meshGeometry));
+ }
+ if (animesh->mNormals) {
+ attributes.push_back(createAttribute(targetBuffer, NORMAL_ATTRIBUTE_NAME,
+ QAttribute::Float, 3,
+ animesh->mNumVertices, noff * sizeof(float),
+ clumpSize * sizeof(float), meshGeometry));
+ }
+ if (animesh->mTangents) {
+ attributes.push_back(createAttribute(targetBuffer, TANGENT_ATTRIBUTE_NAME,
+ QAttribute::Float, 3,
+ animesh->mNumVertices, tanoff * sizeof(float),
+ clumpSize * sizeof(float), meshGeometry));
+ }
+ if (animesh->mTextureCoords[0]) {
+ attributes.push_back(createAttribute(targetBuffer, TEXTCOORD_ATTRIBUTE_NAME,
+ QAttribute::Float, 2,
+ animesh->mNumVertices, texoff * sizeof(float),
+ clumpSize * sizeof(float), meshGeometry));
+ }
+ if (animesh->mColors[0]) {
+ attributes.push_back(createAttribute(targetBuffer, COLOR_ATTRIBUTE_NAME,
+ QAttribute::Float, 4,
+ animesh->mNumVertices, coloff * sizeof(float),
+ clumpSize * sizeof(float), meshGeometry));
+ }
+ target->setAttributes(attributes);
+ }
+ morphingAnimation->setMorphTargets(targets);
+ morphingAnimation->setTargetName(aiStringToQString(mesh->mName));
+ morphingAnimation->setTarget(geometryRenderer);
+ }
+
qCDebug(AssimpImporterLog) << Q_FUNC_INFO << " Mesh " << aiStringToQString(mesh->mName)
- << " Vertices " << mesh->mNumVertices << " Faces " << mesh->mNumFaces << " Indices " << indices;
+ << " Vertices " << mesh->mNumVertices << " Faces "
+ << mesh->mNumFaces << " Indices " << indices;
}
/*!
@@ -790,10 +990,145 @@ void AssimpImporter::loadCamera(uint cameraIndex)
m_scene->m_cameras[cameraNode] = camera;
}
+int findTimeIndex(const QVector<float> &times, float time) {
+ for (int i = 0; i < times.size(); i++) {
+ if (qFuzzyCompare(times[i], time))
+ return i;
+ }
+ return -1;
+}
+
+void insertAtTime(QVector<float> &positions, QVector<Qt3DCore::QTransform *> &tranforms,
+ Qt3DCore::QTransform *t, float time)
+{
+ if (positions.size() == 0) {
+ positions.push_back(time);
+ tranforms.push_back(t);
+ } else if (time < positions.first()) {
+ positions.push_front(time);
+ tranforms.push_front(t);
+ } else if (time > positions.last()) {
+ positions.push_back(time);
+ tranforms.push_back(t);
+ } else {
+ qWarning() << "Insert new key in the middle of the keyframe not implemented.";
+ }
+}
+
// OPTIONAL
void AssimpImporter::loadAnimation(uint animationIndex)
{
- Q_UNUSED(animationIndex);
+ aiAnimation *assimpAnim = m_scene->m_aiScene->mAnimations[animationIndex];
+ qCDebug(AssimpImporterLog) << "load Animation: "<< aiStringToQString(assimpAnim->mName);
+ double tickScale = 1.0;
+ if (!qFuzzyIsNull(assimpAnim->mTicksPerSecond))
+ tickScale = 1.0 / assimpAnim->mTicksPerSecond;
+
+ /* keyframe animations */
+ for (uint i = 0; i < assimpAnim->mNumChannels; ++i) {
+ aiNodeAnim *nodeAnim = assimpAnim->mChannels[i];
+ aiNode *targetNode = m_scene->m_aiScene->mRootNode->FindNode(nodeAnim->mNodeName);
+
+ Qt3DExtras::QKeyframeAnimation *kfa = new Qt3DExtras::QKeyframeAnimation();
+ QVector<float> positions;
+ QVector<Qt3DCore::QTransform*> transforms;
+ if ((nodeAnim->mNumPositionKeys > 1)
+ || !(nodeAnim->mNumPositionKeys == 1 && nodeAnim->mPositionKeys[0].mValue.x == 0
+ && nodeAnim->mPositionKeys[0].mValue.y == 0
+ && nodeAnim->mPositionKeys[0].mValue.z == 0)) {
+ for (uint j = 0; j < nodeAnim->mNumPositionKeys; j++) {
+ positions.push_back(nodeAnim->mPositionKeys[j].mTime);
+ Qt3DCore::QTransform *t = new Qt3DCore::QTransform();
+ t->setTranslation(QVector3D(nodeAnim->mPositionKeys[j].mValue.x,
+ nodeAnim->mPositionKeys[j].mValue.y,
+ nodeAnim->mPositionKeys[j].mValue.z));
+ transforms.push_back(t);
+ }
+ }
+ if ((nodeAnim->mNumRotationKeys > 1) ||
+ !(nodeAnim->mNumRotationKeys == 1 && nodeAnim->mRotationKeys[0].mValue.x == 0
+ && nodeAnim->mRotationKeys[0].mValue.y == 0
+ && nodeAnim->mRotationKeys[0].mValue.z == 0
+ && nodeAnim->mRotationKeys[0].mValue.w == 1)) {
+ for (uint j = 0; j < nodeAnim->mNumRotationKeys; j++) {
+ int index = findTimeIndex(positions, nodeAnim->mRotationKeys[j].mTime);
+ if (index >= 0) {
+ Qt3DCore::QTransform *t = transforms[index];
+ t->setRotation(QQuaternion(nodeAnim->mRotationKeys[j].mValue.w,
+ nodeAnim->mRotationKeys[j].mValue.x,
+ nodeAnim->mRotationKeys[j].mValue.y,
+ nodeAnim->mRotationKeys[j].mValue.z));
+ } else {
+ Qt3DCore::QTransform *t = new Qt3DCore::QTransform();
+ t->setRotation(QQuaternion(nodeAnim->mRotationKeys[j].mValue.w,
+ nodeAnim->mRotationKeys[j].mValue.x,
+ nodeAnim->mRotationKeys[j].mValue.y,
+ nodeAnim->mRotationKeys[j].mValue.z));
+ insertAtTime(positions, transforms, t, nodeAnim->mRotationKeys[j].mTime);
+ }
+ }
+ }
+ if ((nodeAnim->mNumScalingKeys > 1)
+ || !(nodeAnim->mNumScalingKeys == 1 && nodeAnim->mScalingKeys[0].mValue.x == 1
+ && nodeAnim->mScalingKeys[0].mValue.y == 1
+ && nodeAnim->mScalingKeys[0].mValue.z == 1)) {
+ for (uint j = 0; j < nodeAnim->mNumScalingKeys; j++) {
+ int index = findTimeIndex(positions, nodeAnim->mScalingKeys[j].mTime);
+ if (index >= 0) {
+ Qt3DCore::QTransform *t = transforms[index];
+ t->setScale3D(QVector3D(nodeAnim->mScalingKeys[j].mValue.x,
+ nodeAnim->mScalingKeys[j].mValue.y,
+ nodeAnim->mScalingKeys[j].mValue.z));
+ } else {
+ Qt3DCore::QTransform *t = new Qt3DCore::QTransform();
+ t->setScale3D(QVector3D(nodeAnim->mScalingKeys[j].mValue.x,
+ nodeAnim->mScalingKeys[j].mValue.y,
+ nodeAnim->mScalingKeys[j].mValue.z));
+ insertAtTime(positions, transforms, t, nodeAnim->mScalingKeys[j].mTime);
+ }
+ }
+ }
+ for (int j = 0; j < positions.size(); ++j)
+ positions[j] = positions[j] * tickScale;
+ kfa->setFramePositions(positions);
+ kfa->setKeyframes(transforms);
+ kfa->setAnimationName(QString(assimpAnim->mName.C_Str()));
+ kfa->setTargetName(QString(targetNode->mName.C_Str()));
+ m_scene->m_animations.push_back(kfa);
+ }
+ /* mesh morph animations */
+ for (uint i = 0; i < assimpAnim->mNumMorphMeshChannels; ++i) {
+ aiMeshMorphAnim *morphAnim = assimpAnim->mMorphMeshChannels[i];
+ aiNode *targetNode = m_scene->m_aiScene->mRootNode->FindNode(morphAnim->mName);
+ aiMesh *mesh = m_scene->m_aiScene->mMeshes[targetNode->mMeshes[0]];
+
+ Qt3DExtras::QMorphingAnimation *morphingAnimation = new Qt3DExtras::QMorphingAnimation;
+ QVector<float> positions;
+ positions.resize(morphAnim->mNumKeys);
+ // set so that weights array is allocated to correct size in morphingAnimation
+ morphingAnimation->setTargetPositions(positions);
+ for (unsigned int j = 0; j < morphAnim->mNumKeys; ++j) {
+ aiMeshMorphKey &key = morphAnim->mKeys[j];
+ positions[j] = key.mTime * tickScale;
+
+ QVector<float> weights;
+ weights.resize(key.mNumValuesAndWeights);
+ for (int k = 0; k < weights.size(); k++) {
+ const unsigned int value = key.mValues[k];
+ if (value < key.mNumValuesAndWeights)
+ weights[value] = key.mWeights[k];
+ }
+ morphingAnimation->setWeights(j, weights);
+ }
+
+ morphingAnimation->setTargetPositions(positions);
+ morphingAnimation->setAnimationName(QString(assimpAnim->mName.C_Str()));
+ morphingAnimation->setTargetName(QString(targetNode->mName.C_Str()));
+ morphingAnimation->setMethod((mesh->mMethod == aiMorphingMethod_MORPH_NORMALIZED)
+ ? Qt3DExtras::QMorphingAnimation::Normalized
+ : Qt3DExtras::QMorphingAnimation::Relative);
+ m_scene->m_morphAnimations.push_back(morphingAnimation);
+ }
}
/*!
diff --git a/src/plugins/sceneparsers/assimp/assimpimporter.h b/src/plugins/sceneparsers/assimp/assimpimporter.h
index fb60713b8..0d2c0c9e5 100644
--- a/src/plugins/sceneparsers/assimp/assimpimporter.h
+++ b/src/plugins/sceneparsers/assimp/assimpimporter.h
@@ -61,6 +61,7 @@
#include <QMap>
#include <QDir>
+#include <QVector>
#include <QLoggingCategory>
QT_BEGIN_NAMESPACE
@@ -71,6 +72,11 @@ namespace Qt3DCore {
class QCamera;
}
+namespace Qt3DExtras {
+class QKeyframeAnimation;
+class QMorphingAnimation;
+}
+
namespace Qt3DRender {
class QMaterial;
@@ -138,6 +144,8 @@ private:
QMap<QString, QAbstractTexture *> m_materialTextures;
QMap<aiNode*, Qt3DCore::QEntity*> m_cameras;
QHash<aiTextureType, QString> m_textureToParameterName;
+ QVector<Qt3DExtras::QKeyframeAnimation *> m_animations;
+ QVector<Qt3DExtras::QMorphingAnimation *> m_morphAnimations;
// QMap<aiNode*, Light*> m_lights;
};
diff --git a/src/quick3d/imports/extras/defaults.qrc b/src/quick3d/imports/extras/defaults.qrc
new file mode 100644
index 000000000..7b07aafab
--- /dev/null
+++ b/src/quick3d/imports/extras/defaults.qrc
@@ -0,0 +1,21 @@
+<RCC>
+<qresource prefix="/qt-project.org/imports/Qt3D/Extras/">
+<file alias="defaults/qml/DefaultEffect.qml">defaults/qml/DefaultEffect.qml</file>
+<file alias="defaults/qml/DefaultAlphaEffect.qml">defaults/qml/DefaultAlphaEffect.qml</file>
+<file alias="defaults/qml/PhongMaterial.qml">defaults/qml/PhongMaterial.qml</file>
+<file alias="defaults/qml/DiffuseMapMaterial.qml">defaults/qml/DiffuseMapMaterial.qml</file>
+<file alias="defaults/qml/DiffuseSpecularMapMaterial.qml">defaults/qml/DiffuseSpecularMapMaterial.qml</file>
+<file alias="defaults/qml/NormalDiffuseMapMaterial.qml">defaults/qml/NormalDiffuseMapMaterial.qml</file>
+<file alias="defaults/qml/NormalDiffuseMapAlphaMaterial.qml">defaults/qml/NormalDiffuseMapAlphaMaterial.qml</file>
+<file alias="defaults/qml/NormalDiffuseSpecularMapMaterial.qml">defaults/qml/NormalDiffuseSpecularMapMaterial.qml</file>
+<file alias="defaults/qml/ForwardRenderer.qml">defaults/qml/ForwardRenderer.qml</file>
+<file alias="defaults/qml/PerVertexColorMaterial.qml">defaults/qml/PerVertexColorMaterial.qml</file>
+<file alias="defaults/qml/SkyboxEntity.qml">defaults/qml/SkyboxEntity.qml</file>
+<file alias="defaults/qml/GoochMaterial.qml">defaults/qml/GoochMaterial.qml</file>
+<file alias="defaults/qml/PhongAlphaMaterial.qml">defaults/qml/PhongAlphaMaterial.qml</file>
+<file alias="defaults/qml/TextureMaterial.qml">defaults/qml/TextureMaterial.qml</file>
+<file alias="defaults/qml/OrbitCameraController.qml">defaults/qml/OrbitCameraController.qml</file>
+<file alias="defaults/qml/FirstPersonCameraController.qml">defaults/qml/FirstPersonCameraController.qml</file>
+<file alias="defaults/qml/NormalDiffuseMapAlphaEffect.qml">defaults/qml/NormalDiffuseMapAlphaEffect.qml</file>
+</qresource>
+</RCC>
diff --git a/src/quick3d/imports/extras/importsextras.pro b/src/quick3d/imports/extras/importsextras.pro
index acc993fa7..6a70238f4 100644
--- a/src/quick3d/imports/extras/importsextras.pro
+++ b/src/quick3d/imports/extras/importsextras.pro
@@ -3,7 +3,7 @@ TARGET = quick3dextrasplugin
TARGETPATH = Qt3D/Extras
IMPORT_VERSION = 2.0
-QT += core-private qml qml-private quick quick-private 3dcore 3dcore-private 3dquick 3dquick-private 3dextras 3dlogic
+QT += core-private qml qml-private quick quick-private 3dcore 3dcore-private 3dquick 3dquick-private 3dextras 3dlogic 3dquickextras 3dquickextras-private
# Qt3D is free of Q_FOREACH - make sure it stays that way:
DEFINES += QT_NO_FOREACH
diff --git a/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp b/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp
index 7d695ea5b..55af6432b 100644
--- a/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp
+++ b/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp
@@ -52,6 +52,19 @@
#include <Qt3DExtras/qcylindergeometry.h>
#include <Qt3DExtras/qtext3dgeometry.h>
#include <Qt3DExtras/qtext3dmesh.h>
+#include <Qt3DExtras/qkeyframeanimation.h>
+#include <Qt3DExtras/qanimationcontroller.h>
+#include <Qt3DExtras/qabstractanimation.h>
+#include <Qt3DExtras/qmorphinganimation.h>
+#include <Qt3DExtras/qanimationgroup.h>
+#include <Qt3DExtras/qmorphtarget.h>
+
+#include <Qt3DQuickExtras/private/quick3dkeyframeanimation_p.h>
+#include <Qt3DQuickExtras/private/quick3danimationgroup_p.h>
+#include <Qt3DQuickExtras/private/quick3danimationcontroller_p.h>
+#include <Qt3DQuickExtras/private/quick3dmorphtarget_p.h>
+#include <Qt3DQuickExtras/private/quick3dmorphinganimation_p.h>
+
#include <QtQml/qqml.h>
QT_BEGIN_NAMESPACE
@@ -106,6 +119,13 @@ void Qt3DQuick3DExtrasPlugin::registerTypes(const char *uri)
qmlRegisterType<Qt3DExtras::QText3DGeometry>(uri, 2, 2, "Text3DGeometry");
qmlRegisterType<Qt3DExtras::QText3DMesh>(uri, 2, 2, "Text3DMesh");
+ qmlRegisterUncreatableType<Qt3DExtras::QAbstractAnimation>(uri, 2, 0, "AbstractAnimation", QStringLiteral("AbstractAnimation is abstract"));
+ qmlRegisterExtendedType<Qt3DExtras::QKeyframeAnimation, Qt3DExtras::Quick::QQuick3DKeyframeAnimation>(uri, 2, 2, "KeyframeAnimation");
+ qmlRegisterExtendedType<Qt3DExtras::QAnimationGroup, Qt3DExtras::Quick::QQuick3DAnimationGroup>(uri, 2, 2, "AnimationGroup");
+ qmlRegisterExtendedType<Qt3DExtras::QAnimationController, Qt3DExtras::Quick::QQuick3DAnimationController>(uri, 2, 2, "AnimationController");
+ qmlRegisterExtendedType<Qt3DExtras::QMorphingAnimation, Qt3DExtras::Quick::QQuick3DMorphingAnimation>(uri, 2, 2, "MorphingAnimation");
+ qmlRegisterExtendedType<Qt3DExtras::QMorphTarget, Qt3DExtras::Quick::QQuick3DMorphTarget>(uri, 2, 2, "MorphTarget");
+
// Register types provided as QML files compiled into the plugin
for (int i = 0; i < int(sizeof(qmldir) / sizeof(qmldir[0])); i++) {
auto path = QLatin1String("qrc:/qt-project.org/imports/Qt3D/Extras/defaults/qml/");
diff --git a/src/quick3d/quick3dextras/items/items.pri b/src/quick3d/quick3dextras/items/items.pri
new file mode 100644
index 000000000..cdb1e1245
--- /dev/null
+++ b/src/quick3d/quick3dextras/items/items.pri
@@ -0,0 +1,15 @@
+HEADERS += \
+ $$PWD/quick3danimationcontroller_p.h \
+ $$PWD/quick3danimationgroup_p.h \
+ $$PWD/quick3dkeyframeanimation_p.h \
+ $$PWD/quick3dmorphinganimation_p.h \
+ $$PWD/quick3dmorphtarget_p.h
+
+SOURCES += \
+ $$PWD/quick3danimationcontroller.cpp \
+ $$PWD/quick3danimationgroup.cpp \
+ $$PWD/quick3dkeyframeanimation.cpp \
+ $$PWD/quick3dmorphinganimation.cpp \
+ $$PWD/quick3dmorphtarget.cpp
+
+INCLUDEPATH += $$PWD
diff --git a/src/quick3d/quick3dextras/items/quick3danimationcontroller.cpp b/src/quick3d/quick3dextras/items/quick3danimationcontroller.cpp
new file mode 100644
index 000000000..4aceb0d55
--- /dev/null
+++ b/src/quick3d/quick3dextras/items/quick3danimationcontroller.cpp
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "quick3danimationcontroller_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+namespace Quick {
+
+QQuick3DAnimationController::QQuick3DAnimationController(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QQmlListProperty<QAnimationGroup> QQuick3DAnimationController::animationGroups()
+{
+ return QQmlListProperty<QAnimationGroup>(this, 0,
+ &QQuick3DAnimationController::appendAnimationGroup,
+ &QQuick3DAnimationController::animationGroupCount,
+ &QQuick3DAnimationController::animationGroupAt,
+ &QQuick3DAnimationController::clearAnimationGroups);
+}
+
+
+void QQuick3DAnimationController::appendAnimationGroup(QQmlListProperty<QAnimationGroup> *list, QAnimationGroup *bar)
+{
+ QQuick3DAnimationController *controller = qobject_cast<QQuick3DAnimationController *>(list->object);
+ if (controller)
+ controller->parentAnimationController()->addAnimationGroup(bar);
+}
+
+int QQuick3DAnimationController::animationGroupCount(QQmlListProperty<QAnimationGroup> *list)
+{
+ QQuick3DAnimationController *controller = qobject_cast<QQuick3DAnimationController *>(list->object);
+ if (controller)
+ return controller->parentAnimationController()->animationGroupList().count();
+ return 0;
+}
+
+QAnimationGroup *QQuick3DAnimationController::animationGroupAt(QQmlListProperty<QAnimationGroup> *list, int index)
+{
+ QQuick3DAnimationController *controller = qobject_cast<QQuick3DAnimationController *>(list->object);
+ if (controller)
+ return qobject_cast<QAnimationGroup *>(controller->parentAnimationController()->getGroup(index));
+ return nullptr;
+}
+
+void QQuick3DAnimationController::clearAnimationGroups(QQmlListProperty<QAnimationGroup> *list)
+{
+ QQuick3DAnimationController *controller = qobject_cast<QQuick3DAnimationController *>(list->object);
+ if (controller) {
+ QVector<QAnimationGroup *> emptyList;
+ controller->parentAnimationController()->setAnimationGroups(emptyList);
+ }
+}
+
+
+} // namespace Quick
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/quick3dextras/items/quick3danimationcontroller_p.h b/src/quick3d/quick3dextras/items/quick3danimationcontroller_p.h
new file mode 100644
index 000000000..82ad29e2c
--- /dev/null
+++ b/src/quick3d/quick3dextras/items/quick3danimationcontroller_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QUICK_QUICK3DANIMATIONCONTROLLER_P_H
+#define QT3DEXTRAS_QUICK_QUICK3DANIMATIONCONTROLLER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DQuickExtras/qt3dquickextras_global.h>
+#include <QQmlListProperty>
+#include <Qt3DExtras/QAnimationController>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+namespace Quick {
+
+class QT3DQUICKEXTRASSHARED_EXPORT QQuick3DAnimationController : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<Qt3DExtras::QAnimationGroup> animationGroups READ animationGroups)
+
+public:
+
+ explicit QQuick3DAnimationController(QObject *parent = nullptr);
+
+ inline Qt3DExtras::QAnimationController *parentAnimationController() const
+ {
+ return qobject_cast<Qt3DExtras::QAnimationController *>(parent());
+ }
+
+ QQmlListProperty<Qt3DExtras::QAnimationGroup> animationGroups();
+
+private:
+
+ static void appendAnimationGroup(QQmlListProperty<Qt3DExtras::QAnimationGroup> *list, Qt3DExtras::QAnimationGroup *bar);
+ static QAnimationGroup *animationGroupAt(QQmlListProperty<Qt3DExtras::QAnimationGroup> *list, int index);
+ static int animationGroupCount(QQmlListProperty<Qt3DExtras::QAnimationGroup> *list);
+ static void clearAnimationGroups(QQmlListProperty<Qt3DExtras::QAnimationGroup> *list);
+};
+
+} // namespace Quick
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_RENDER_QUICK_QUICK3DEFFECT_P_H
diff --git a/src/quick3d/quick3dextras/items/quick3danimationgroup.cpp b/src/quick3d/quick3dextras/items/quick3danimationgroup.cpp
new file mode 100644
index 000000000..3e3813227
--- /dev/null
+++ b/src/quick3d/quick3dextras/items/quick3danimationgroup.cpp
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "quick3danimationgroup_p.h"
+
+#include <Qt3DExtras/qabstractanimation.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+namespace Quick {
+
+QQuick3DAnimationGroup::QQuick3DAnimationGroup(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QQmlListProperty<Qt3DExtras::QAbstractAnimation> QQuick3DAnimationGroup::animations()
+{
+ return QQmlListProperty<Qt3DExtras::QAbstractAnimation>(this, 0,
+ &QQuick3DAnimationGroup::appendAnimation,
+ &QQuick3DAnimationGroup::animationCount,
+ &QQuick3DAnimationGroup::animationAt,
+ &QQuick3DAnimationGroup::clearAnimation);
+}
+
+
+void QQuick3DAnimationGroup::appendAnimation(QQmlListProperty<Qt3DExtras::QAbstractAnimation> *list,
+ Qt3DExtras::QAbstractAnimation *animation)
+{
+ QQuick3DAnimationGroup *animationGroup = qobject_cast<QQuick3DAnimationGroup *>(list->object);
+ if (animationGroup)
+ animationGroup->parentAnimationGroup()->addAnimation(animation);
+}
+
+int QQuick3DAnimationGroup::animationCount(QQmlListProperty<Qt3DExtras::QAbstractAnimation> *list)
+{
+ QQuick3DAnimationGroup *animationGroup = qobject_cast<QQuick3DAnimationGroup *>(list->object);
+ if (animationGroup)
+ return animationGroup->parentAnimationGroup()->animationList().count();
+ return 0;
+}
+
+Qt3DExtras::QAbstractAnimation *QQuick3DAnimationGroup::animationAt(QQmlListProperty<Qt3DExtras::QAbstractAnimation> *list, int index)
+{
+ QQuick3DAnimationGroup *animationGroup = qobject_cast<QQuick3DAnimationGroup *>(list->object);
+ if (animationGroup) {
+ return qobject_cast<Qt3DExtras::QAbstractAnimation *>(
+ animationGroup->parentAnimationGroup()->animationList().at(index));
+ }
+ return nullptr;
+}
+
+void QQuick3DAnimationGroup::clearAnimation(QQmlListProperty<Qt3DExtras::QAbstractAnimation> *list)
+{
+ QQuick3DAnimationGroup *animationGroup = qobject_cast<QQuick3DAnimationGroup *>(list->object);
+ if (animationGroup) {
+ QVector<Qt3DExtras::QAbstractAnimation *> emptyList;
+ animationGroup->parentAnimationGroup()->setAnimations(emptyList);
+ }
+}
+
+} // namespace Quick
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/quick3dextras/items/quick3danimationgroup_p.h b/src/quick3d/quick3dextras/items/quick3danimationgroup_p.h
new file mode 100644
index 000000000..c7140c946
--- /dev/null
+++ b/src/quick3d/quick3dextras/items/quick3danimationgroup_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QUICK_QUICK3DANIMATIONGROUP_P_H
+#define QT3DEXTRAS_QUICK_QUICK3DANIMATIONGROUP_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQml/qqmllist.h>
+#include <Qt3DExtras/qabstractanimation.h>
+#include <Qt3DExtras/qanimationgroup.h>
+
+#include <Qt3DQuickExtras/qt3dquickextras_global.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+namespace Quick {
+
+class QT3DQUICKEXTRASSHARED_EXPORT QQuick3DAnimationGroup : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<Qt3DExtras::QAbstractAnimation> animations READ animations)
+
+public:
+
+ explicit QQuick3DAnimationGroup(QObject *parent = nullptr);
+
+ inline Qt3DExtras::QAnimationGroup *parentAnimationGroup() const
+ {
+ return qobject_cast<Qt3DExtras::QAnimationGroup *>(parent());
+ }
+
+ QQmlListProperty<Qt3DExtras::QAbstractAnimation> animations();
+
+private:
+
+ static void appendAnimation(QQmlListProperty<Qt3DExtras::QAbstractAnimation> *list, Qt3DExtras::QAbstractAnimation *animation);
+ static Qt3DExtras::QAbstractAnimation *animationAt(QQmlListProperty<Qt3DExtras::QAbstractAnimation> *list, int index);
+ static int animationCount(QQmlListProperty<Qt3DExtras::QAbstractAnimation> *list);
+ static void clearAnimation(QQmlListProperty<Qt3DExtras::QAbstractAnimation> *list);
+};
+
+} // namespace Quick
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_RENDER_QUICK_QUICK3DEFFECT_P_H
diff --git a/src/quick3d/quick3dextras/items/quick3dkeyframeanimation.cpp b/src/quick3d/quick3dextras/items/quick3dkeyframeanimation.cpp
new file mode 100644
index 000000000..cfd9ca7d2
--- /dev/null
+++ b/src/quick3d/quick3dextras/items/quick3dkeyframeanimation.cpp
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "quick3dkeyframeanimation_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+namespace Quick {
+
+QQuick3DKeyframeAnimation::QQuick3DKeyframeAnimation(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QQmlListProperty<Qt3DCore::QTransform> QQuick3DKeyframeAnimation::keyframes()
+{
+ return QQmlListProperty<Qt3DCore::QTransform>(this, 0,
+ &QQuick3DKeyframeAnimation::appendKeyframe,
+ &QQuick3DKeyframeAnimation::keyframeCount,
+ &QQuick3DKeyframeAnimation::keyframeAt,
+ &QQuick3DKeyframeAnimation::clearKeyframes);
+}
+
+void QQuick3DKeyframeAnimation::appendKeyframe(QQmlListProperty<Qt3DCore::QTransform> *list,
+ Qt3DCore::QTransform *transform)
+{
+ QQuick3DKeyframeAnimation *keyframeAnimation
+ = qobject_cast<QQuick3DKeyframeAnimation *>(list->object);
+ if (keyframeAnimation)
+ keyframeAnimation->parentKeyframeAnimation()->addKeyframe(transform);
+}
+
+int QQuick3DKeyframeAnimation::keyframeCount(QQmlListProperty<Qt3DCore::QTransform> *list)
+{
+ QQuick3DKeyframeAnimation *keyframeAnimation
+ = qobject_cast<QQuick3DKeyframeAnimation *>(list->object);
+ if (keyframeAnimation)
+ return keyframeAnimation->parentKeyframeAnimation()->keyframeList().count();
+ return 0;
+}
+
+Qt3DCore::QTransform *QQuick3DKeyframeAnimation::keyframeAt(QQmlListProperty<Qt3DCore::QTransform> *list,
+ int index)
+{
+ QQuick3DKeyframeAnimation *keyframeAnimation
+ = qobject_cast<QQuick3DKeyframeAnimation *>(list->object);
+ if (keyframeAnimation) {
+ return qobject_cast<Qt3DCore::QTransform *>(
+ keyframeAnimation->parentKeyframeAnimation()->keyframeList().at(index));
+ }
+ return nullptr;
+}
+
+void QQuick3DKeyframeAnimation::clearKeyframes(QQmlListProperty<Qt3DCore::QTransform> *list)
+{
+ QQuick3DKeyframeAnimation *keyframeAnimation
+ = qobject_cast<QQuick3DKeyframeAnimation *>(list->object);
+ if (keyframeAnimation) {
+ QVector<Qt3DCore::QTransform *> emptyList;
+ keyframeAnimation->parentKeyframeAnimation()->setKeyframes(emptyList);
+ }
+}
+
+} // namespace Quick
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/quick3dextras/items/quick3dkeyframeanimation_p.h b/src/quick3d/quick3dextras/items/quick3dkeyframeanimation_p.h
new file mode 100644
index 000000000..e8309de9e
--- /dev/null
+++ b/src/quick3d/quick3dextras/items/quick3dkeyframeanimation_p.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QUICK_QUICK3DKEYFRAMEANIMATION_P_H
+#define QT3DEXTRAS_QUICK_QUICK3DKEYFRAMEANIMATION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQml/qqmllist.h>
+
+#include <Qt3DExtras/qkeyframeanimation.h>
+
+#include <Qt3DQuickExtras/qt3dquickextras_global.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+namespace Quick {
+
+class QT3DQUICKEXTRASSHARED_EXPORT QQuick3DKeyframeAnimation : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<Qt3DCore::QTransform> keyframes READ keyframes)
+
+public:
+ QQuick3DKeyframeAnimation(QObject *parent = nullptr);
+
+ inline QKeyframeAnimation *parentKeyframeAnimation() const
+ {
+ return qobject_cast<QKeyframeAnimation *>(parent());
+ }
+
+ QQmlListProperty<Qt3DCore::QTransform> keyframes();
+
+private:
+
+ static void appendKeyframe(QQmlListProperty<Qt3DCore::QTransform> *list,
+ Qt3DCore::QTransform *transform);
+ static Qt3DCore::QTransform *keyframeAt(QQmlListProperty<Qt3DCore::QTransform> *list,
+ int index);
+ static int keyframeCount(QQmlListProperty<Qt3DCore::QTransform> *list);
+ static void clearKeyframes(QQmlListProperty<Qt3DCore::QTransform> *list);
+};
+
+} // namespace Quick
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QUICK_QUICK3DKEYFRAMEANIMATION_P_H
diff --git a/src/quick3d/quick3dextras/items/quick3dmorphinganimation.cpp b/src/quick3d/quick3dextras/items/quick3dmorphinganimation.cpp
new file mode 100644
index 000000000..61636f06d
--- /dev/null
+++ b/src/quick3d/quick3dextras/items/quick3dmorphinganimation.cpp
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "quick3dmorphinganimation_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+namespace Quick {
+
+QQuick3DMorphingAnimation::QQuick3DMorphingAnimation(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QQmlListProperty<Qt3DExtras::QMorphTarget> QQuick3DMorphingAnimation::morphTargets()
+{
+ return QQmlListProperty<Qt3DExtras::QMorphTarget>(this, 0,
+ &QQuick3DMorphingAnimation::appendMorphTarget,
+ &QQuick3DMorphingAnimation::morphTargetCount,
+ &QQuick3DMorphingAnimation::morphTargetAt,
+ &QQuick3DMorphingAnimation::clearMorphTargets);
+}
+
+void QQuick3DMorphingAnimation::appendMorphTarget(QQmlListProperty<Qt3DExtras::QMorphTarget> *list,
+ Qt3DExtras::QMorphTarget *morphTarget)
+{
+ QQuick3DMorphingAnimation *animation = qobject_cast<QQuick3DMorphingAnimation *>(list->object);
+ if (animation)
+ animation->parentMorphingAnimation()->addMorphTarget(morphTarget);
+}
+
+int QQuick3DMorphingAnimation::morphTargetCount(QQmlListProperty<Qt3DExtras::QMorphTarget> *list)
+{
+ QQuick3DMorphingAnimation *animation = qobject_cast<QQuick3DMorphingAnimation *>(list->object);
+ if (animation)
+ return animation->parentMorphingAnimation()->morphTargetList().count();
+ return 0;
+}
+
+Qt3DExtras::QMorphTarget *QQuick3DMorphingAnimation::morphTargetAt(QQmlListProperty<Qt3DExtras::QMorphTarget> *list,
+ int index)
+{
+ QQuick3DMorphingAnimation *animation = qobject_cast<QQuick3DMorphingAnimation *>(list->object);
+ if (animation) {
+ return qobject_cast<Qt3DExtras::QMorphTarget *>(
+ animation->parentMorphingAnimation()->morphTargetList().at(index));
+ }
+ return nullptr;
+}
+
+void QQuick3DMorphingAnimation::clearMorphTargets(QQmlListProperty<Qt3DExtras::QMorphTarget> *list)
+{
+ QQuick3DMorphingAnimation *animation = qobject_cast<QQuick3DMorphingAnimation *>(list->object);
+ if (animation) {
+ QVector<Qt3DExtras::QMorphTarget *> emptyList;
+ animation->parentMorphingAnimation()->setMorphTargets(emptyList);
+ }
+}
+
+} // namespace Quick
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/quick3dextras/items/quick3dmorphinganimation_p.h b/src/quick3d/quick3dextras/items/quick3dmorphinganimation_p.h
new file mode 100644
index 000000000..5f052fd04
--- /dev/null
+++ b/src/quick3d/quick3dextras/items/quick3dmorphinganimation_p.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QUICK_QUICK3DMORPHINGANIMATION_P_H
+#define QT3DEXTRAS_QUICK_QUICK3DMORPHINGANIMATION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQml/qqmllist.h>
+
+#include <Qt3DExtras/qmorphinganimation.h>
+
+#include <Qt3DQuickExtras/qt3dquickextras_global.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+namespace Quick {
+
+class QT3DQUICKEXTRASSHARED_EXPORT QQuick3DMorphingAnimation : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<Qt3DExtras::QMorphTarget> morphTargets READ morphTargets)
+
+public:
+ QQuick3DMorphingAnimation(QObject *parent = nullptr);
+
+ inline QMorphingAnimation *parentMorphingAnimation() const
+ {
+ return qobject_cast<QMorphingAnimation *>(parent());
+ }
+
+ QQmlListProperty<Qt3DExtras::QMorphTarget> morphTargets();
+
+private:
+
+ static void appendMorphTarget(QQmlListProperty<Qt3DExtras::QMorphTarget> *list,
+ Qt3DExtras::QMorphTarget *morphTarget);
+ static Qt3DExtras::QMorphTarget *morphTargetAt(QQmlListProperty<Qt3DExtras::QMorphTarget> *list,
+ int index);
+ static int morphTargetCount(QQmlListProperty<Qt3DExtras::QMorphTarget> *list);
+ static void clearMorphTargets(QQmlListProperty<Qt3DExtras::QMorphTarget> *list);
+};
+
+} // namespace Quick
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QUICK_QUICK3DMORPHINGANIMATION_P_H
diff --git a/src/quick3d/quick3dextras/items/quick3dmorphtarget.cpp b/src/quick3d/quick3dextras/items/quick3dmorphtarget.cpp
new file mode 100644
index 000000000..8c1b9f0c1
--- /dev/null
+++ b/src/quick3d/quick3dextras/items/quick3dmorphtarget.cpp
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "quick3dmorphtarget_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+namespace Quick {
+
+QQuick3DMorphTarget::QQuick3DMorphTarget(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QQmlListProperty<Qt3DRender::QAttribute> QQuick3DMorphTarget::attributes()
+{
+ return QQmlListProperty<Qt3DRender::QAttribute>(this, 0,
+ &QQuick3DMorphTarget::appendAttribute,
+ &QQuick3DMorphTarget::attributeCount,
+ &QQuick3DMorphTarget::attributeAt,
+ &QQuick3DMorphTarget::clearAttributes);
+}
+
+void QQuick3DMorphTarget::appendAttribute(QQmlListProperty<Qt3DRender::QAttribute> *list, Qt3DRender::QAttribute *bar)
+{
+ QQuick3DMorphTarget *target = qobject_cast<QQuick3DMorphTarget *>(list->object);
+ if (target)
+ target->parentMorphTarget()->addAttribute(bar);
+}
+
+int QQuick3DMorphTarget::attributeCount(QQmlListProperty<Qt3DRender::QAttribute> *list)
+{
+ QQuick3DMorphTarget *target = qobject_cast<QQuick3DMorphTarget *>(list->object);
+ if (target)
+ return target->parentMorphTarget()->attributeList().count();
+ return 0;
+}
+
+Qt3DRender::QAttribute *QQuick3DMorphTarget::attributeAt(QQmlListProperty<Qt3DRender::QAttribute> *list, int index)
+{
+ QQuick3DMorphTarget *target = qobject_cast<QQuick3DMorphTarget *>(list->object);
+ if (target)
+ return qobject_cast<Qt3DRender::QAttribute *>(target->parentMorphTarget()->attributeList().at(index));
+ return nullptr;
+}
+
+void QQuick3DMorphTarget::clearAttributes(QQmlListProperty<Qt3DRender::QAttribute> *list)
+{
+ QQuick3DMorphTarget *target = qobject_cast<QQuick3DMorphTarget *>(list->object);
+ if (target) {
+ QVector<Qt3DRender::QAttribute *> emptyList;
+ target->parentMorphTarget()->setAttributes(emptyList);
+ }
+}
+
+} // namespace Quick
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
diff --git a/src/quick3d/quick3dextras/items/quick3dmorphtarget_p.h b/src/quick3d/quick3dextras/items/quick3dmorphtarget_p.h
new file mode 100644
index 000000000..e5c664370
--- /dev/null
+++ b/src/quick3d/quick3dextras/items/quick3dmorphtarget_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DEXTRAS_QUICK_QUICK3DMORPHTARGET_P_H
+#define QT3DEXTRAS_QUICK_QUICK3DMORPHTARGET_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DQuickExtras/qt3dquickextras_global.h>
+#include <QQmlListProperty>
+#include <Qt3DExtras/QMorphTarget>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+namespace Quick {
+
+class QT3DQUICKEXTRASSHARED_EXPORT QQuick3DMorphTarget : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<Qt3DRender::QAttribute> attributes READ attributes)
+
+public:
+ QQuick3DMorphTarget(QObject *parent = nullptr);
+
+ inline QMorphTarget *parentMorphTarget() const { return qobject_cast<QMorphTarget *>(parent()); }
+
+ QQmlListProperty<Qt3DRender::QAttribute> attributes();
+
+private:
+
+ static void appendAttribute(QQmlListProperty<Qt3DRender::QAttribute> *list, Qt3DRender::QAttribute *bar);
+ static Qt3DRender::QAttribute *attributeAt(QQmlListProperty<Qt3DRender::QAttribute> *list, int index);
+ static int attributeCount(QQmlListProperty<Qt3DRender::QAttribute> *list);
+ static void clearAttributes(QQmlListProperty<Qt3DRender::QAttribute> *list);
+};
+
+} // namespace Quick
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QUICK_QUICK3DMORPHTARGET_P_H
diff --git a/src/quick3d/quick3dextras/quick3dextras.pro b/src/quick3d/quick3dextras/quick3dextras.pro
index 8965e9f5d..4f103765c 100644
--- a/src/quick3d/quick3dextras/quick3dextras.pro
+++ b/src/quick3d/quick3dextras/quick3dextras.pro
@@ -1,7 +1,7 @@
TARGET = Qt3DQuickExtras
MODULE = 3dquickextras
-QT += core core-private qml qml-private 3dcore 3dinput 3dquick 3drender 3drender-private 3dlogic
+QT += core core-private qml qml-private 3dcore 3dinput 3dquick 3drender 3drender-private 3dlogic 3dextras
CONFIG -= precompile_header
# Qt3D is free of Q_FOREACH - make sure it stays that way:
@@ -23,4 +23,6 @@ HEADERS += \
# otherwise mingw headers do not declare common functions like ::strcasecmp
win32-g++*:QMAKE_CXXFLAGS_CXX11 = -std=gnu++0x
+include(./items/items.pri)
+
load(qt_module)
diff --git a/tests/manual/anim-viewer/anim-viewer.pro b/tests/manual/anim-viewer/anim-viewer.pro
new file mode 100644
index 000000000..d9c3d8fb2
--- /dev/null
+++ b/tests/manual/anim-viewer/anim-viewer.pro
@@ -0,0 +1,13 @@
+!include( ../manual.pri ) {
+ error( "Couldn't find the manual.pri file!" )
+}
+
+TEMPLATE = app
+
+QT += qml quick 3dcore 3drender 3dinput 3dquick 3dextras 3dquickextras
+
+CONFIG += c++11
+
+SOURCES += main.cpp
+
+RESOURCES += qml.qrc
diff --git a/tests/manual/anim-viewer/assets/blendshapeanimation.dae b/tests/manual/anim-viewer/assets/blendshapeanimation.dae
new file mode 100644
index 000000000..01edd1484
--- /dev/null
+++ b/tests/manual/anim-viewer/assets/blendshapeanimation.dae
@@ -0,0 +1,1281 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset><contributor><author></author><authoring_tool>FBX COLLADA exporter</authoring_tool><comments></comments></contributor><created>2016-09-30T11:11:20Z</created><keywords></keywords><modified>2016-09-30T11:11:20Z</modified><revision></revision><subject></subject><title></title><unit meter="0.010000" name="centimeter"></unit><up_axis>Y_UP</up_axis></asset>
+ <library_materials>
+ <material id="lambert2" name="lambert2">
+ <instance_effect url="#lambert2-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="lambert2-fx" name="lambert2">
+ <profile_COMMON>
+ <technique sid="standard">
+ <lambert>
+ <emission>
+ <color sid="emission">0.000000 0.000000 0.000000 1.000000</color>
+ </emission>
+ <ambient>
+ <color sid="ambient">0.000000 0.000000 0.000000 1.000000</color>
+ </ambient>
+ <diffuse>
+ <color sid="diffuse">0.400000 0.400000 0.400000 1.000000</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color sid="transparent">0.000000 0.000000 0.000000 1.000000</color>
+ </transparent>
+ <transparency>
+ <float sid="transparency">1.000000</float>
+ </transparency>
+ </lambert>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="pPlane16-lib" name="pPlane16Mesh">
+ <mesh>
+ <source id="pPlane16-POSITION">
+ <float_array id="pPlane16-POSITION-array" count="258">
+-0.312507 -0.000000 2.637385
+0.312506 -0.000000 2.637385
+-0.312507 -0.000000 2.359762
+0.312506 -0.000000 2.359762
+-0.312507 -0.000000 2.082143
+0.312506 -0.000000 2.082143
+-0.312507 -0.000000 1.804527
+0.312506 -0.000000 1.804527
+-0.312507 -0.000000 1.526906
+0.312506 -0.000000 1.526906
+-0.312506 0.000000 -1.526906
+0.312507 0.000000 -1.526906
+-0.312506 0.000000 -1.804527
+0.312507 0.000000 -1.804527
+-0.312506 0.000000 -2.082142
+0.312507 0.000000 -2.082142
+-0.312506 0.000000 -2.359762
+0.312507 0.000000 -2.359762
+-0.312506 0.000000 -2.637385
+0.312507 0.000000 -2.637385
+0.312507 0.000000 -2.498573
+-0.312506 0.000000 -2.498573
+0.312507 0.000000 -2.220952
+-0.312506 0.000000 -2.220952
+0.312507 0.000000 -1.943334
+-0.312506 0.000000 -1.943334
+0.312507 0.000000 -1.665716
+-0.312506 0.000000 -1.665716
+0.312506 -0.000000 1.665716
+-0.312507 -0.000000 1.665716
+0.312506 -0.000000 1.943335
+-0.312507 -0.000000 1.943335
+0.312506 -0.000000 2.220952
+-0.312507 -0.000000 2.220952
+0.312506 -0.000000 2.498574
+-0.312507 -0.000000 2.498574
+0.312506 -0.000000 1.380497
+-0.312507 -0.000000 1.380497
+0.312506 -0.000000 1.236356
+-0.312507 -0.000000 1.236356
+0.312506 -0.000000 1.096244
+-0.312507 -0.000000 1.096244
+0.312506 -0.000000 0.961413
+-0.312507 -0.000000 0.961413
+0.312506 -0.000000 0.832655
+-0.312507 -0.000000 0.832655
+0.312507 -0.000000 0.710343
+-0.312507 -0.000000 0.710343
+0.312507 -0.000000 0.594481
+-0.312507 -0.000000 0.594481
+0.312507 -0.000000 0.484749
+-0.312507 -0.000000 0.484749
+0.312507 -0.000000 0.380550
+-0.312507 -0.000000 0.380550
+0.312507 -0.000000 0.281054
+-0.312507 -0.000000 0.281054
+0.312507 -0.000000 0.185247
+-0.312507 -0.000000 0.185247
+0.312507 -0.000000 0.091978
+-0.312507 -0.000000 0.091978
+0.312507 -0.000000 -0.000000
+-0.312507 -0.000000 -0.000000
+0.312507 0.000000 -0.091978
+-0.312507 0.000000 -0.091978
+0.312507 0.000000 -0.185248
+-0.312507 0.000000 -0.185248
+0.312507 0.000000 -0.281054
+-0.312507 0.000000 -0.281054
+0.312507 0.000000 -0.380550
+-0.312507 0.000000 -0.380550
+0.312507 0.000000 -0.484749
+-0.312507 0.000000 -0.484749
+0.312507 0.000000 -0.594481
+-0.312507 0.000000 -0.594481
+0.312507 0.000000 -0.710343
+-0.312507 0.000000 -0.710343
+0.312507 0.000000 -0.832655
+-0.312506 0.000000 -0.832655
+0.312507 0.000000 -0.961414
+-0.312506 0.000000 -0.961414
+0.312507 0.000000 -1.096244
+-0.312506 0.000000 -1.096244
+0.312507 0.000000 -1.236356
+-0.312506 0.000000 -1.236356
+0.312507 0.000000 -1.380498
+-0.312506 0.000000 -1.380498
+</float_array>
+ <technique_common>
+ <accessor source="#pPlane16-POSITION-array" count="86" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="pPlane16-Normal0">
+ <float_array id="pPlane16-Normal0-array" count="258">
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+</float_array>
+ <technique_common>
+ <accessor source="#pPlane16-Normal0-array" count="86" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="pPlane16-UV0">
+ <float_array id="pPlane16-UV0-array" count="172">
+0.000000 0.000000
+1.000000 0.000000
+0.000000 0.052632
+1.000000 0.052632
+0.000000 0.105263
+1.000000 0.105263
+0.000000 0.157895
+1.000000 0.157895
+0.000000 0.210526
+1.000000 0.210526
+0.000000 0.789474
+1.000000 0.789474
+0.000000 0.842105
+1.000000 0.842105
+0.000000 0.894737
+1.000000 0.894737
+0.000000 0.947368
+1.000000 0.947368
+0.000000 1.000000
+1.000000 1.000000
+1.000000 0.973684
+0.000000 0.973684
+1.000000 0.921053
+0.000000 0.921053
+1.000000 0.868421
+0.000000 0.868421
+1.000000 0.815789
+0.000000 0.815789
+1.000000 0.184211
+0.000000 0.184211
+1.000000 0.131579
+0.000000 0.131579
+1.000000 0.078947
+0.000000 0.078947
+1.000000 0.026316
+0.000000 0.026316
+1.000000 0.232794
+0.000000 0.232794
+1.000000 0.255061
+0.000000 0.255061
+1.000000 0.277328
+0.000000 0.277328
+1.000000 0.299595
+0.000000 0.299595
+1.000000 0.321862
+0.000000 0.321862
+1.000000 0.344130
+0.000000 0.344130
+1.000000 0.366397
+0.000000 0.366397
+1.000000 0.388664
+0.000000 0.388664
+1.000000 0.410931
+0.000000 0.410931
+1.000000 0.433198
+0.000000 0.433198
+1.000000 0.455466
+0.000000 0.455466
+1.000000 0.477733
+0.000000 0.477733
+1.000000 0.500000
+0.000000 0.500000
+1.000000 0.522267
+0.000000 0.522267
+1.000000 0.544534
+0.000000 0.544534
+1.000000 0.566802
+0.000000 0.566802
+1.000000 0.589069
+0.000000 0.589069
+1.000000 0.611336
+0.000000 0.611336
+1.000000 0.633603
+0.000000 0.633603
+1.000000 0.655870
+0.000000 0.655870
+1.000000 0.678138
+0.000000 0.678138
+1.000000 0.700405
+0.000000 0.700405
+1.000000 0.722672
+0.000000 0.722672
+1.000000 0.744939
+0.000000 0.744939
+1.000000 0.767206
+0.000000 0.767206
+</float_array>
+ <technique_common>
+ <accessor source="#pPlane16-UV0-array" count="86" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="pPlane16-VERTEX">
+ <input semantic="POSITION" source="#pPlane16-POSITION"/>
+ <input semantic="NORMAL" source="#pPlane16-Normal0"/>
+ </vertices>
+ <triangles count="84" material="lambert2"><input semantic="VERTEX" offset="0" source="#pPlane16-VERTEX"/><input semantic="TEXCOORD" offset="1" set="0" source="#pPlane16-UV0"/><p> 0 0 1 1 34 34 0 0 34 34 35 35 2 2 3 3 32 32 2 2 32 32 33 33 4 4 5 5 30 30 4 4 30 30 31 31 6 6 7 7 28 28 6 6 28 28 29 29 10 10 11 11 26 26 10 10 26 26 27 27 12 12 13 13 24 24 12 12 24 24 25 25 14 14 15 15 22 22 14 14 22 22 23 23 16 16 17 17 20 20 16 16 20 20 21 21 21 21 20 20 19 19 21 21 19 19 18 18 23 23 22 22 17 17 23 23 17 17 16 16 25 25 24 24 15 15 25 25 15 15 14 14 27 27 26 26 13 13 27 27 13 13 12 12 29 29 28 28 9 9 29 29 9 9 8 8 31 31 30 30 7 7 31 31 7 7 6 6 33 33 32 32 5 5 33 33 5 5 4 4 35 35 34 34 3 3 35 35 3 3 2 2 8 8 9 9 36 36 8 8 36 36 37 37 36 36 39 39 37 37 39 39 36 36 38 38 40 40 39 39 38 38 39 39 40 40 41 41 41 41 40 40 42 42 41 41 42 42 43 43 44 44 43 43 42 42 43 43 44 44 45 45 44 44 47 47 45 45 47 47 44 44 46 46 48 48 47 47 46 46 47 47 48 48 49 49 49 49 48 48 50 50 49 49 50 50 51 51 51 51 50 50 52 52 51 51 52 52 53 53 52 52 55 55 53 53 55 55 52 52 54 54 55 55 54 54 56 56 55 55 56 56 57 57 58 58 57 57 56 56 57 57 58 58 59 59 58 58 61 61 59 59 61 61 58 58 60 60 60 60 63 63 61 61 63 63 60 60 62 62 64 64 63 63 62 62 63 63 64 64 65 65 65 65 64 64 66 66 65 65 66 66 67 67 66 66 69 69 67 67 69 69 66 66 68 68 69 69 68 68 70 70 69 69 70 70 71 71 71 71 70 70 72 72 71 71 72 72 73 73 74 74 73 73 72 72 73 73 74 74 75 75 74 74 77 77 75 75 77 77 74 74 76 76 77 77 76 76 78 78 77 77 78 78 79 79 79 79 78 78 80 80 79 79 80 80 81 81 82 82 81 81 80 80 81 81 82 82 83 83 82 82 85 85 83 83 85 85 82 82 84 84 85 85 84 84 11 11 85 85 11 11 10 10</p></triangles>
+ </mesh>
+ </geometry>
+ <geometry id="pPlane13-lib" name="pPlane13Mesh">
+ <mesh>
+ <source id="pPlane13-POSITION">
+ <float_array id="pPlane13-POSITION-array" count="258">
+0.277128 -0.000000 2.637385
+0.902142 -0.000000 2.637385
+0.277128 -0.000000 2.359762
+0.902142 -0.000000 2.359762
+0.277128 -0.000000 2.082143
+0.902142 -0.000000 2.082143
+0.277128 -0.000000 1.804527
+0.902142 -0.000000 1.804527
+0.277128 -0.000000 1.526906
+0.902142 -0.000000 1.526906
+-0.312506 0.000000 -1.526906
+0.312507 0.000000 -1.526906
+-0.312506 0.000000 -1.804527
+0.312507 0.000000 -1.804527
+-0.312506 0.000000 -2.082142
+0.312507 0.000000 -2.082142
+-0.312506 0.000000 -2.359762
+0.312507 0.000000 -2.359762
+-0.312506 0.000000 -2.637385
+0.312507 0.000000 -2.637385
+0.312507 0.000000 -2.498573
+-0.312506 0.000000 -2.498573
+0.312507 0.000000 -2.220952
+-0.312506 0.000000 -2.220952
+0.312507 0.000000 -1.943334
+-0.312506 0.000000 -1.943334
+0.312507 0.000000 -1.665716
+-0.312506 0.000000 -1.665716
+0.902142 -0.000000 1.665716
+0.277128 -0.000000 1.665716
+0.902142 -0.000000 1.943335
+0.277128 -0.000000 1.943335
+0.902142 -0.000000 2.220952
+0.277128 -0.000000 2.220952
+0.902142 -0.000000 2.498574
+0.277128 -0.000000 2.498574
+0.901823 -0.000000 1.377058
+0.276814 -0.000000 1.378653
+0.899714 -0.000000 1.226396
+0.274789 -0.000000 1.236163
+0.894316 -0.000000 1.076746
+0.269829 -0.000000 1.101454
+0.884449 -0.000000 0.929918
+0.261180 -0.000000 0.975449
+0.869252 -0.000000 0.787199
+0.248482 -0.000000 0.858589
+0.848199 -0.000000 0.649525
+0.231682 -0.000000 0.750752
+0.821141 -0.000000 0.517632
+0.210924 -0.000000 0.651211
+0.788364 -0.000000 0.392129
+0.186414 -0.000000 0.558660
+0.750629 -0.000000 0.273497
+0.158320 -0.000000 0.471312
+0.709139 -0.000000 0.162012
+0.126714 -0.000000 0.387082
+0.665419 -0.000000 0.057629
+0.091640 -0.000000 0.303802
+0.621099 -0.000000 -0.040095
+0.053245 -0.000000 0.219401
+0.577691 -0.000000 -0.132024
+0.011945 -0.000000 0.132024
+0.536391 0.000000 -0.219402
+-0.031463 0.000000 0.040094
+0.497996 0.000000 -0.303803
+-0.075782 0.000000 -0.057630
+0.462922 0.000000 -0.387082
+-0.119503 0.000000 -0.162013
+0.431317 0.000000 -0.471312
+-0.160993 0.000000 -0.273498
+0.403221 0.000000 -0.558660
+-0.198729 0.000000 -0.392129
+0.378712 0.000000 -0.651212
+-0.231505 0.000000 -0.517632
+0.357954 0.000000 -0.750752
+-0.258563 0.000000 -0.649525
+0.341155 0.000000 -0.858589
+-0.279616 0.000000 -0.787199
+0.328456 0.000000 -0.975448
+-0.294814 0.000000 -0.929919
+0.319807 0.000000 -1.101453
+-0.304681 0.000000 -1.076746
+0.314846 0.000000 -1.236163
+-0.310079 0.000000 -1.226396
+0.312821 0.000000 -1.378653
+-0.312188 0.000000 -1.377058
+</float_array>
+ <technique_common>
+ <accessor source="#pPlane13-POSITION-array" count="86" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="pPlane13-Normal0">
+ <float_array id="pPlane13-Normal0-array" count="258">
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+</float_array>
+ <technique_common>
+ <accessor source="#pPlane13-Normal0-array" count="86" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="pPlane13-UV0">
+ <float_array id="pPlane13-UV0-array" count="172">
+0.000000 0.000000
+1.000000 0.000000
+0.000000 0.052632
+1.000000 0.052632
+0.000000 0.105263
+1.000000 0.105263
+0.000000 0.157895
+1.000000 0.157895
+0.000000 0.210526
+1.000000 0.210526
+0.000000 0.789474
+1.000000 0.789474
+0.000000 0.842105
+1.000000 0.842105
+0.000000 0.894737
+1.000000 0.894737
+0.000000 0.947368
+1.000000 0.947368
+0.000000 1.000000
+1.000000 1.000000
+1.000000 0.973684
+0.000000 0.973684
+1.000000 0.921053
+0.000000 0.921053
+1.000000 0.868421
+0.000000 0.868421
+1.000000 0.815789
+0.000000 0.815789
+1.000000 0.184211
+0.000000 0.184211
+1.000000 0.131579
+0.000000 0.131579
+1.000000 0.078947
+0.000000 0.078947
+1.000000 0.026316
+0.000000 0.026316
+1.000000 0.232794
+0.000000 0.232794
+1.000000 0.255061
+0.000000 0.255061
+1.000000 0.277328
+0.000000 0.277328
+1.000000 0.299595
+0.000000 0.299595
+1.000000 0.321862
+0.000000 0.321862
+1.000000 0.344130
+0.000000 0.344130
+1.000000 0.366397
+0.000000 0.366397
+1.000000 0.388664
+0.000000 0.388664
+1.000000 0.410931
+0.000000 0.410931
+1.000000 0.433198
+0.000000 0.433198
+1.000000 0.455466
+0.000000 0.455466
+1.000000 0.477733
+0.000000 0.477733
+1.000000 0.500000
+0.000000 0.500000
+1.000000 0.522267
+0.000000 0.522267
+1.000000 0.544534
+0.000000 0.544534
+1.000000 0.566802
+0.000000 0.566802
+1.000000 0.589069
+0.000000 0.589069
+1.000000 0.611336
+0.000000 0.611336
+1.000000 0.633603
+0.000000 0.633603
+1.000000 0.655870
+0.000000 0.655870
+1.000000 0.678138
+0.000000 0.678138
+1.000000 0.700405
+0.000000 0.700405
+1.000000 0.722672
+0.000000 0.722672
+1.000000 0.744939
+0.000000 0.744939
+1.000000 0.767206
+0.000000 0.767206
+</float_array>
+ <technique_common>
+ <accessor source="#pPlane13-UV0-array" count="86" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="pPlane13-VERTEX">
+ <input semantic="POSITION" source="#pPlane13-POSITION"/>
+ <input semantic="NORMAL" source="#pPlane13-Normal0"/>
+ </vertices>
+ <triangles count="84"><input semantic="VERTEX" offset="0" source="#pPlane13-VERTEX"/><input semantic="TEXCOORD" offset="1" set="0" source="#pPlane13-UV0"/><p> 0 0 1 1 34 34 0 0 34 34 35 35 2 2 3 3 32 32 2 2 32 32 33 33 4 4 5 5 30 30 4 4 30 30 31 31 6 6 7 7 28 28 6 6 28 28 29 29 10 10 11 11 26 26 10 10 26 26 27 27 12 12 13 13 24 24 12 12 24 24 25 25 14 14 15 15 22 22 14 14 22 22 23 23 16 16 17 17 20 20 16 16 20 20 21 21 21 21 20 20 19 19 21 21 19 19 18 18 23 23 22 22 17 17 23 23 17 17 16 16 25 25 24 24 15 15 25 25 15 15 14 14 27 27 26 26 13 13 27 27 13 13 12 12 29 29 28 28 9 9 29 29 9 9 8 8 31 31 30 30 7 7 31 31 7 7 6 6 33 33 32 32 5 5 33 33 5 5 4 4 35 35 34 34 3 3 35 35 3 3 2 2 8 8 9 9 36 36 8 8 36 36 37 37 36 36 39 39 37 37 39 39 36 36 38 38 40 40 39 39 38 38 39 39 40 40 41 41 41 41 40 40 42 42 41 41 42 42 43 43 44 44 43 43 42 42 43 43 44 44 45 45 44 44 47 47 45 45 47 47 44 44 46 46 48 48 47 47 46 46 47 47 48 48 49 49 49 49 48 48 50 50 49 49 50 50 51 51 51 51 50 50 52 52 51 51 52 52 53 53 52 52 55 55 53 53 55 55 52 52 54 54 55 55 54 54 56 56 55 55 56 56 57 57 58 58 57 57 56 56 57 57 58 58 59 59 58 58 61 61 59 59 61 61 58 58 60 60 60 60 63 63 61 61 63 63 60 60 62 62 64 64 63 63 62 62 63 63 64 64 65 65 65 65 64 64 66 66 65 65 66 66 67 67 66 66 69 69 67 67 69 69 66 66 68 68 69 69 68 68 70 70 69 69 70 70 71 71 71 71 70 70 72 72 71 71 72 72 73 73 74 74 73 73 72 72 73 73 74 74 75 75 74 74 77 77 75 75 77 77 74 74 76 76 77 77 76 76 78 78 77 77 78 78 79 79 79 79 78 78 80 80 79 79 80 80 81 81 82 82 81 81 80 80 81 81 82 82 83 83 82 82 85 85 83 83 85 85 82 82 84 84 85 85 84 84 11 11 85 85 11 11 10 10</p></triangles>
+ </mesh>
+ </geometry>
+ <geometry id="pPlane17-lib" name="pPlane17Mesh">
+ <mesh>
+ <source id="pPlane17-POSITION">
+ <float_array id="pPlane17-POSITION-array" count="258">
+-0.902142 -0.000000 2.637385
+-0.277128 -0.000000 2.637385
+-0.902142 -0.000000 2.359762
+-0.277128 -0.000000 2.359762
+-0.902142 -0.000000 2.082143
+-0.277128 -0.000000 2.082143
+-0.902142 -0.000000 1.804527
+-0.277128 -0.000000 1.804527
+-0.902142 -0.000000 1.526906
+-0.277128 -0.000000 1.526906
+-0.312506 0.000000 -1.526906
+0.312507 0.000000 -1.526906
+-0.312506 0.000000 -1.804527
+0.312507 0.000000 -1.804527
+-0.312506 0.000000 -2.082142
+0.312507 0.000000 -2.082142
+-0.312506 0.000000 -2.359762
+0.312507 0.000000 -2.359762
+-0.312506 0.000000 -2.637385
+0.312507 0.000000 -2.637385
+0.312507 0.000000 -2.498573
+-0.312506 0.000000 -2.498573
+0.312507 0.000000 -2.220952
+-0.312506 0.000000 -2.220952
+0.312507 0.000000 -1.943334
+-0.312506 0.000000 -1.943334
+0.312507 0.000000 -1.665716
+-0.312506 0.000000 -1.665716
+-0.277128 -0.000000 1.665716
+-0.902142 -0.000000 1.665716
+-0.277128 -0.000000 1.943335
+-0.902142 -0.000000 1.943335
+-0.277128 -0.000000 2.220952
+-0.902142 -0.000000 2.220952
+-0.277128 -0.000000 2.498574
+-0.902142 -0.000000 2.498574
+-0.276814 -0.000000 1.378653
+-0.901823 -0.000000 1.377058
+-0.274789 -0.000000 1.236163
+-0.899714 -0.000000 1.226396
+-0.269829 -0.000000 1.101454
+-0.894316 -0.000000 1.076746
+-0.261179 -0.000000 0.975449
+-0.884449 -0.000000 0.929919
+-0.248481 -0.000000 0.858589
+-0.869251 -0.000000 0.787199
+-0.231682 -0.000000 0.750752
+-0.848198 -0.000000 0.649526
+-0.210923 -0.000000 0.651211
+-0.821140 -0.000000 0.517632
+-0.186414 -0.000000 0.558660
+-0.788364 -0.000000 0.392129
+-0.158320 -0.000000 0.471312
+-0.750629 -0.000000 0.273498
+-0.126714 -0.000000 0.387082
+-0.709139 -0.000000 0.162012
+-0.091639 -0.000000 0.303803
+-0.665418 -0.000000 0.057630
+-0.053244 -0.000000 0.219402
+-0.621099 -0.000000 -0.040095
+-0.011945 -0.000000 0.132024
+-0.577691 -0.000000 -0.132024
+0.031464 0.000000 0.040095
+-0.536390 0.000000 -0.219402
+0.075783 0.000000 -0.057630
+-0.497995 0.000000 -0.303803
+0.119504 0.000000 -0.162012
+-0.462921 0.000000 -0.387082
+0.160994 0.000000 -0.273498
+-0.431315 0.000000 -0.471312
+0.198730 0.000000 -0.392129
+-0.403220 0.000000 -0.558660
+0.231506 0.000000 -0.517633
+-0.378712 0.000000 -0.651212
+0.258564 0.000000 -0.649526
+-0.357953 0.000000 -0.750752
+0.279617 0.000000 -0.787199
+-0.341154 0.000000 -0.858589
+0.294815 0.000000 -0.929919
+-0.328455 0.000000 -0.975449
+0.304681 0.000000 -1.076746
+-0.319806 0.000000 -1.101453
+0.310079 0.000000 -1.226396
+-0.314846 0.000000 -1.236163
+0.312188 0.000000 -1.377058
+-0.312821 0.000000 -1.378653
+</float_array>
+ <technique_common>
+ <accessor source="#pPlane17-POSITION-array" count="86" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="pPlane17-Normal0">
+ <float_array id="pPlane17-Normal0-array" count="258">
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+0.000000 1.000000 0.000000
+-0.000000 1.000000 0.000000
+</float_array>
+ <technique_common>
+ <accessor source="#pPlane17-Normal0-array" count="86" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="pPlane17-UV0">
+ <float_array id="pPlane17-UV0-array" count="172">
+0.000000 0.000000
+1.000000 0.000000
+0.000000 0.052632
+1.000000 0.052632
+0.000000 0.105263
+1.000000 0.105263
+0.000000 0.157895
+1.000000 0.157895
+0.000000 0.210526
+1.000000 0.210526
+0.000000 0.789474
+1.000000 0.789474
+0.000000 0.842105
+1.000000 0.842105
+0.000000 0.894737
+1.000000 0.894737
+0.000000 0.947368
+1.000000 0.947368
+0.000000 1.000000
+1.000000 1.000000
+1.000000 0.973684
+0.000000 0.973684
+1.000000 0.921053
+0.000000 0.921053
+1.000000 0.868421
+0.000000 0.868421
+1.000000 0.815789
+0.000000 0.815789
+1.000000 0.184211
+0.000000 0.184211
+1.000000 0.131579
+0.000000 0.131579
+1.000000 0.078947
+0.000000 0.078947
+1.000000 0.026316
+0.000000 0.026316
+1.000000 0.232794
+0.000000 0.232794
+1.000000 0.255061
+0.000000 0.255061
+1.000000 0.277328
+0.000000 0.277328
+1.000000 0.299595
+0.000000 0.299595
+1.000000 0.321862
+0.000000 0.321862
+1.000000 0.344130
+0.000000 0.344130
+1.000000 0.366397
+0.000000 0.366397
+1.000000 0.388664
+0.000000 0.388664
+1.000000 0.410931
+0.000000 0.410931
+1.000000 0.433198
+0.000000 0.433198
+1.000000 0.455466
+0.000000 0.455466
+1.000000 0.477733
+0.000000 0.477733
+1.000000 0.500000
+0.000000 0.500000
+1.000000 0.522267
+0.000000 0.522267
+1.000000 0.544534
+0.000000 0.544534
+1.000000 0.566802
+0.000000 0.566802
+1.000000 0.589069
+0.000000 0.589069
+1.000000 0.611336
+0.000000 0.611336
+1.000000 0.633603
+0.000000 0.633603
+1.000000 0.655870
+0.000000 0.655870
+1.000000 0.678138
+0.000000 0.678138
+1.000000 0.700405
+0.000000 0.700405
+1.000000 0.722672
+0.000000 0.722672
+1.000000 0.744939
+0.000000 0.744939
+1.000000 0.767206
+0.000000 0.767206
+</float_array>
+ <technique_common>
+ <accessor source="#pPlane17-UV0-array" count="86" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="pPlane17-VERTEX">
+ <input semantic="POSITION" source="#pPlane17-POSITION"/>
+ <input semantic="NORMAL" source="#pPlane17-Normal0"/>
+ </vertices>
+ <triangles count="84"><input semantic="VERTEX" offset="0" source="#pPlane17-VERTEX"/><input semantic="TEXCOORD" offset="1" set="0" source="#pPlane17-UV0"/><p> 0 0 1 1 34 34 0 0 34 34 35 35 2 2 3 3 32 32 2 2 32 32 33 33 4 4 5 5 30 30 4 4 30 30 31 31 6 6 7 7 28 28 6 6 28 28 29 29 10 10 11 11 26 26 10 10 26 26 27 27 12 12 13 13 24 24 12 12 24 24 25 25 14 14 15 15 22 22 14 14 22 22 23 23 16 16 17 17 20 20 16 16 20 20 21 21 21 21 20 20 19 19 21 21 19 19 18 18 23 23 22 22 17 17 23 23 17 17 16 16 25 25 24 24 15 15 25 25 15 15 14 14 27 27 26 26 13 13 27 27 13 13 12 12 29 29 28 28 9 9 29 29 9 9 8 8 31 31 30 30 7 7 31 31 7 7 6 6 33 33 32 32 5 5 33 33 5 5 4 4 35 35 34 34 3 3 35 35 3 3 2 2 8 8 9 9 36 36 8 8 36 36 37 37 36 36 39 39 37 37 39 39 36 36 38 38 40 40 39 39 38 38 39 39 40 40 41 41 41 41 40 40 42 42 41 41 42 42 43 43 44 44 43 43 42 42 43 43 44 44 45 45 44 44 47 47 45 45 47 47 44 44 46 46 48 48 47 47 46 46 47 47 48 48 49 49 49 49 48 48 50 50 49 49 50 50 51 51 51 51 50 50 52 52 51 51 52 52 53 53 52 52 55 55 53 53 55 55 52 52 54 54 55 55 54 54 56 56 55 55 56 56 57 57 58 58 57 57 56 56 57 57 58 58 59 59 58 58 61 61 59 59 61 61 58 58 60 60 60 60 63 63 61 61 63 63 60 60 62 62 64 64 63 63 62 62 63 63 64 64 65 65 65 65 64 64 66 66 65 65 66 66 67 67 66 66 69 69 67 67 69 69 66 66 68 68 69 69 68 68 70 70 69 69 70 70 71 71 71 71 70 70 72 72 71 71 72 72 73 73 74 74 73 73 72 72 73 73 74 74 75 75 74 74 77 77 75 75 77 77 74 74 76 76 77 77 76 76 78 78 77 77 78 78 79 79 79 79 78 78 80 80 79 79 80 80 81 81 82 82 81 81 80 80 81 81 82 82 83 83 82 82 85 85 83 83 85 85 82 82 84 84 85 85 84 84 11 11 85 85 11 11 10 10</p></triangles>
+ </mesh>
+ </geometry>
+ </library_geometries>
+ <library_controllers>
+ <controller id="pPlane16-lib-morph">
+ <morph source="#pPlane16-lib" method="NORMALIZED">
+ <source id="pPlane16-lib-morph-targets">
+ <Name_array id="pPlane16-lib-morph-targets-array" count="2">
+ pPlane13-lib pPlane17-lib</Name_array>
+ <technique_common>
+ <accessor source="#pPlane16-lib-morph-targets-array" count="2">
+ <param type="name"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="pPlane16-lib-morph-weights">
+ <float_array id="pPlane16-lib-morph-weights-array" count="2">
+
+0.000000 0.000824</float_array>
+ <technique_common>
+ <accessor source="#pPlane16-lib-morph-weights-array" count="2">
+ <param name="WEIGHT" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <targets>
+ <input semantic="MORPH_TARGET" source="#pPlane16-lib-morph-targets"/>
+ <input semantic="MORPH_WEIGHT" source="#pPlane16-lib-morph-weights"/>
+ </targets>
+ </morph>
+ </controller>
+ </library_controllers>
+ <library_animations>
+ <animation id="pPlane16-anim" name="pPlane16"><animation><source id="pPlane16-Matrix-animation-input"><float_array id="pPlane16-Matrix-animation-input-array" count="241">
+
+0.000000 0.041667 0.083333 0.125000 0.166667 0.208333 0.250000 0.291667 0.333333 0.375000 0.416667 0.458333 0.500000 0.541667 0.583333 0.625000
+0.666667 0.708333 0.750000 0.791667 0.833333 0.875000 0.916667 0.958333 1.000000 1.041667 1.083333 1.125000 1.166667 1.208333 1.250000 1.291667
+1.333333 1.375000 1.416667 1.458333 1.500000 1.541667 1.583333 1.625000 1.666667 1.708333 1.750000 1.791667 1.833333 1.875000 1.916667 1.958333
+2.000000 2.041667 2.083333 2.125000 2.166667 2.208333 2.250000 2.291667 2.333333 2.375000 2.416667 2.458333 2.500000 2.541667 2.583333 2.625000
+2.666667 2.708333 2.750000 2.791667 2.833333 2.875000 2.916667 2.958333 3.000000 3.041667 3.083333 3.125000 3.166667 3.208333 3.250000 3.291667
+3.333333 3.375000 3.416667 3.458333 3.500000 3.541667 3.583333 3.625000 3.666667 3.708333 3.750000 3.791667 3.833333 3.875000 3.916667 3.958333
+4.000000 4.041667 4.083333 4.125000 4.166667 4.208333 4.250000 4.291667 4.333333 4.375000 4.416667 4.458333 4.500000 4.541667 4.583333 4.625000
+4.666667 4.708333 4.750000 4.791667 4.833333 4.875000 4.916667 4.958333 5.000000 5.041667 5.083333 5.125000 5.166667 5.208333 5.250000 5.291667
+5.333333 5.375000 5.416667 5.458333 5.500000 5.541667 5.583333 5.625000 5.666667 5.708333 5.750000 5.791667 5.833333 5.875000 5.916667 5.958333
+6.000000 6.041667 6.083333 6.125000 6.166667 6.208333 6.250000 6.291667 6.333333 6.375000 6.416667 6.458333 6.500000 6.541667 6.583333 6.625000
+6.666667 6.708333 6.750000 6.791667 6.833333 6.875000 6.916667 6.958333 7.000000 7.041667 7.083333 7.125000 7.166667 7.208333 7.250000 7.291667
+7.333333 7.375000 7.416667 7.458333 7.500000 7.541667 7.583333 7.625000 7.666667 7.708333 7.750000 7.791667 7.833333 7.875000 7.916667 7.958333
+8.000000 8.041667 8.083333 8.125000 8.166667 8.208333 8.250000 8.291667 8.333333 8.375000 8.416667 8.458333 8.500000 8.541667 8.583333 8.625000
+8.666667 8.708333 8.750000 8.791667 8.833333 8.875000 8.916667 8.958333 9.000000 9.041667 9.083333 9.125000 9.166667 9.208333 9.250000 9.291667
+9.333333 9.375000 9.416667 9.458333 9.500000 9.541667 9.583333 9.625000 9.666667 9.708333 9.750000 9.791667 9.833333 9.875000 9.916667 9.958333
+10.000000</float_array><technique_common><accessor source="#pPlane16-Matrix-animation-input-array" count="241"><param name="TIME" type="float"/></accessor></technique_common></source><source id="pPlane16-Matrix-animation-output-transform"><float_array id="pPlane16-Matrix-animation-output-transform-array" count="3856">
+
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.288479 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 1.140794 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 2.537553 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 4.459312 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 6.886627 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 9.800054 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 13.180146 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 17.007462 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 21.262554 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 25.925980 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 30.978294 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 36.400055 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 42.171814 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 48.274124 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 54.687553 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 61.392647 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 68.369957 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 75.600052 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 83.063484 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 90.740799 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 98.612556 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 106.659309 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 114.861633 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 123.200050 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 131.655136 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 140.207443 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 148.837540 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 157.525970 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 166.253296 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 175.000046 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 183.746811 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 192.474121 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 201.162552 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 209.792633 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 218.344955 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 226.800049 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 235.138458 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 243.340790 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 251.387543 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 259.259338 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 266.936646 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 274.400055 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 281.630157 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 288.607483 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 295.312561 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 301.726013 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 307.828278 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 313.600067 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 319.021820 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 324.074127 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 328.737549 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 332.992645 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 336.819977 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 340.200073 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 343.113495 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 345.540802 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 347.462555 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 348.859314 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 349.711639 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 350.000061 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 349.711639 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 348.859314 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 347.462555 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 345.540802 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 343.113495 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 340.200073 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 336.819977 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 332.992645 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 328.737549 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 324.074127 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 319.021820 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 313.600067 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 307.828278 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 301.726013 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 295.312561 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 288.607483 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 281.630157 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 274.400055 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 266.936646 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 259.259338 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 251.387543 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 243.340790 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 235.138458 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 226.800049 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 218.344955 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 209.792633 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 201.162552 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 192.474121 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 183.746796 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 175.000046 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 166.253296 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 157.525970 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 148.837540 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 140.207458 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 131.655136 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 123.200050 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 114.861633 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 106.659317 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 98.612556 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 90.740791 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 83.063492 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 75.600052 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 68.369949 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 61.392647 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 54.687553 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 48.274128 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 42.171814 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 36.400055 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 30.978291 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 25.925980 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 21.262554 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 17.007458 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 13.180144 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 9.800054 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 6.886628 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 4.459314 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 2.537553 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 1.140794 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.288479 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000
+593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000</float_array><technique_common><accessor source="#pPlane16-Matrix-animation-output-transform-array" count="241" stride="16"><param type="float4x4"/></accessor></technique_common></source><source id="pPlane16-Interpolations"><Name_array id="pPlane16-Interpolations-array" count="241">
+ LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR
+LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR
+LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR
+LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR
+LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR
+LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR
+LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR
+LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR
+LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR
+LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR
+LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR
+LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR
+LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR
+LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR
+LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR
+LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR
+LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR
+LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR
+LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR
+LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR
+LINEAR LINEAR</Name_array><technique_common><accessor source="#pPlane16-Interpolations-array" count="241"><param type="name"/></accessor></technique_common></source><sampler id="pPlane16-Matrix-animation-transform"><input semantic="INPUT" source="#pPlane16-Matrix-animation-input"/><input semantic="OUTPUT" source="#pPlane16-Matrix-animation-output-transform"/><input semantic="INTERPOLATION" source="#pPlane16-Interpolations"/></sampler><channel source="#pPlane16-Matrix-animation-transform" target="pPlane16/matrix"/></animation><animation><source id="pPlane16-visibility-animation-input"><float_array id="pPlane16-visibility-animation-input-array" count="5">
+
+0.000000 2.500000 5.000000 7.500000 10.000000</float_array><technique_common><accessor source="#pPlane16-visibility-animation-input-array" count="5"><param name="TIME" type="float"/></accessor></technique_common></source><source id="pPlane16-visibility-animation-output"><float_array id="pPlane16-visibility-animation-output-array" count="5">
+
+1.000000 1.000000 1.000000 1.000000 1.000000</float_array><technique_common><accessor source="#pPlane16-visibility-animation-output-array" count="5"><param type="float"/></accessor></technique_common></source><source id="pPlane16-visibility-animation-intan"><float_array id="pPlane16-visibility-animation-intan-array" count="5">
+
+0.000000 0.000000 0.000000 0.000000 0.000000</float_array><technique_common><accessor source="#pPlane16-visibility-animation-intan-array" count="5"><param type="float"/></accessor></technique_common></source><source id="pPlane16-visibility-animation-outtan"><float_array id="pPlane16-visibility-animation-outtan-array" count="5">
+
+0.000000 0.000000 0.000000 0.000000 0.000000</float_array><technique_common><accessor source="#pPlane16-visibility-animation-outtan-array" count="5"><param type="float"/></accessor></technique_common></source><source id="pPlane16-visibility-animation-interpolation"><Name_array id="pPlane16-visibility-animation-interpolation-array" count="5">
+ STEP STEP STEP STEP BEZIER</Name_array><technique_common><accessor source="#pPlane16-visibility-animation-interpolation-array" count="5"><param type="name"/></accessor></technique_common></source><sampler id="pPlane16-visibility-animation"><input semantic="INPUT" source="#pPlane16-visibility-animation-input"/><input semantic="OUTPUT" source="#pPlane16-visibility-animation-output"/><input semantic="IN_TANGENT" source="#pPlane16-visibility-animation-intan"/><input semantic="OUT_TANGENT" source="#pPlane16-visibility-animation-outtan"/><input semantic="INTERPOLATION" source="#pPlane16-visibility-animation-interpolation"/></sampler><channel source="#pPlane16-visibility-animation" target="pPlane16/visibility"/></animation><animation><source id="pPlane16-lib-morph-weights-animation-inputWeight_0_0"><float_array id="pPlane16-lib-morph-weights-animation-inputWeight_0_0-array" count="5">
+
+0.000000 2.500000 5.000000 7.500000 10.000000</float_array><technique_common><accessor source="#pPlane16-lib-morph-weights-animation-inputWeight_0_0-array" count="5"><param name="TIME" type="float"/></accessor></technique_common></source><source id="pPlane16-lib-morph-weights-animation-outputWeight_0_0"><float_array id="pPlane16-lib-morph-weights-animation-outputWeight_0_0-array" count="5">
+
+0.000000 1.000000 0.000000 0.000000 0.000000</float_array><technique_common><accessor source="#pPlane16-lib-morph-weights-animation-outputWeight_0_0-array" count="5"><param name="Weight_0_0" type="float"/></accessor></technique_common></source><source id="pPlane16-lib-morph-weights-animation-intanWeight_0_0"><float_array id="pPlane16-lib-morph-weights-animation-intanWeight_0_0-array" count="5">
+
+0.000000 0.000000 0.000000 0.000000 0.000000</float_array><technique_common><accessor source="#pPlane16-lib-morph-weights-animation-intanWeight_0_0-array" count="5"><param name="Weight_0_0" type="float"/></accessor></technique_common></source><source id="pPlane16-lib-morph-weights-animation-outtanWeight_0_0"><float_array id="pPlane16-lib-morph-weights-animation-outtanWeight_0_0-array" count="5">
+
+0.000000 0.000000 0.000000 0.000000 0.000000</float_array><technique_common><accessor source="#pPlane16-lib-morph-weights-animation-outtanWeight_0_0-array" count="5"><param name="Weight_0_0" type="float"/></accessor></technique_common></source><source id="pPlane16-lib-morph-weights-animation-interpolationWeight_0_0"><Name_array id="pPlane16-lib-morph-weights-animation-interpolationWeight_0_0-array" count="5">
+ BEZIER BEZIER BEZIER BEZIER BEZIER</Name_array><technique_common><accessor source="#pPlane16-lib-morph-weights-animation-interpolationWeight_0_0-array" count="5"><param type="name"/></accessor></technique_common></source><sampler id="pPlane16-lib-morph-weights-animationWeight_0_0"><input semantic="INPUT" source="#pPlane16-lib-morph-weights-animation-inputWeight_0_0"/><input semantic="OUTPUT" source="#pPlane16-lib-morph-weights-animation-outputWeight_0_0"/><input semantic="IN_TANGENT" source="#pPlane16-lib-morph-weights-animation-intanWeight_0_0"/><input semantic="OUT_TANGENT" source="#pPlane16-lib-morph-weights-animation-outtanWeight_0_0"/><input semantic="INTERPOLATION" source="#pPlane16-lib-morph-weights-animation-interpolationWeight_0_0"/></sampler><channel source="#pPlane16-lib-morph-weights-animationWeight_0_0" target="pPlane16-lib-morph-weights(Weight_0_0)"/></animation><animation><source id="pPlane16-lib-morph-weights-animation-inputWeight_0_1"><float_array id="pPlane16-lib-morph-weights-animation-inputWeight_0_1-array" count="4">
+
+2.500000 5.000000 7.500000 10.000000</float_array><technique_common><accessor source="#pPlane16-lib-morph-weights-animation-inputWeight_0_1-array" count="4"><param name="TIME" type="float"/></accessor></technique_common></source><source id="pPlane16-lib-morph-weights-animation-outputWeight_0_1"><float_array id="pPlane16-lib-morph-weights-animation-outputWeight_0_1-array" count="4">
+
+0.000000 0.000000 1.000000 0.000000</float_array><technique_common><accessor source="#pPlane16-lib-morph-weights-animation-outputWeight_0_1-array" count="4"><param name="Weight_0_1" type="float"/></accessor></technique_common></source><source id="pPlane16-lib-morph-weights-animation-intanWeight_0_1"><float_array id="pPlane16-lib-morph-weights-animation-intanWeight_0_1-array" count="4">
+
+0.000000 0.000000 0.000000 0.000000</float_array><technique_common><accessor source="#pPlane16-lib-morph-weights-animation-intanWeight_0_1-array" count="4"><param name="Weight_0_1" type="float"/></accessor></technique_common></source><source id="pPlane16-lib-morph-weights-animation-outtanWeight_0_1"><float_array id="pPlane16-lib-morph-weights-animation-outtanWeight_0_1-array" count="4">
+
+0.000000 0.000000 0.000000 0.000000</float_array><technique_common><accessor source="#pPlane16-lib-morph-weights-animation-outtanWeight_0_1-array" count="4"><param name="Weight_0_1" type="float"/></accessor></technique_common></source><source id="pPlane16-lib-morph-weights-animation-interpolationWeight_0_1"><Name_array id="pPlane16-lib-morph-weights-animation-interpolationWeight_0_1-array" count="4">
+ BEZIER BEZIER BEZIER BEZIER</Name_array><technique_common><accessor source="#pPlane16-lib-morph-weights-animation-interpolationWeight_0_1-array" count="4"><param type="name"/></accessor></technique_common></source><sampler id="pPlane16-lib-morph-weights-animationWeight_0_1"><input semantic="INPUT" source="#pPlane16-lib-morph-weights-animation-inputWeight_0_1"/><input semantic="OUTPUT" source="#pPlane16-lib-morph-weights-animation-outputWeight_0_1"/><input semantic="IN_TANGENT" source="#pPlane16-lib-morph-weights-animation-intanWeight_0_1"/><input semantic="OUT_TANGENT" source="#pPlane16-lib-morph-weights-animation-outtanWeight_0_1"/><input semantic="INTERPOLATION" source="#pPlane16-lib-morph-weights-animation-interpolationWeight_0_1"/></sampler><channel source="#pPlane16-lib-morph-weights-animationWeight_0_1" target="pPlane16-lib-morph-weights(Weight_0_1)"/></animation></animation>
+ </library_animations>
+ <library_visual_scenes>
+ <visual_scene id="blendshapeanimation" name="blendshapeanimation">
+ <node name="pPlane16" id="pPlane16" sid="pPlane16"><matrix sid="matrix">593.587463 0.000000 0.000000 0.000053 0.000000 593.587463 0.000000 0.000000 0.000000 0.000000 597.200012 1684.046143 0.000000 0.000000 0.000000 1.000000</matrix><instance_controller url="#pPlane16-lib-morph"><bind_material><technique_common><instance_material symbol="lambert2" target="#lambert2"/></technique_common></bind_material></instance_controller><extra><technique profile="FCOLLADA"><visibility>1.000000</visibility></technique></extra></node>
+ <extra><technique profile="MAX3D"><frame_rate>24.000000</frame_rate></technique><technique profile="FCOLLADA"><start_time>0.041667</start_time><end_time>8.333333</end_time></technique></extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_visual_scene url="#blendshapeanimation"></instance_visual_scene>
+ </scene>
+</COLLADA>
diff --git a/tests/manual/anim-viewer/assets/gears.dae b/tests/manual/anim-viewer/assets/gears.dae
new file mode 100644
index 000000000..4d34983b7
--- /dev/null
+++ b/tests/manual/anim-viewer/assets/gears.dae
@@ -0,0 +1,873 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>Blender User</author>
+ <authoring_tool>Blender 2.77.0 commit date:2016-04-05, commit time:18:12, hash:abf6f08</authoring_tool>
+ </contributor>
+ <created>2016-09-21T14:50:51</created>
+ <modified>2016-09-21T14:50:51</modified>
+ <unit name="meter" meter="1"/>
+ <up_axis>Z_UP</up_axis>
+ </asset>
+ <library_images/>
+ <library_effects>
+ <effect id="Material_001-effect">
+ <profile_COMMON>
+ <technique sid="common">
+ <phong>
+ <emission>
+ <color sid="emission">0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color sid="ambient">0.02197916 0.02197916 0.02197916 1</color>
+ </ambient>
+ <diffuse>
+ <color sid="diffuse">0.64 0.64 0.64 1</color>
+ </diffuse>
+ <specular>
+ <color sid="specular">0.5 0.5 0.5 1</color>
+ </specular>
+ <shininess>
+ <float sid="shininess">50</float>
+ </shininess>
+ <index_of_refraction>
+ <float sid="index_of_refraction">1</float>
+ </index_of_refraction>
+ </phong>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ <effect id="Material_002-effect">
+ <profile_COMMON>
+ <technique sid="common">
+ <phong>
+ <emission>
+ <color sid="emission">0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color sid="ambient">0.02197916 0.02197916 0.02197916 1</color>
+ </ambient>
+ <diffuse>
+ <color sid="diffuse">0.64 0.64 0.64 1</color>
+ </diffuse>
+ <specular>
+ <color sid="specular">0.5 0.5 0.5 1</color>
+ </specular>
+ <shininess>
+ <float sid="shininess">50</float>
+ </shininess>
+ <index_of_refraction>
+ <float sid="index_of_refraction">1</float>
+ </index_of_refraction>
+ </phong>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ <effect id="Material-effect">
+ <profile_COMMON>
+ <technique sid="common">
+ <phong>
+ <emission>
+ <color sid="emission">0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color sid="ambient">0.02197916 0.02197916 0.02197916 1</color>
+ </ambient>
+ <diffuse>
+ <color sid="diffuse">0.64 0.64 0.64 1</color>
+ </diffuse>
+ <specular>
+ <color sid="specular">0.5 0.5 0.5 1</color>
+ </specular>
+ <shininess>
+ <float sid="shininess">50</float>
+ </shininess>
+ <index_of_refraction>
+ <float sid="index_of_refraction">1</float>
+ </index_of_refraction>
+ </phong>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_materials>
+ <material id="Material_001-material" name="Material_001">
+ <instance_effect url="#Material_001-effect"/>
+ </material>
+ <material id="Material_002-material" name="Material_002">
+ <instance_effect url="#Material_002-effect"/>
+ </material>
+ <material id="Material-material" name="Material">
+ <instance_effect url="#Material-effect"/>
+ </material>
+ </library_materials>
+ <library_geometries>
+ <geometry id="Cylinder_005-mesh" name="Cylinder.005">
+ <mesh>
+ <source id="Cylinder_005-mesh-positions">
+ <float_array id="Cylinder_005-mesh-positions-array" count="216">-0.6937502 0.7202157 -0.1465266 -0.117956 0.122456 0.1465266 -0.2406975 0.9706001 -0.1465266 -0.04092502 0.165028 0.1465266 0.2768501 0.9609132 -0.1465266 0.04707187 0.1633808 0.1465266 0.7202157 0.6937502 -0.1465266 0.122456 0.1179561 0.1465266 0.9706003 0.2406975 -0.1465266 0.165028 0.04092496 0.1465266 0.9609132 -0.2768499 -0.1465266 0.163381 -0.04707187 0.1465266 0.6937503 -0.7202156 -0.1465266 0.1179561 -0.1224558 0.1465266 0.2406976 -0.9706001 -0.1465266 0.04092496 -0.1650279 0.1465266 -0.2768496 -0.9609132 -0.1465266 -0.04707181 -0.163381 0.1465266 -0.7202154 -0.6937506 -0.1465266 -0.1224559 -0.1179561 0.1465266 -0.9706 -0.240698 -0.1465266 -0.165028 -0.04092508 0.1465266 -0.9609134 0.2768493 -0.1465266 -0.1633809 0.04707157 0.1465266 -1.161437 1.002034 -0.1465266 -1.161437 1.002034 0.1465266 -0.2304791 1.516537 0.1465266 -0.2304791 1.516537 -0.1465266 0.2870684 1.50685 -0.1465266 0.2870684 1.50685 0.1465266 1.19812 0.9578695 0.1465266 1.19812 0.9578695 -0.1465266 1.448505 0.5048167 -0.1465266 1.448505 0.5048167 0.1465266 1.4286 -0.5586678 0.1465266 1.4286 -0.5586678 -0.1465266 1.161437 -1.002034 -0.1465266 1.161437 -1.002034 0.1465266 0.2304794 -1.516537 0.1465266 0.2304794 -1.516537 -0.1465266 -0.2870679 -1.50685 -0.1465266 -0.2870679 -1.50685 0.1465266 -1.19812 -0.95787 0.1465266 -1.19812 -0.95787 -0.1465266 -1.448505 -0.5048175 -0.1465266 -1.448505 -0.5048175 0.1465266 -1.4286 0.5586673 0.1465266 -1.4286 0.5586673 -0.1465266 -0.2406975 0.9706001 0.1465266 -0.6937502 0.7202157 0.1465266 0.2768501 0.9609132 0.1465266 0.7202157 0.6937502 0.1465266 0.9706003 0.2406975 0.1465266 0.9609132 -0.2768499 0.1465266 0.6937503 -0.7202156 0.1465266 0.2406976 -0.9706001 0.1465266 -0.2768496 -0.9609132 0.1465266 -0.7202154 -0.6937506 0.1465266 -0.9706 -0.240698 0.1465266 -0.9609134 0.2768493 0.1465266 -0.04092502 0.165028 2.134743 -0.117956 0.122456 2.134743 0.04707187 0.1633808 2.134743 0.122456 0.1179561 2.134743 0.165028 0.04092496 2.134743 0.163381 -0.04707187 2.134743 0.1179561 -0.1224558 2.134743 0.04092496 -0.1650279 2.134743 -0.04707181 -0.163381 2.134743 -0.1224559 -0.1179561 2.134743 -0.165028 -0.04092508 2.134743 -0.1633809 0.04707157 2.134743</float_array>
+ <technique_common>
+ <accessor source="#Cylinder_005-mesh-positions-array" count="72" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Cylinder_005-mesh-normals">
+ <float_array id="Cylinder_005-mesh-normals-array" count="180">0.01019328 0.5446093 0.838628 -0.4665465 0.281112 -0.8386361 0.01019328 0.5446093 -0.838628 -0.1965123 0.7924888 0.5773599 0.4767377 0.2634708 0.8386324 0.4767377 0.2634708 -0.8386324 -0.4767377 -0.2634708 -0.8386324 -0.5880461 -0.5664384 0.5773643 -0.4767377 -0.2634708 0.8386324 0.4665465 -0.281112 0.8386361 0.4665465 -0.281112 -0.8386361 0.2260238 0.7845829 -0.5773588 -0.01019328 -0.5446093 0.838628 -0.01019328 -0.5446093 -0.838628 0.7924888 0.1965123 -0.5773599 0.1965123 -0.7924888 -0.5773599 0.5664384 -0.5880461 0.5773643 -0.6127917 0.1765526 0.7702699 -0.525269 0.5453203 0.6532368 -0.4424093 0.4592865 0.7702792 -0.4665465 0.281112 0.8386361 -0.7845829 0.2260238 0.5773588 -0.5664384 0.5880461 0.5773643 0.5880461 0.5664384 -0.5773643 -0.5664384 0.5880461 -0.5773643 0.2260238 0.7845829 0.5773588 0.7845829 -0.2260238 -0.5773588 0.7924888 0.1965123 0.5773599 -0.5880461 -0.5664384 -0.5773643 0.5664384 -0.5880461 -0.5773643 -0.2260238 -0.7845829 0.5773588 -0.7845829 0.2260238 -0.5773588 -0.2260238 -0.7845829 -0.5773588 -0.7924888 -0.1965123 0.5773599 -0.1965123 0.7924888 -0.5773599 -0.7924888 -0.1965123 -0.5773599 0.1965123 -0.7924888 0.5773599 0.7845829 -0.2260238 0.5773588 0.5880461 0.5664384 0.5773643 0.1765526 0.6127917 0.7702699 -0.1534789 0.6189819 0.7702634 0.4592865 0.4424093 0.7702792 0.6189819 0.1534789 0.7702634 0.6127917 -0.1765526 0.7702699 0.1534789 -0.6189819 0.7702634 0.4424093 -0.4592865 0.7702792 -0.1765526 -0.6127917 0.7702699 -0.4592865 -0.4424093 0.7702792 -0.6189819 -0.1534789 0.7702634 -0.7349014 -0.1822299 0.6532321 0.525269 -0.5453203 0.6532368 0.209604 0.7275715 0.6532273 -0.5453203 -0.525269 0.6532368 0.5453203 0.525269 0.6532368 0.1822299 -0.7349014 0.6532321 0.7349014 0.1822299 0.6532321 -0.7275715 0.209604 0.6532273 -0.1822299 0.7349014 0.6532321 -0.209604 -0.7275715 0.6532273 0.7275715 -0.209604 0.6532273</float_array>
+ <technique_common>
+ <accessor source="#Cylinder_005-mesh-normals-array" count="60" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Cylinder_005-mesh-vertices">
+ <input semantic="POSITION" source="#Cylinder_005-mesh-positions"/>
+ </vertices>
+ <polylist material="Material_001-material" count="140">
+ <input semantic="VERTEX" source="#Cylinder_005-mesh-vertices" offset="0"/>
+ <input semantic="NORMAL" source="#Cylinder_005-mesh-normals" offset="1"/>
+ <vcount>3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 </vcount>
+ <p>49 0 2 1 0 2 0 2 25 3 49 0 50 4 6 2 4 5 16 6 41 7 56 8 52 9 10 5 8 10 51 0 31 11 6 2 54 12 14 10 12 13 12 13 35 14 36 15 56 8 18 13 16 6 55 9 41 7 38 16 23 17 61 18 1 19 58 20 22 6 20 1 20 1 45 21 58 20 6 2 14 10 22 6 26 22 28 23 27 24 30 25 32 26 31 11 34 27 36 15 35 14 38 16 40 28 39 29 42 30 44 31 43 32 46 33 24 34 47 35 54 12 34 27 53 4 8 10 31 11 32 26 48 20 27 24 2 1 12 13 37 36 54 12 59 8 47 35 22 6 52 9 30 25 51 0 4 5 27 24 28 23 22 6 24 34 0 2 8 10 33 37 52 9 57 12 43 32 18 13 50 4 26 22 48 20 49 0 46 33 59 8 20 1 43 32 44 31 4 5 29 38 50 4 55 9 39 29 14 10 58 20 42 30 57 12 14 10 40 28 16 6 53 4 35 14 10 5 1 19 48 20 49 0 5 39 48 20 3 40 7 41 50 4 5 39 9 42 51 0 7 41 11 43 52 9 9 42 11 43 54 12 53 4 15 44 54 12 13 45 17 46 55 9 15 44 19 47 56 8 17 46 19 47 58 20 57 12 21 48 59 8 58 20 1 19 59 8 23 17 70 49 66 50 62 51 3 40 62 51 5 39 17 46 69 52 19 47 11 43 66 50 13 45 5 39 63 53 7 41 19 47 70 49 21 48 13 45 67 54 15 44 7 41 64 55 9 42 21 48 71 56 23 17 1 19 60 57 3 40 15 44 68 58 17 46 9 42 65 59 11 43 49 0 48 20 2 1 0 2 24 34 25 3 50 4 51 0 6 2 16 6 40 28 41 7 52 9 53 4 10 5 51 0 30 25 31 11 54 12 55 9 14 10 12 13 10 5 35 14 56 8 57 12 18 13 55 9 56 8 41 7 23 17 71 56 61 18 58 20 59 8 22 6 20 1 44 31 45 21 22 6 0 2 6 2 2 1 4 5 6 2 6 2 8 10 10 5 10 5 12 13 14 10 14 10 16 6 18 13 18 13 20 1 14 10 0 2 2 1 6 2 6 2 10 5 14 10 14 10 20 1 22 6 26 22 29 38 28 23 30 25 33 37 32 26 34 27 37 36 36 15 38 16 41 7 40 28 42 30 45 21 44 31 46 33 25 3 24 34 54 12 37 36 34 27 8 10 6 2 31 11 48 20 26 22 27 24 12 13 36 15 37 36 59 8 46 33 47 35 52 9 33 37 30 25 4 5 2 1 27 24 22 6 47 35 24 34 8 10 32 26 33 37 57 12 42 30 43 32 50 4 29 38 26 22 49 0 25 3 46 33 20 1 18 13 43 32 4 5 28 23 29 38 55 9 38 16 39 29 58 20 45 21 42 30 14 10 39 29 40 28 53 4 34 27 35 14 1 19 3 40 48 20 5 39 50 4 48 20 7 41 51 0 50 4 9 42 52 9 51 0 11 43 53 4 52 9 11 43 13 45 54 12 15 44 55 9 54 12 17 46 56 8 55 9 19 47 57 12 56 8 19 47 21 48 58 20 21 48 23 17 59 8 1 19 49 0 59 8 62 51 60 57 61 18 61 18 71 56 62 51 70 49 69 52 68 58 68 58 67 54 70 49 66 50 65 59 64 55 64 55 63 53 62 51 62 51 71 56 70 49 70 49 67 54 66 50 66 50 64 55 62 51 3 40 60 57 62 51 17 46 68 58 69 52 11 43 65 59 66 50 5 39 62 51 63 53 19 47 69 52 70 49 13 45 66 50 67 54 7 41 63 53 64 55 21 48 70 49 71 56 1 19 61 18 60 57 15 44 67 54 68 58 9 42 64 55 65 59</p>
+ </polylist>
+ </mesh>
+ </geometry>
+ <geometry id="Cylinder_001-mesh" name="Cylinder.001">
+ <mesh>
+ <source id="Cylinder_001-mesh-positions">
+ <float_array id="Cylinder_001-mesh-positions-array" count="216">-0.6937502 0.7202157 -0.1465266 -0.117956 0.122456 0.1465266 -0.2406975 0.9706001 -0.1465266 -0.04092502 0.165028 0.1465266 0.2768501 0.9609132 -0.1465266 0.04707187 0.1633808 0.1465266 0.7202157 0.6937502 -0.1465266 0.122456 0.1179561 0.1465266 0.9706003 0.2406975 -0.1465266 0.165028 0.04092496 0.1465266 0.9609132 -0.2768499 -0.1465266 0.163381 -0.04707187 0.1465266 0.6937503 -0.7202156 -0.1465266 0.1179561 -0.1224558 0.1465266 0.2406976 -0.9706001 -0.1465266 0.04092496 -0.1650279 0.1465266 -0.2768496 -0.9609132 -0.1465266 -0.04707181 -0.163381 0.1465266 -0.7202154 -0.6937506 -0.1465266 -0.1224559 -0.1179561 0.1465266 -0.9706 -0.240698 -0.1465266 -0.165028 -0.04092508 0.1465266 -0.9609134 0.2768493 -0.1465266 -0.1633809 0.04707157 0.1465266 -1.161437 1.002034 -0.1465266 -1.161437 1.002034 0.1465266 -0.2304791 1.516537 0.1465266 -0.2304791 1.516537 -0.1465266 0.2870684 1.50685 -0.1465266 0.2870684 1.50685 0.1465266 1.19812 0.9578695 0.1465266 1.19812 0.9578695 -0.1465266 1.448505 0.5048167 -0.1465266 1.448505 0.5048167 0.1465266 1.4286 -0.5586678 0.1465266 1.4286 -0.5586678 -0.1465266 1.161437 -1.002034 -0.1465266 1.161437 -1.002034 0.1465266 0.2304794 -1.516537 0.1465266 0.2304794 -1.516537 -0.1465266 -0.2870679 -1.50685 -0.1465266 -0.2870679 -1.50685 0.1465266 -1.19812 -0.95787 0.1465266 -1.19812 -0.95787 -0.1465266 -1.448505 -0.5048175 -0.1465266 -1.448505 -0.5048175 0.1465266 -1.4286 0.5586673 0.1465266 -1.4286 0.5586673 -0.1465266 -0.2406975 0.9706001 0.1465266 -0.6937502 0.7202157 0.1465266 0.2768501 0.9609132 0.1465266 0.7202157 0.6937502 0.1465266 0.9706003 0.2406975 0.1465266 0.9609132 -0.2768499 0.1465266 0.6937503 -0.7202156 0.1465266 0.2406976 -0.9706001 0.1465266 -0.2768496 -0.9609132 0.1465266 -0.7202154 -0.6937506 0.1465266 -0.9706 -0.240698 0.1465266 -0.9609134 0.2768493 0.1465266 -0.04092502 0.165028 2.134743 -0.117956 0.122456 2.134743 0.04707187 0.1633808 2.134743 0.122456 0.1179561 2.134743 0.165028 0.04092496 2.134743 0.163381 -0.04707187 2.134743 0.1179561 -0.1224558 2.134743 0.04092496 -0.1650279 2.134743 -0.04707181 -0.163381 2.134743 -0.1224559 -0.1179561 2.134743 -0.165028 -0.04092508 2.134743 -0.1633809 0.04707157 2.134743</float_array>
+ <technique_common>
+ <accessor source="#Cylinder_001-mesh-positions-array" count="72" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Cylinder_001-mesh-normals">
+ <float_array id="Cylinder_001-mesh-normals-array" count="180">0.01019328 0.5446093 0.838628 -0.4665465 0.281112 -0.8386361 0.01019328 0.5446093 -0.838628 -0.1965123 0.7924888 0.5773599 0.4767377 0.2634708 0.8386324 0.4767377 0.2634708 -0.8386324 -0.4767377 -0.2634708 -0.8386324 -0.5880461 -0.5664384 0.5773643 -0.4767377 -0.2634708 0.8386324 0.4665465 -0.281112 0.8386361 0.4665465 -0.281112 -0.8386361 0.2260238 0.7845829 -0.5773588 -0.01019328 -0.5446093 0.838628 -0.01019328 -0.5446093 -0.838628 0.7924888 0.1965123 -0.5773599 0.1965123 -0.7924888 -0.5773599 0.5664384 -0.5880461 0.5773643 -0.6127917 0.1765526 0.7702699 -0.525269 0.5453203 0.6532368 -0.4424093 0.4592865 0.7702792 -0.4665465 0.281112 0.8386361 -0.7845829 0.2260238 0.5773588 -0.5664384 0.5880461 0.5773643 0.5880461 0.5664384 -0.5773643 -0.5664384 0.5880461 -0.5773643 0.2260238 0.7845829 0.5773588 0.7845829 -0.2260238 -0.5773588 0.7924888 0.1965123 0.5773599 -0.5880461 -0.5664384 -0.5773643 0.5664384 -0.5880461 -0.5773643 -0.2260238 -0.7845829 0.5773588 -0.7845829 0.2260238 -0.5773588 -0.2260238 -0.7845829 -0.5773588 -0.7924888 -0.1965123 0.5773599 -0.1965123 0.7924888 -0.5773599 -0.7924888 -0.1965123 -0.5773599 0.1965123 -0.7924888 0.5773599 0.7845829 -0.2260238 0.5773588 0.5880461 0.5664384 0.5773643 0.1765526 0.6127917 0.7702699 -0.1534789 0.6189819 0.7702634 0.4592865 0.4424093 0.7702792 0.6189819 0.1534789 0.7702634 0.6127917 -0.1765526 0.7702699 0.1534789 -0.6189819 0.7702634 0.4424093 -0.4592865 0.7702792 -0.1765526 -0.6127917 0.7702699 -0.4592865 -0.4424093 0.7702792 -0.6189819 -0.1534789 0.7702634 -0.7349014 -0.1822299 0.6532321 0.525269 -0.5453203 0.6532368 0.209604 0.7275715 0.6532273 -0.5453203 -0.525269 0.6532368 0.5453203 0.525269 0.6532368 0.1822299 -0.7349014 0.6532321 0.7349014 0.1822299 0.6532321 -0.7275715 0.209604 0.6532273 -0.1822299 0.7349014 0.6532321 -0.209604 -0.7275715 0.6532273 0.7275715 -0.209604 0.6532273</float_array>
+ <technique_common>
+ <accessor source="#Cylinder_001-mesh-normals-array" count="60" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Cylinder_001-mesh-vertices">
+ <input semantic="POSITION" source="#Cylinder_001-mesh-positions"/>
+ </vertices>
+ <polylist material="Material_001-material" count="140">
+ <input semantic="VERTEX" source="#Cylinder_001-mesh-vertices" offset="0"/>
+ <input semantic="NORMAL" source="#Cylinder_001-mesh-normals" offset="1"/>
+ <vcount>3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 </vcount>
+ <p>49 0 2 1 0 2 0 2 25 3 49 0 50 4 6 2 4 5 16 6 41 7 56 8 52 9 10 5 8 10 51 0 31 11 6 2 54 12 14 10 12 13 12 13 35 14 36 15 56 8 18 13 16 6 55 9 41 7 38 16 23 17 61 18 1 19 58 20 22 6 20 1 20 1 45 21 58 20 6 2 14 10 22 6 26 22 28 23 27 24 30 25 32 26 31 11 34 27 36 15 35 14 38 16 40 28 39 29 42 30 44 31 43 32 46 33 24 34 47 35 54 12 34 27 53 4 8 10 31 11 32 26 48 20 27 24 2 1 12 13 37 36 54 12 59 8 47 35 22 6 52 9 30 25 51 0 4 5 27 24 28 23 22 6 24 34 0 2 8 10 33 37 52 9 57 12 43 32 18 13 50 4 26 22 48 20 49 0 46 33 59 8 20 1 43 32 44 31 4 5 29 38 50 4 55 9 39 29 14 10 58 20 42 30 57 12 14 10 40 28 16 6 53 4 35 14 10 5 1 19 48 20 49 0 5 39 48 20 3 40 7 41 50 4 5 39 9 42 51 0 7 41 11 43 52 9 9 42 11 43 54 12 53 4 15 44 54 12 13 45 17 46 55 9 15 44 19 47 56 8 17 46 19 47 58 20 57 12 21 48 59 8 58 20 1 19 59 8 23 17 70 49 66 50 62 51 3 40 62 51 5 39 17 46 69 52 19 47 11 43 66 50 13 45 5 39 63 53 7 41 19 47 70 49 21 48 13 45 67 54 15 44 7 41 64 55 9 42 21 48 71 56 23 17 1 19 60 57 3 40 15 44 68 58 17 46 9 42 65 59 11 43 49 0 48 20 2 1 0 2 24 34 25 3 50 4 51 0 6 2 16 6 40 28 41 7 52 9 53 4 10 5 51 0 30 25 31 11 54 12 55 9 14 10 12 13 10 5 35 14 56 8 57 12 18 13 55 9 56 8 41 7 23 17 71 56 61 18 58 20 59 8 22 6 20 1 44 31 45 21 22 6 0 2 6 2 2 1 4 5 6 2 6 2 8 10 10 5 10 5 12 13 14 10 14 10 16 6 18 13 18 13 20 1 14 10 0 2 2 1 6 2 6 2 10 5 14 10 14 10 20 1 22 6 26 22 29 38 28 23 30 25 33 37 32 26 34 27 37 36 36 15 38 16 41 7 40 28 42 30 45 21 44 31 46 33 25 3 24 34 54 12 37 36 34 27 8 10 6 2 31 11 48 20 26 22 27 24 12 13 36 15 37 36 59 8 46 33 47 35 52 9 33 37 30 25 4 5 2 1 27 24 22 6 47 35 24 34 8 10 32 26 33 37 57 12 42 30 43 32 50 4 29 38 26 22 49 0 25 3 46 33 20 1 18 13 43 32 4 5 28 23 29 38 55 9 38 16 39 29 58 20 45 21 42 30 14 10 39 29 40 28 53 4 34 27 35 14 1 19 3 40 48 20 5 39 50 4 48 20 7 41 51 0 50 4 9 42 52 9 51 0 11 43 53 4 52 9 11 43 13 45 54 12 15 44 55 9 54 12 17 46 56 8 55 9 19 47 57 12 56 8 19 47 21 48 58 20 21 48 23 17 59 8 1 19 49 0 59 8 62 51 60 57 61 18 61 18 71 56 62 51 70 49 69 52 68 58 68 58 67 54 70 49 66 50 65 59 64 55 64 55 63 53 62 51 62 51 71 56 70 49 70 49 67 54 66 50 66 50 64 55 62 51 3 40 60 57 62 51 17 46 68 58 69 52 11 43 65 59 66 50 5 39 62 51 63 53 19 47 69 52 70 49 13 45 66 50 67 54 7 41 63 53 64 55 21 48 70 49 71 56 1 19 61 18 60 57 15 44 67 54 68 58 9 42 64 55 65 59</p>
+ </polylist>
+ </mesh>
+ </geometry>
+ <geometry id="Cylinder_003-mesh" name="Cylinder.003">
+ <mesh>
+ <source id="Cylinder_003-mesh-positions">
+ <float_array id="Cylinder_003-mesh-positions-array" count="216">0.1465264 -0.9675643 0.252625 -0.1465267 -0.1645117 0.04295283 0.1465264 -0.9642478 -0.2650024 -0.1465267 -0.1639478 -0.04505747 0.1465265 -0.7025618 -0.7116228 -0.1465267 -0.1194542 -0.1209948 0.1465266 -0.2526249 -0.9675642 -0.1465267 -0.04295289 -0.1645118 0.1465267 0.2650024 -0.9642477 -0.1465266 0.04505759 -0.1639479 0.1465268 0.7116226 -0.7025619 -0.1465266 0.1209949 -0.1194544 0.1465269 0.9675641 -0.2526252 -0.1465266 0.1645117 -0.04295301 0.1465269 0.9642477 0.2650023 -0.1465266 0.1639478 0.04505747 0.1465269 0.7025619 0.7116225 -0.1465266 0.1194544 0.1209949 0.1465268 0.2526254 0.9675642 -0.1465266 0.04295307 0.1645118 0.1465266 -0.2650019 0.9642478 -0.1465266 -0.04505741 0.163948 0.1465265 -0.7116223 0.7025623 -0.1465267 -0.1209946 0.1194544 0.1465263 -1.442182 0.5226061 -0.146527 -1.442182 0.5226061 -0.1465271 -1.435367 -0.541043 0.1465263 -1.435367 -0.541043 0.1465263 -1.173681 -0.9876634 -0.146527 -1.173681 -0.9876634 -0.1465268 -0.2491264 -1.513586 0.1465265 -0.2491265 -1.513586 0.1465267 0.2685009 -1.510269 -0.1465266 0.268501 -1.510269 -0.1465264 1.186241 -0.972543 0.1465269 1.186241 -0.972543 0.146527 1.442182 -0.5226063 -0.1465263 1.442182 -0.5226063 -0.1465263 1.435367 0.5410427 0.1465271 1.435367 0.5410427 0.146527 1.173681 0.9876629 -0.1465263 1.173681 0.9876629 -0.1465265 0.2491272 1.513586 0.1465268 0.2491272 1.513586 0.1465266 -0.2685002 1.510269 -0.1465267 -0.2685002 1.510269 -0.1465269 -1.18624 0.9725435 0.1465264 -1.18624 0.9725435 -0.1465269 -0.9642477 -0.2650024 -0.1465269 -0.9675642 0.252625 -0.1465269 -0.7025617 -0.7116228 -0.1465268 -0.2526249 -0.9675642 -0.1465266 0.2650025 -0.9642477 -0.1465265 0.7116227 -0.7025619 -0.1465264 0.9675642 -0.2526252 -0.1465264 0.9642478 0.2650023 -0.1465265 0.702562 0.7116225 -0.1465266 0.2526255 0.9675642 -0.1465267 -0.2650018 0.9642478 -0.1465268 -0.7116222 0.7025623 -2.134743 -0.1639474 -0.04505741 -2.134743 -0.1645112 0.04295295 -2.134743 -0.1194536 -0.1209948 -2.134743 -0.04295235 -0.1645117 -2.134743 0.04505807 -0.1639478 -2.134743 0.1209955 -0.1194543 -2.134743 0.1645123 -0.04295295 -2.134743 0.1639484 0.04505753 -2.134743 0.1194549 0.1209949 -2.134743 0.04295361 0.1645119 -2.134743 -0.04505687 0.1639481 -2.134743 -0.120994 0.1194545</float_array>
+ <technique_common>
+ <accessor source="#Cylinder_003-mesh-positions-array" count="72" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Cylinder_003-mesh-normals">
+ <float_array id="Cylinder_003-mesh-normals-array" count="180">-0.8386326 -0.4699627 -0.2753733 0.8386434 -0.4734479 0.2693035 0.8386326 -0.4699627 -0.2753733 -0.5773617 -0.7873031 -0.2163504 -0.8386386 0.003479182 -0.5446771 0.8386386 0.003479182 -0.5446771 0.8386386 -0.003479182 0.5446771 -0.5773573 0.206247 0.7900132 -0.8386386 -0.003479182 0.5446771 -0.8386434 0.4734479 -0.2693035 0.8386434 0.4734479 -0.2693035 0.5773628 -0.5736395 -0.5810251 0.8386326 0.4699627 0.2753733 0.5773617 0.2163504 -0.7873031 0.5773617 0.7873031 0.2163504 -0.5773573 0.7900132 -0.206247 -0.770264 -0.4538146 0.4480465 -0.6532273 -0.732607 0.1912621 -0.7702726 -0.6170361 0.16108 -0.8386434 -0.4734479 0.2693035 -0.5773627 -0.581025 0.5736394 0.5773573 -0.7900132 0.206247 -0.5773573 -0.206247 -0.7900132 0.5773573 -0.206247 -0.7900132 -0.5773628 -0.5736395 -0.5810251 0.5773627 0.581025 -0.5736394 -0.5773617 0.7873031 0.2163504 0.5773573 0.206247 0.7900132 0.5773573 0.7900132 -0.206247 0.5773628 0.5736395 0.5810251 0.5773627 -0.581025 0.5736394 -0.5773617 -0.2163504 0.7873031 0.5773617 -0.7873031 -0.2163504 0.5773617 -0.2163504 0.7873031 -0.8386326 0.4699627 0.2753733 -0.5773617 0.2163504 -0.7873031 -0.5773627 0.581025 -0.5736394 -0.5773573 -0.7900132 0.206247 -0.5773628 0.5736395 0.5810251 -0.770267 -0.6149257 -0.1689832 -0.7702641 -0.4480466 -0.4538146 -0.7702726 -0.16108 -0.6170361 -0.770267 0.1689832 -0.6149257 -0.770264 0.4538146 -0.4480465 -0.770267 0.6149257 0.1689832 -0.7702726 0.6170361 -0.16108 -0.7702641 0.4480466 0.4538146 -0.7702726 0.16108 0.6170361 -0.770267 -0.1689832 0.6149257 -0.6532381 -0.2006348 0.7300861 -0.6532273 0.732607 -0.1912621 -0.6532307 -0.5319478 -0.5388146 -0.6532381 -0.7300861 -0.2006348 -0.6532273 0.1912621 0.732607 -0.6532273 -0.1912621 -0.732607 -0.6532381 0.7300861 0.2006348 -0.6532381 0.2006348 -0.7300861 -0.6532307 -0.5388146 0.5319478 -0.6532307 0.5319478 0.5388146 -0.6532307 0.5388146 -0.5319478</float_array>
+ <technique_common>
+ <accessor source="#Cylinder_003-mesh-normals-array" count="60" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Cylinder_003-mesh-vertices">
+ <input semantic="POSITION" source="#Cylinder_003-mesh-positions"/>
+ </vertices>
+ <polylist material="Material_002-material" count="140">
+ <input semantic="VERTEX" source="#Cylinder_003-mesh-vertices" offset="0"/>
+ <input semantic="NORMAL" source="#Cylinder_003-mesh-normals" offset="1"/>
+ <vcount>3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 </vcount>
+ <p>49 0 2 1 0 2 0 2 25 3 49 0 50 4 6 2 4 5 16 6 41 7 56 8 52 9 10 5 8 10 51 0 31 11 6 2 12 12 55 9 14 10 12 12 35 13 36 14 56 8 18 12 16 6 55 9 41 7 38 15 23 16 61 17 1 18 58 19 22 6 20 1 20 1 45 20 58 19 6 2 18 12 22 6 27 21 29 22 28 23 30 24 32 25 31 11 35 13 37 26 36 14 38 15 40 27 39 28 43 29 45 20 44 30 46 31 24 32 47 33 54 34 34 35 53 4 6 2 32 25 8 10 48 19 27 21 2 1 12 12 37 26 54 34 59 8 47 33 22 6 52 9 30 24 51 0 4 5 27 21 28 23 22 6 24 32 0 2 8 10 33 36 52 9 57 34 43 29 18 12 48 19 29 22 26 37 49 0 46 31 59 8 20 1 43 29 44 30 4 5 29 22 50 4 14 10 38 15 39 28 58 19 42 38 57 34 14 10 40 27 16 6 53 4 35 13 10 5 3 39 49 0 1 18 5 40 48 19 3 39 7 41 50 4 5 40 9 42 51 0 7 41 11 43 52 9 9 42 11 43 54 34 53 4 15 44 54 34 13 45 17 46 55 9 15 44 19 47 56 8 17 46 19 47 58 19 57 34 21 48 59 8 58 19 1 18 59 8 23 16 70 49 66 50 62 51 5 40 60 52 62 51 17 46 69 53 19 47 11 43 66 50 13 45 5 40 63 54 7 41 19 47 70 49 21 48 15 44 66 50 67 55 9 42 63 54 64 56 21 48 71 57 23 16 1 18 60 52 3 39 15 44 68 58 17 46 11 43 64 56 65 59 49 0 48 19 2 1 0 2 24 32 25 3 50 4 51 0 6 2 16 6 40 27 41 7 52 9 53 4 10 5 51 0 30 24 31 11 12 12 54 34 55 9 12 12 10 5 35 13 56 8 57 34 18 12 55 9 56 8 41 7 23 16 71 57 61 17 58 19 59 8 22 6 20 1 44 30 45 20 22 6 0 2 2 1 2 1 4 5 6 2 6 2 8 10 10 5 10 5 12 12 6 2 14 10 16 6 18 12 18 12 20 1 22 6 22 6 2 1 6 2 6 2 12 12 14 10 14 10 18 12 6 2 27 21 26 37 29 22 30 24 33 36 32 25 35 13 34 35 37 26 38 15 41 7 40 27 43 29 42 38 45 20 46 31 25 3 24 32 54 34 37 26 34 35 6 2 31 11 32 25 48 19 26 37 27 21 12 12 36 14 37 26 59 8 46 31 47 33 52 9 33 36 30 24 4 5 2 1 27 21 22 6 47 33 24 32 8 10 32 25 33 36 57 34 42 38 43 29 48 19 50 4 29 22 49 0 25 3 46 31 20 1 18 12 43 29 4 5 28 23 29 22 14 10 55 9 38 15 58 19 45 20 42 38 14 10 39 28 40 27 53 4 34 35 35 13 3 39 48 19 49 0 5 40 50 4 48 19 7 41 51 0 50 4 9 42 52 9 51 0 11 43 53 4 52 9 11 43 13 45 54 34 15 44 55 9 54 34 17 46 56 8 55 9 19 47 57 34 56 8 19 47 21 48 58 19 21 48 23 16 59 8 1 18 49 0 59 8 62 51 60 52 61 17 61 17 71 57 62 51 70 49 69 53 68 58 68 58 67 55 70 49 66 50 65 59 64 56 64 56 63 54 62 51 62 51 71 57 70 49 70 49 67 55 66 50 66 50 64 56 62 51 5 40 3 39 60 52 17 46 68 58 69 53 11 43 65 59 66 50 5 40 62 51 63 54 19 47 69 53 70 49 15 44 13 45 66 50 9 42 7 41 63 54 21 48 70 49 71 57 1 18 61 17 60 52 15 44 67 55 68 58 11 43 9 42 64 56</p>
+ </polylist>
+ </mesh>
+ </geometry>
+ <geometry id="Cylinder_004-mesh" name="Cylinder.004">
+ <mesh>
+ <source id="Cylinder_004-mesh-positions">
+ <float_array id="Cylinder_004-mesh-positions-array" count="216">-0.1465266 0.9675642 0.252625 0.1465266 0.1645117 0.04295283 -0.1465266 0.9642477 -0.2650024 0.1465267 0.1639479 -0.04505747 -0.1465266 0.7025617 -0.7116228 0.1465267 0.1194542 -0.1209948 -0.1465266 0.2526249 -0.9675642 0.1465267 0.04295295 -0.1645118 -0.1465266 -0.2650025 -0.9642477 0.1465266 -0.04505753 -0.1639479 -0.1465267 -0.7116227 -0.7025619 0.1465266 -0.1209949 -0.1194544 -0.1465267 -0.9675642 -0.2526252 0.1465266 -0.1645117 -0.04295301 -0.1465267 -0.9642478 0.2650023 0.1465266 -0.1639478 0.04505747 -0.1465267 -0.702562 0.7116225 0.1465266 -0.1194543 0.1209949 -0.1465267 -0.2526254 0.9675642 0.1465266 -0.04295307 0.1645118 -0.1465267 0.2650019 0.9642478 0.1465266 0.04505747 0.163948 -0.1465266 0.7116222 0.7025623 0.1465266 0.1209946 0.1194544 -0.1465266 1.442182 0.5226061 0.1465267 1.442182 0.5226061 0.1465268 1.435367 -0.541043 -0.1465266 1.435367 -0.541043 -0.1465266 1.173681 -0.9876634 0.1465268 1.173681 -0.9876634 0.1465268 0.2491264 -1.513586 -0.1465266 0.2491265 -1.513586 -0.1465266 -0.2685009 -1.510269 0.1465267 -0.2685009 -1.510269 0.1465266 -1.186241 -0.972543 -0.1465267 -1.186241 -0.972543 -0.1465267 -1.442182 -0.5226063 0.1465266 -1.442182 -0.5226063 0.1465266 -1.435367 0.5410427 -0.1465268 -1.435367 0.5410427 -0.1465268 -1.173681 0.9876629 0.1465266 -1.173681 0.9876629 0.1465266 -0.2491272 1.513586 -0.1465268 -0.2491272 1.513586 -0.1465267 0.2685002 1.510269 0.1465266 0.2685002 1.510269 0.1465267 1.18624 0.9725435 -0.1465266 1.18624 0.9725435 0.1465267 0.9642477 -0.2650024 0.1465267 0.9675642 0.252625 0.1465267 0.7025617 -0.7116228 0.1465267 0.2526249 -0.9675642 0.1465267 -0.2650025 -0.9642477 0.1465266 -0.7116227 -0.7025619 0.1465266 -0.9675642 -0.2526252 0.1465266 -0.9642478 0.2650023 0.1465266 -0.702562 0.7116225 0.1465266 -0.2526254 0.9675642 0.1465266 0.2650019 0.9642478 0.1465267 0.7116222 0.7025623 2.134743 0.1639478 -0.04505741 2.134743 0.1645116 0.04295295 2.134743 0.1194541 -0.1209948 2.134743 0.04295283 -0.1645117 2.134743 -0.04505765 -0.1639478 2.134743 -0.1209951 -0.1194543 2.134743 -0.1645119 -0.04295295 2.134743 -0.1639479 0.04505753 2.134743 -0.1194545 0.1209949 2.134743 -0.04295319 0.1645119 2.134743 0.04505735 0.1639481 2.134743 0.1209945 0.1194545</float_array>
+ <technique_common>
+ <accessor source="#Cylinder_004-mesh-positions-array" count="72" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Cylinder_004-mesh-normals">
+ <float_array id="Cylinder_004-mesh-normals-array" count="180">0.8386326 0.4699627 -0.2753733 -0.8386434 0.4734479 0.2693035 -0.8386326 0.4699627 -0.2753733 0.5773617 0.7873031 -0.2163504 0.8386386 -0.003479182 -0.5446771 -0.8386386 -0.003479182 -0.5446771 -0.8386386 0.003479182 0.5446771 0.5773573 -0.206247 0.7900132 0.8386386 0.003479182 0.5446771 -0.8386434 -0.4734479 -0.2693035 -0.5773628 0.5736395 -0.5810251 0.8386326 -0.4699627 0.2753733 -0.8386326 -0.4699627 0.2753733 -0.5773617 -0.2163504 -0.7873031 -0.5773617 -0.7873031 0.2163504 0.8386434 -0.4734479 -0.2693035 0.5773573 -0.7900132 -0.206247 0.770264 0.4538146 0.4480465 0.6532273 0.732607 0.1912621 0.7702726 0.6170361 0.16108 0.8386434 0.4734479 0.2693035 0.5773627 0.581025 0.5736394 0.5773573 0.7900132 0.206247 -0.5773573 0.206247 -0.7900132 -0.5773573 0.7900132 0.206247 0.5773628 0.5736395 -0.5810251 -0.5773627 -0.581025 -0.5736394 0.5773617 -0.7873031 0.2163504 -0.5773573 -0.206247 0.7900132 -0.5773573 -0.7900132 -0.206247 -0.5773628 -0.5736395 0.5810251 -0.5773627 0.581025 0.5736394 0.5773617 0.2163504 0.7873031 -0.5773617 0.7873031 -0.2163504 -0.5773617 0.2163504 0.7873031 0.5773617 -0.2163504 -0.7873031 0.5773627 -0.581025 -0.5736394 0.5773628 -0.5736395 0.5810251 0.5773573 0.206247 -0.7900132 0.7702641 0.4480466 -0.4538146 0.770267 0.6149257 -0.1689832 0.770267 -0.1689832 -0.6149257 0.7702726 0.16108 -0.6170361 0.770264 -0.4538146 -0.4480465 0.770267 -0.6149257 0.1689832 0.7702726 -0.6170361 -0.16108 0.7702641 -0.4480466 0.4538146 0.7702726 -0.16108 0.6170361 0.770267 0.1689832 0.6149257 0.6532381 0.2006348 0.7300861 0.6532273 -0.732607 -0.1912621 0.6532307 0.5319478 -0.5388146 0.6532273 -0.1912621 0.732607 0.6532273 0.1912621 -0.732607 0.6532235 -0.7301003 0.2006303 0.6532381 -0.2006348 -0.7300861 0.6532307 0.5388146 0.5319478 0.6532381 0.7300861 -0.2006348 0.6532307 -0.5319478 0.5388146 0.6532307 -0.5388146 -0.5319478</float_array>
+ <technique_common>
+ <accessor source="#Cylinder_004-mesh-normals-array" count="60" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Cylinder_004-mesh-vertices">
+ <input semantic="POSITION" source="#Cylinder_004-mesh-positions"/>
+ </vertices>
+ <polylist material="Material-material" count="140">
+ <input semantic="VERTEX" source="#Cylinder_004-mesh-vertices" offset="0"/>
+ <input semantic="NORMAL" source="#Cylinder_004-mesh-normals" offset="1"/>
+ <vcount>3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 </vcount>
+ <p>49 0 2 1 0 2 0 2 25 3 49 0 50 4 6 2 4 5 16 6 41 7 56 8 8 9 53 4 10 5 51 0 31 10 6 2 54 11 14 9 12 12 12 12 35 13 36 14 56 8 18 12 16 6 55 15 41 7 38 16 23 17 61 18 1 19 58 20 22 6 20 1 20 1 45 21 58 20 6 2 18 12 22 6 26 22 28 23 27 24 30 25 32 26 31 10 35 13 37 27 36 14 38 16 40 28 39 29 43 30 45 21 44 31 46 32 24 33 47 34 54 11 34 35 53 4 6 2 32 26 8 9 48 20 27 24 2 1 12 12 37 27 54 11 59 8 47 34 22 6 52 15 30 25 51 0 2 1 28 23 4 5 22 6 24 33 0 2 52 15 32 26 33 36 18 12 42 37 43 30 50 4 26 22 48 20 49 0 46 32 59 8 20 1 43 30 44 31 50 4 28 23 29 38 14 9 38 16 39 29 58 20 42 37 57 11 14 9 40 28 16 6 53 4 35 13 10 5 1 19 48 20 49 0 5 39 48 20 3 40 5 39 51 0 50 4 9 41 51 0 7 42 11 43 52 15 9 41 11 43 54 11 53 4 15 44 54 11 13 45 17 46 55 15 15 44 19 47 56 8 17 46 19 47 58 20 57 11 23 17 58 20 21 48 1 19 59 8 23 17 70 49 66 50 62 51 3 40 62 51 5 39 17 46 69 52 19 47 11 43 66 50 13 45 5 39 63 53 7 42 19 47 70 49 21 48 15 44 66 50 67 54 9 41 63 53 64 55 21 48 71 56 23 17 1 19 60 57 3 40 15 44 68 58 17 46 9 41 65 59 11 43 49 0 48 20 2 1 0 2 24 33 25 3 50 4 51 0 6 2 16 6 40 28 41 7 8 9 52 15 53 4 51 0 30 25 31 10 54 11 55 15 14 9 12 12 10 5 35 13 56 8 57 11 18 12 55 15 56 8 41 7 23 17 71 56 61 18 58 20 59 8 22 6 20 1 44 31 45 21 22 6 0 2 2 1 2 1 4 5 6 2 6 2 8 9 10 5 10 5 12 12 6 2 14 9 16 6 18 12 18 12 20 1 22 6 22 6 2 1 6 2 6 2 12 12 14 9 14 9 18 12 6 2 26 22 29 38 28 23 30 25 33 36 32 26 35 13 34 35 37 27 38 16 41 7 40 28 43 30 42 37 45 21 46 32 25 3 24 33 54 11 37 27 34 35 6 2 31 10 32 26 48 20 26 22 27 24 12 12 36 14 37 27 59 8 46 32 47 34 52 15 33 36 30 25 2 1 27 24 28 23 22 6 47 34 24 33 52 15 8 9 32 26 18 12 57 11 42 37 50 4 29 38 26 22 49 0 25 3 46 32 20 1 18 12 43 30 50 4 4 5 28 23 14 9 55 15 38 16 58 20 45 21 42 37 14 9 39 29 40 28 53 4 34 35 35 13 1 19 3 40 48 20 5 39 50 4 48 20 5 39 7 42 51 0 9 41 52 15 51 0 11 43 53 4 52 15 11 43 13 45 54 11 15 44 55 15 54 11 17 46 56 8 55 15 19 47 57 11 56 8 19 47 21 48 58 20 23 17 59 8 58 20 1 19 49 0 59 8 62 51 60 57 61 18 61 18 71 56 62 51 70 49 69 52 66 50 68 58 67 54 66 50 66 50 65 59 64 55 64 55 63 53 62 51 62 51 71 56 70 49 69 52 68 58 66 50 66 50 64 55 62 51 3 40 60 57 62 51 17 46 68 58 69 52 11 43 65 59 66 50 5 39 62 51 63 53 19 47 69 52 70 49 15 44 13 45 66 50 9 41 7 42 63 53 21 48 70 49 71 56 1 19 61 18 60 57 15 44 67 54 68 58 9 41 64 55 65 59</p>
+ </polylist>
+ </mesh>
+ </geometry>
+ <geometry id="Cylinder_006-mesh" name="Cylinder.006">
+ <mesh>
+ <source id="Cylinder_006-mesh-positions">
+ <float_array id="Cylinder_006-mesh-positions-array" count="216">-0.6937502 0.7202157 -0.1465266 -0.117956 0.122456 0.1465266 -0.2406975 0.9706001 -0.1465266 -0.04092502 0.165028 0.1465266 0.2768501 0.9609132 -0.1465266 0.04707187 0.1633808 0.1465266 0.7202157 0.6937502 -0.1465266 0.122456 0.1179561 0.1465266 0.9706003 0.2406975 -0.1465266 0.165028 0.04092496 0.1465266 0.9609132 -0.2768499 -0.1465266 0.163381 -0.04707187 0.1465266 0.6937503 -0.7202156 -0.1465266 0.1179561 -0.1224558 0.1465266 0.2406976 -0.9706001 -0.1465266 0.04092496 -0.1650279 0.1465266 -0.2768496 -0.9609132 -0.1465266 -0.04707181 -0.163381 0.1465266 -0.7202154 -0.6937506 -0.1465266 -0.1224559 -0.1179561 0.1465266 -0.9706 -0.240698 -0.1465266 -0.165028 -0.04092508 0.1465266 -0.9609134 0.2768493 -0.1465266 -0.1633809 0.04707157 0.1465266 -1.161437 1.002034 -0.1465266 -1.161437 1.002034 0.1465266 -0.2304791 1.516537 0.1465266 -0.2304791 1.516537 -0.1465266 0.2870684 1.50685 -0.1465266 0.2870684 1.50685 0.1465266 1.19812 0.9578695 0.1465266 1.19812 0.9578695 -0.1465266 1.448505 0.5048167 -0.1465266 1.448505 0.5048167 0.1465266 1.4286 -0.5586678 0.1465266 1.4286 -0.5586678 -0.1465266 1.161437 -1.002034 -0.1465266 1.161437 -1.002034 0.1465266 0.2304794 -1.516537 0.1465266 0.2304794 -1.516537 -0.1465266 -0.2870679 -1.50685 -0.1465266 -0.2870679 -1.50685 0.1465266 -1.19812 -0.95787 0.1465266 -1.19812 -0.95787 -0.1465266 -1.448505 -0.5048175 -0.1465266 -1.448505 -0.5048175 0.1465266 -1.4286 0.5586673 0.1465266 -1.4286 0.5586673 -0.1465266 -0.2406975 0.9706001 0.1465266 -0.6937502 0.7202157 0.1465266 0.2768501 0.9609132 0.1465266 0.7202157 0.6937502 0.1465266 0.9706003 0.2406975 0.1465266 0.9609132 -0.2768499 0.1465266 0.6937503 -0.7202156 0.1465266 0.2406976 -0.9706001 0.1465266 -0.2768496 -0.9609132 0.1465266 -0.7202154 -0.6937506 0.1465266 -0.9706 -0.240698 0.1465266 -0.9609134 0.2768493 0.1465266 -0.04092502 0.165028 4.503279 -0.117956 0.122456 4.503279 0.04707187 0.1633808 4.503279 0.122456 0.1179561 4.503279 0.165028 0.04092496 4.503279 0.163381 -0.04707187 4.503279 0.1179561 -0.1224558 4.503279 0.04092496 -0.1650279 4.503279 -0.04707181 -0.163381 4.503279 -0.1224559 -0.1179561 4.503279 -0.165028 -0.04092508 4.503279 -0.1633809 0.04707157 4.503279</float_array>
+ <technique_common>
+ <accessor source="#Cylinder_006-mesh-positions-array" count="72" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Cylinder_006-mesh-normals">
+ <float_array id="Cylinder_006-mesh-normals-array" count="180">0.01019328 0.5446093 0.838628 -0.4665465 0.281112 -0.8386361 0.01019328 0.5446093 -0.838628 -0.1965123 0.7924888 0.5773599 0.4767377 0.2634708 0.8386324 0.4767377 0.2634708 -0.8386324 -0.4767377 -0.2634708 -0.8386324 -0.5880461 -0.5664384 0.5773643 -0.4767377 -0.2634708 0.8386324 0.4665465 -0.281112 0.8386361 0.4665465 -0.281112 -0.8386361 0.2260238 0.7845829 -0.5773588 -0.01019328 -0.5446093 0.838628 -0.01019328 -0.5446093 -0.838628 0.7924888 0.1965123 -0.5773599 0.1965123 -0.7924888 -0.5773599 0.5664384 -0.5880461 0.5773643 -0.6127917 0.1765526 0.7702699 -0.525269 0.5453203 0.6532368 -0.4424093 0.4592865 0.7702792 -0.4665465 0.281112 0.8386361 -0.7845829 0.2260238 0.5773588 -0.5664384 0.5880461 0.5773643 0.5880461 0.5664384 -0.5773643 -0.5664384 0.5880461 -0.5773643 0.2260238 0.7845829 0.5773588 0.7845829 -0.2260238 -0.5773588 0.7924888 0.1965123 0.5773599 -0.5880461 -0.5664384 -0.5773643 0.5664384 -0.5880461 -0.5773643 -0.2260238 -0.7845829 0.5773588 -0.7845829 0.2260238 -0.5773588 -0.2260238 -0.7845829 -0.5773588 -0.7924888 -0.1965123 0.5773599 -0.1965123 0.7924888 -0.5773599 -0.7924888 -0.1965123 -0.5773599 0.1965123 -0.7924888 0.5773599 0.7845829 -0.2260238 0.5773588 0.5880461 0.5664384 0.5773643 0.1765526 0.6127917 0.7702699 -0.1534789 0.6189819 0.7702634 0.4592865 0.4424093 0.7702792 0.6189819 0.1534789 0.7702634 0.6127917 -0.1765526 0.7702699 0.1534789 -0.6189819 0.7702634 0.4424093 -0.4592865 0.7702792 -0.1765526 -0.6127917 0.7702699 -0.4592865 -0.4424093 0.7702792 -0.6189819 -0.1534789 0.7702634 -0.7349014 -0.1822299 0.6532321 0.525269 -0.5453203 0.6532368 0.209604 0.7275715 0.6532273 -0.5453203 -0.525269 0.6532368 0.5453203 0.525269 0.6532368 0.1822299 -0.7349014 0.6532321 0.7349014 0.1822299 0.6532321 -0.7275715 0.209604 0.6532273 -0.1822299 0.7349014 0.6532321 -0.209604 -0.7275715 0.6532273 0.7275571 -0.2096087 0.6532418</float_array>
+ <technique_common>
+ <accessor source="#Cylinder_006-mesh-normals-array" count="60" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Cylinder_006-mesh-vertices">
+ <input semantic="POSITION" source="#Cylinder_006-mesh-positions"/>
+ </vertices>
+ <polylist material="Material_001-material" count="140">
+ <input semantic="VERTEX" source="#Cylinder_006-mesh-vertices" offset="0"/>
+ <input semantic="NORMAL" source="#Cylinder_006-mesh-normals" offset="1"/>
+ <vcount>3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 </vcount>
+ <p>49 0 2 1 0 2 0 2 25 3 49 0 50 4 6 2 4 5 16 6 41 7 56 8 52 9 10 5 8 10 51 0 31 11 6 2 54 12 14 10 12 13 12 13 35 14 36 15 56 8 18 13 16 6 55 9 41 7 38 16 23 17 61 18 1 19 58 20 22 6 20 1 20 1 45 21 58 20 6 2 14 10 22 6 26 22 28 23 27 24 30 25 32 26 31 11 34 27 36 15 35 14 38 16 40 28 39 29 42 30 44 31 43 32 46 33 24 34 47 35 54 12 34 27 53 4 8 10 31 11 32 26 48 20 27 24 2 1 12 13 37 36 54 12 59 8 47 35 22 6 52 9 30 25 51 0 4 5 27 24 28 23 22 6 24 34 0 2 8 10 33 37 52 9 57 12 43 32 18 13 50 4 26 22 48 20 49 0 46 33 59 8 20 1 43 32 44 31 4 5 29 38 50 4 55 9 39 29 14 10 58 20 42 30 57 12 14 10 40 28 16 6 53 4 35 14 10 5 1 19 48 20 49 0 5 39 48 20 3 40 7 41 50 4 5 39 9 42 51 0 7 41 11 43 52 9 9 42 11 43 54 12 53 4 15 44 54 12 13 45 17 46 55 9 15 44 19 47 56 8 17 46 19 47 58 20 57 12 21 48 59 8 58 20 1 19 59 8 23 17 70 49 66 50 62 51 3 40 62 51 5 39 17 46 69 52 19 47 11 43 66 50 13 45 5 39 63 53 7 41 19 47 70 49 21 48 13 45 67 54 15 44 7 41 64 55 9 42 21 48 71 56 23 17 1 19 60 57 3 40 15 44 68 58 17 46 9 42 65 59 11 43 49 0 48 20 2 1 0 2 24 34 25 3 50 4 51 0 6 2 16 6 40 28 41 7 52 9 53 4 10 5 51 0 30 25 31 11 54 12 55 9 14 10 12 13 10 5 35 14 56 8 57 12 18 13 55 9 56 8 41 7 23 17 71 56 61 18 58 20 59 8 22 6 20 1 44 31 45 21 22 6 0 2 6 2 2 1 4 5 6 2 6 2 8 10 10 5 10 5 12 13 14 10 14 10 16 6 18 13 18 13 20 1 14 10 0 2 2 1 6 2 6 2 10 5 14 10 14 10 20 1 22 6 26 22 29 38 28 23 30 25 33 37 32 26 34 27 37 36 36 15 38 16 41 7 40 28 42 30 45 21 44 31 46 33 25 3 24 34 54 12 37 36 34 27 8 10 6 2 31 11 48 20 26 22 27 24 12 13 36 15 37 36 59 8 46 33 47 35 52 9 33 37 30 25 4 5 2 1 27 24 22 6 47 35 24 34 8 10 32 26 33 37 57 12 42 30 43 32 50 4 29 38 26 22 49 0 25 3 46 33 20 1 18 13 43 32 4 5 28 23 29 38 55 9 38 16 39 29 58 20 45 21 42 30 14 10 39 29 40 28 53 4 34 27 35 14 1 19 3 40 48 20 5 39 50 4 48 20 7 41 51 0 50 4 9 42 52 9 51 0 11 43 53 4 52 9 11 43 13 45 54 12 15 44 55 9 54 12 17 46 56 8 55 9 19 47 57 12 56 8 19 47 21 48 58 20 21 48 23 17 59 8 1 19 49 0 59 8 62 51 60 57 61 18 61 18 71 56 62 51 70 49 69 52 68 58 68 58 67 54 70 49 66 50 65 59 64 55 64 55 63 53 62 51 62 51 71 56 70 49 70 49 67 54 66 50 66 50 64 55 62 51 3 40 60 57 62 51 17 46 68 58 69 52 11 43 65 59 66 50 5 39 62 51 63 53 19 47 69 52 70 49 13 45 66 50 67 54 7 41 63 53 64 55 21 48 70 49 71 56 1 19 61 18 60 57 15 44 67 54 68 58 9 42 64 55 65 59</p>
+ </polylist>
+ </mesh>
+ </geometry>
+ <geometry id="Cube-mesh" name="Cube">
+ <mesh>
+ <source id="Cube-mesh-positions">
+ <float_array id="Cube-mesh-positions-array" count="24">-0.4649617 -2.207998 2.663758 -0.4649617 -2.207998 3.004 -2.199902 4.454042 2.663758 -2.199902 4.454042 3.004 1.470484 -1.703966 2.663758 1.470484 -1.703966 3.004 -0.2644557 4.958074 2.663758 -0.2644557 4.958074 3.004</float_array>
+ <technique_common>
+ <accessor source="#Cube-mesh-positions-array" count="8" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Cube-mesh-normals">
+ <float_array id="Cube-mesh-normals-array" count="33">-0.967723 -0.2520163 0 -0.252016 0.9677231 0 0.9677231 0.2520161 0 0.2520161 -0.9677231 0 0 0 -1 2.7706e-7 0 1 -0.9677231 -0.2520158 0 -0.252016 0.9677231 0 0.2520164 -0.967723 0 0 0 -1 0 0 1</float_array>
+ <technique_common>
+ <accessor source="#Cube-mesh-normals-array" count="11" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Cube-mesh-vertices">
+ <input semantic="POSITION" source="#Cube-mesh-positions"/>
+ </vertices>
+ <polylist count="12">
+ <input semantic="VERTEX" source="#Cube-mesh-vertices" offset="0"/>
+ <input semantic="NORMAL" source="#Cube-mesh-normals" offset="1"/>
+ <vcount>3 3 3 3 3 3 3 3 3 3 3 3 </vcount>
+ <p>3 0 0 0 1 0 7 1 2 1 3 1 5 2 6 2 7 2 1 3 4 3 5 3 2 4 4 4 0 4 5 5 3 5 1 5 3 6 2 6 0 6 7 7 6 7 2 7 5 2 4 2 6 2 1 8 0 8 4 8 2 9 6 9 4 9 5 10 7 10 3 10</p>
+ </polylist>
+ </mesh>
+ </geometry>
+ </library_geometries>
+ <library_animations>
+ <animation id="GearTop_rotation_euler_X">
+ <source id="GearTop_rotation_euler_X-input">
+ <float_array id="GearTop_rotation_euler_X-input-array" count="4">0 0.8333333 1.666667 2.5</float_array>
+ <technique_common>
+ <accessor source="#GearTop_rotation_euler_X-input-array" count="4" stride="1">
+ <param name="TIME" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="GearTop_rotation_euler_X-output">
+ <float_array id="GearTop_rotation_euler_X-output-array" count="4">0 0 0 0</float_array>
+ <technique_common>
+ <accessor source="#GearTop_rotation_euler_X-output-array" count="4" stride="1">
+ <param name="ANGLE" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="GearTop_rotation_euler_X-interpolation">
+ <Name_array id="GearTop_rotation_euler_X-interpolation-array" count="4">LINEAR LINEAR LINEAR LINEAR</Name_array>
+ <technique_common>
+ <accessor source="#GearTop_rotation_euler_X-interpolation-array" count="4" stride="1">
+ <param name="INTERPOLATION" type="name"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <sampler id="GearTop_rotation_euler_X-sampler">
+ <input semantic="INPUT" source="#GearTop_rotation_euler_X-input"/>
+ <input semantic="OUTPUT" source="#GearTop_rotation_euler_X-output"/>
+ <input semantic="INTERPOLATION" source="#GearTop_rotation_euler_X-interpolation"/>
+ </sampler>
+ <channel source="#GearTop_rotation_euler_X-sampler" target="GearTop/rotationX.ANGLE"/>
+ </animation>
+ <animation id="GearTop_rotation_euler_Y">
+ <source id="GearTop_rotation_euler_Y-input">
+ <float_array id="GearTop_rotation_euler_Y-input-array" count="4">0 0.8333333 1.666667 2.5</float_array>
+ <technique_common>
+ <accessor source="#GearTop_rotation_euler_Y-input-array" count="4" stride="1">
+ <param name="TIME" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="GearTop_rotation_euler_Y-output">
+ <float_array id="GearTop_rotation_euler_Y-output-array" count="4">0 0 0 0</float_array>
+ <technique_common>
+ <accessor source="#GearTop_rotation_euler_Y-output-array" count="4" stride="1">
+ <param name="ANGLE" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="GearTop_rotation_euler_Y-interpolation">
+ <Name_array id="GearTop_rotation_euler_Y-interpolation-array" count="4">LINEAR LINEAR LINEAR LINEAR</Name_array>
+ <technique_common>
+ <accessor source="#GearTop_rotation_euler_Y-interpolation-array" count="4" stride="1">
+ <param name="INTERPOLATION" type="name"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <sampler id="GearTop_rotation_euler_Y-sampler">
+ <input semantic="INPUT" source="#GearTop_rotation_euler_Y-input"/>
+ <input semantic="OUTPUT" source="#GearTop_rotation_euler_Y-output"/>
+ <input semantic="INTERPOLATION" source="#GearTop_rotation_euler_Y-interpolation"/>
+ </sampler>
+ <channel source="#GearTop_rotation_euler_Y-sampler" target="GearTop/rotationY.ANGLE"/>
+ </animation>
+ <animation id="GearTop_rotation_euler_Z">
+ <source id="GearTop_rotation_euler_Z-input">
+ <float_array id="GearTop_rotation_euler_Z-input-array" count="4">0 0.8333333 1.666667 2.5</float_array>
+ <technique_common>
+ <accessor source="#GearTop_rotation_euler_Z-input-array" count="4" stride="1">
+ <param name="TIME" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="GearTop_rotation_euler_Z-output">
+ <float_array id="GearTop_rotation_euler_Z-output-array" count="4">0 -120 -240 -360</float_array>
+ <technique_common>
+ <accessor source="#GearTop_rotation_euler_Z-output-array" count="4" stride="1">
+ <param name="ANGLE" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="GearTop_rotation_euler_Z-interpolation">
+ <Name_array id="GearTop_rotation_euler_Z-interpolation-array" count="4">LINEAR LINEAR LINEAR LINEAR</Name_array>
+ <technique_common>
+ <accessor source="#GearTop_rotation_euler_Z-interpolation-array" count="4" stride="1">
+ <param name="INTERPOLATION" type="name"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <sampler id="GearTop_rotation_euler_Z-sampler">
+ <input semantic="INPUT" source="#GearTop_rotation_euler_Z-input"/>
+ <input semantic="OUTPUT" source="#GearTop_rotation_euler_Z-output"/>
+ <input semantic="INTERPOLATION" source="#GearTop_rotation_euler_Z-interpolation"/>
+ </sampler>
+ <channel source="#GearTop_rotation_euler_Z-sampler" target="GearTop/rotationZ.ANGLE"/>
+ </animation>
+ <animation id="GearLeft_rotation_euler_X">
+ <source id="GearLeft_rotation_euler_X-input">
+ <float_array id="GearLeft_rotation_euler_X-input-array" count="4">0 0.8333333 1.666667 2.458333</float_array>
+ <technique_common>
+ <accessor source="#GearLeft_rotation_euler_X-input-array" count="4" stride="1">
+ <param name="TIME" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="GearLeft_rotation_euler_X-output">
+ <float_array id="GearLeft_rotation_euler_X-output-array" count="4">0 -122.0339 -244.0678 -360</float_array>
+ <technique_common>
+ <accessor source="#GearLeft_rotation_euler_X-output-array" count="4" stride="1">
+ <param name="ANGLE" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="GearLeft_rotation_euler_X-interpolation">
+ <Name_array id="GearLeft_rotation_euler_X-interpolation-array" count="4">LINEAR LINEAR LINEAR LINEAR</Name_array>
+ <technique_common>
+ <accessor source="#GearLeft_rotation_euler_X-interpolation-array" count="4" stride="1">
+ <param name="INTERPOLATION" type="name"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <sampler id="GearLeft_rotation_euler_X-sampler">
+ <input semantic="INPUT" source="#GearLeft_rotation_euler_X-input"/>
+ <input semantic="OUTPUT" source="#GearLeft_rotation_euler_X-output"/>
+ <input semantic="INTERPOLATION" source="#GearLeft_rotation_euler_X-interpolation"/>
+ </sampler>
+ <channel source="#GearLeft_rotation_euler_X-sampler" target="GearLeft/rotationX.ANGLE"/>
+ </animation>
+ <animation id="GearLeft_rotation_euler_Y">
+ <source id="GearLeft_rotation_euler_Y-input">
+ <float_array id="GearLeft_rotation_euler_Y-input-array" count="4">0 0.8333333 1.666667 2.458333</float_array>
+ <technique_common>
+ <accessor source="#GearLeft_rotation_euler_Y-input-array" count="4" stride="1">
+ <param name="TIME" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="GearLeft_rotation_euler_Y-output">
+ <float_array id="GearLeft_rotation_euler_Y-output-array" count="4">0 0 0 0</float_array>
+ <technique_common>
+ <accessor source="#GearLeft_rotation_euler_Y-output-array" count="4" stride="1">
+ <param name="ANGLE" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="GearLeft_rotation_euler_Y-interpolation">
+ <Name_array id="GearLeft_rotation_euler_Y-interpolation-array" count="4">LINEAR LINEAR LINEAR LINEAR</Name_array>
+ <technique_common>
+ <accessor source="#GearLeft_rotation_euler_Y-interpolation-array" count="4" stride="1">
+ <param name="INTERPOLATION" type="name"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <sampler id="GearLeft_rotation_euler_Y-sampler">
+ <input semantic="INPUT" source="#GearLeft_rotation_euler_Y-input"/>
+ <input semantic="OUTPUT" source="#GearLeft_rotation_euler_Y-output"/>
+ <input semantic="INTERPOLATION" source="#GearLeft_rotation_euler_Y-interpolation"/>
+ </sampler>
+ <channel source="#GearLeft_rotation_euler_Y-sampler" target="GearLeft/rotationY.ANGLE"/>
+ </animation>
+ <animation id="GearLeft_rotation_euler_Z">
+ <source id="GearLeft_rotation_euler_Z-input">
+ <float_array id="GearLeft_rotation_euler_Z-input-array" count="4">0 0.8333333 1.666667 2.458333</float_array>
+ <technique_common>
+ <accessor source="#GearLeft_rotation_euler_Z-input-array" count="4" stride="1">
+ <param name="TIME" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="GearLeft_rotation_euler_Z-output">
+ <float_array id="GearLeft_rotation_euler_Z-output-array" count="4">0 0 0 0</float_array>
+ <technique_common>
+ <accessor source="#GearLeft_rotation_euler_Z-output-array" count="4" stride="1">
+ <param name="ANGLE" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="GearLeft_rotation_euler_Z-interpolation">
+ <Name_array id="GearLeft_rotation_euler_Z-interpolation-array" count="4">LINEAR LINEAR LINEAR LINEAR</Name_array>
+ <technique_common>
+ <accessor source="#GearLeft_rotation_euler_Z-interpolation-array" count="4" stride="1">
+ <param name="INTERPOLATION" type="name"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <sampler id="GearLeft_rotation_euler_Z-sampler">
+ <input semantic="INPUT" source="#GearLeft_rotation_euler_Z-input"/>
+ <input semantic="OUTPUT" source="#GearLeft_rotation_euler_Z-output"/>
+ <input semantic="INTERPOLATION" source="#GearLeft_rotation_euler_Z-interpolation"/>
+ </sampler>
+ <channel source="#GearLeft_rotation_euler_Z-sampler" target="GearLeft/rotationZ.ANGLE"/>
+ </animation>
+ <animation id="GearRight_rotation_euler_X">
+ <source id="GearRight_rotation_euler_X-input">
+ <float_array id="GearRight_rotation_euler_X-input-array" count="4">0.04166662 0.8333333 1.666667 2.5</float_array>
+ <technique_common>
+ <accessor source="#GearRight_rotation_euler_X-input-array" count="4" stride="1">
+ <param name="TIME" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="GearRight_rotation_euler_X-output">
+ <float_array id="GearRight_rotation_euler_X-output-array" count="4">0 115.9322 237.9661 360</float_array>
+ <technique_common>
+ <accessor source="#GearRight_rotation_euler_X-output-array" count="4" stride="1">
+ <param name="ANGLE" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="GearRight_rotation_euler_X-interpolation">
+ <Name_array id="GearRight_rotation_euler_X-interpolation-array" count="4">LINEAR LINEAR LINEAR LINEAR</Name_array>
+ <technique_common>
+ <accessor source="#GearRight_rotation_euler_X-interpolation-array" count="4" stride="1">
+ <param name="INTERPOLATION" type="name"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <sampler id="GearRight_rotation_euler_X-sampler">
+ <input semantic="INPUT" source="#GearRight_rotation_euler_X-input"/>
+ <input semantic="OUTPUT" source="#GearRight_rotation_euler_X-output"/>
+ <input semantic="INTERPOLATION" source="#GearRight_rotation_euler_X-interpolation"/>
+ </sampler>
+ <channel source="#GearRight_rotation_euler_X-sampler" target="GearRight/rotationX.ANGLE"/>
+ </animation>
+ <animation id="GearRight_rotation_euler_Y">
+ <source id="GearRight_rotation_euler_Y-input">
+ <float_array id="GearRight_rotation_euler_Y-input-array" count="4">0.04166662 0.8333333 1.666667 2.5</float_array>
+ <technique_common>
+ <accessor source="#GearRight_rotation_euler_Y-input-array" count="4" stride="1">
+ <param name="TIME" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="GearRight_rotation_euler_Y-output">
+ <float_array id="GearRight_rotation_euler_Y-output-array" count="4">0 0 0 0</float_array>
+ <technique_common>
+ <accessor source="#GearRight_rotation_euler_Y-output-array" count="4" stride="1">
+ <param name="ANGLE" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="GearRight_rotation_euler_Y-interpolation">
+ <Name_array id="GearRight_rotation_euler_Y-interpolation-array" count="4">LINEAR LINEAR LINEAR LINEAR</Name_array>
+ <technique_common>
+ <accessor source="#GearRight_rotation_euler_Y-interpolation-array" count="4" stride="1">
+ <param name="INTERPOLATION" type="name"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <sampler id="GearRight_rotation_euler_Y-sampler">
+ <input semantic="INPUT" source="#GearRight_rotation_euler_Y-input"/>
+ <input semantic="OUTPUT" source="#GearRight_rotation_euler_Y-output"/>
+ <input semantic="INTERPOLATION" source="#GearRight_rotation_euler_Y-interpolation"/>
+ </sampler>
+ <channel source="#GearRight_rotation_euler_Y-sampler" target="GearRight/rotationY.ANGLE"/>
+ </animation>
+ <animation id="GearRight_rotation_euler_Z">
+ <source id="GearRight_rotation_euler_Z-input">
+ <float_array id="GearRight_rotation_euler_Z-input-array" count="4">0.04166662 0.8333333 1.666667 2.5</float_array>
+ <technique_common>
+ <accessor source="#GearRight_rotation_euler_Z-input-array" count="4" stride="1">
+ <param name="TIME" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="GearRight_rotation_euler_Z-output">
+ <float_array id="GearRight_rotation_euler_Z-output-array" count="4">0 0 0 0</float_array>
+ <technique_common>
+ <accessor source="#GearRight_rotation_euler_Z-output-array" count="4" stride="1">
+ <param name="ANGLE" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="GearRight_rotation_euler_Z-interpolation">
+ <Name_array id="GearRight_rotation_euler_Z-interpolation-array" count="4">LINEAR LINEAR LINEAR LINEAR</Name_array>
+ <technique_common>
+ <accessor source="#GearRight_rotation_euler_Z-interpolation-array" count="4" stride="1">
+ <param name="INTERPOLATION" type="name"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <sampler id="GearRight_rotation_euler_Z-sampler">
+ <input semantic="INPUT" source="#GearRight_rotation_euler_Z-input"/>
+ <input semantic="OUTPUT" source="#GearRight_rotation_euler_Z-output"/>
+ <input semantic="INTERPOLATION" source="#GearRight_rotation_euler_Z-interpolation"/>
+ </sampler>
+ <channel source="#GearRight_rotation_euler_Z-sampler" target="GearRight/rotationZ.ANGLE"/>
+ </animation>
+ <animation id="GearTop_001_rotation_euler_X">
+ <source id="GearTop_001_rotation_euler_X-input">
+ <float_array id="GearTop_001_rotation_euler_X-input-array" count="4">0 0.8333333 1.666667 2.5</float_array>
+ <technique_common>
+ <accessor source="#GearTop_001_rotation_euler_X-input-array" count="4" stride="1">
+ <param name="TIME" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="GearTop_001_rotation_euler_X-output">
+ <float_array id="GearTop_001_rotation_euler_X-output-array" count="4">0 0 0 0</float_array>
+ <technique_common>
+ <accessor source="#GearTop_001_rotation_euler_X-output-array" count="4" stride="1">
+ <param name="ANGLE" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="GearTop_001_rotation_euler_X-interpolation">
+ <Name_array id="GearTop_001_rotation_euler_X-interpolation-array" count="4">LINEAR LINEAR LINEAR LINEAR</Name_array>
+ <technique_common>
+ <accessor source="#GearTop_001_rotation_euler_X-interpolation-array" count="4" stride="1">
+ <param name="INTERPOLATION" type="name"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <sampler id="GearTop_001_rotation_euler_X-sampler">
+ <input semantic="INPUT" source="#GearTop_001_rotation_euler_X-input"/>
+ <input semantic="OUTPUT" source="#GearTop_001_rotation_euler_X-output"/>
+ <input semantic="INTERPOLATION" source="#GearTop_001_rotation_euler_X-interpolation"/>
+ </sampler>
+ <channel source="#GearTop_001_rotation_euler_X-sampler" target="GearTop_001/rotationX.ANGLE"/>
+ </animation>
+ <animation id="GearTop_001_rotation_euler_Y">
+ <source id="GearTop_001_rotation_euler_Y-input">
+ <float_array id="GearTop_001_rotation_euler_Y-input-array" count="4">0 0.8333333 1.666667 2.5</float_array>
+ <technique_common>
+ <accessor source="#GearTop_001_rotation_euler_Y-input-array" count="4" stride="1">
+ <param name="TIME" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="GearTop_001_rotation_euler_Y-output">
+ <float_array id="GearTop_001_rotation_euler_Y-output-array" count="4">0 0 0 0</float_array>
+ <technique_common>
+ <accessor source="#GearTop_001_rotation_euler_Y-output-array" count="4" stride="1">
+ <param name="ANGLE" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="GearTop_001_rotation_euler_Y-interpolation">
+ <Name_array id="GearTop_001_rotation_euler_Y-interpolation-array" count="4">LINEAR LINEAR LINEAR LINEAR</Name_array>
+ <technique_common>
+ <accessor source="#GearTop_001_rotation_euler_Y-interpolation-array" count="4" stride="1">
+ <param name="INTERPOLATION" type="name"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <sampler id="GearTop_001_rotation_euler_Y-sampler">
+ <input semantic="INPUT" source="#GearTop_001_rotation_euler_Y-input"/>
+ <input semantic="OUTPUT" source="#GearTop_001_rotation_euler_Y-output"/>
+ <input semantic="INTERPOLATION" source="#GearTop_001_rotation_euler_Y-interpolation"/>
+ </sampler>
+ <channel source="#GearTop_001_rotation_euler_Y-sampler" target="GearTop_001/rotationY.ANGLE"/>
+ </animation>
+ <animation id="GearTop_001_rotation_euler_Z">
+ <source id="GearTop_001_rotation_euler_Z-input">
+ <float_array id="GearTop_001_rotation_euler_Z-input-array" count="4">0 0.8333333 1.666667 2.5</float_array>
+ <technique_common>
+ <accessor source="#GearTop_001_rotation_euler_Z-input-array" count="4" stride="1">
+ <param name="TIME" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="GearTop_001_rotation_euler_Z-output">
+ <float_array id="GearTop_001_rotation_euler_Z-output-array" count="4">0 -120 -240 -360</float_array>
+ <technique_common>
+ <accessor source="#GearTop_001_rotation_euler_Z-output-array" count="4" stride="1">
+ <param name="ANGLE" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="GearTop_001_rotation_euler_Z-interpolation">
+ <Name_array id="GearTop_001_rotation_euler_Z-interpolation-array" count="4">LINEAR LINEAR LINEAR LINEAR</Name_array>
+ <technique_common>
+ <accessor source="#GearTop_001_rotation_euler_Z-interpolation-array" count="4" stride="1">
+ <param name="INTERPOLATION" type="name"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <sampler id="GearTop_001_rotation_euler_Z-sampler">
+ <input semantic="INPUT" source="#GearTop_001_rotation_euler_Z-input"/>
+ <input semantic="OUTPUT" source="#GearTop_001_rotation_euler_Z-output"/>
+ <input semantic="INTERPOLATION" source="#GearTop_001_rotation_euler_Z-interpolation"/>
+ </sampler>
+ <channel source="#GearTop_001_rotation_euler_Z-sampler" target="GearTop_001/rotationZ.ANGLE"/>
+ </animation>
+ <animation id="Cube_rotation_euler_X">
+ <source id="Cube_rotation_euler_X-input">
+ <float_array id="Cube_rotation_euler_X-input-array" count="4">0 0.8333333 1.666667 2.5</float_array>
+ <technique_common>
+ <accessor source="#Cube_rotation_euler_X-input-array" count="4" stride="1">
+ <param name="TIME" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Cube_rotation_euler_X-output">
+ <float_array id="Cube_rotation_euler_X-output-array" count="4">0 0 0 0</float_array>
+ <technique_common>
+ <accessor source="#Cube_rotation_euler_X-output-array" count="4" stride="1">
+ <param name="ANGLE" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Cube_rotation_euler_X-interpolation">
+ <Name_array id="Cube_rotation_euler_X-interpolation-array" count="4">LINEAR LINEAR LINEAR LINEAR</Name_array>
+ <technique_common>
+ <accessor source="#Cube_rotation_euler_X-interpolation-array" count="4" stride="1">
+ <param name="INTERPOLATION" type="name"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <sampler id="Cube_rotation_euler_X-sampler">
+ <input semantic="INPUT" source="#Cube_rotation_euler_X-input"/>
+ <input semantic="OUTPUT" source="#Cube_rotation_euler_X-output"/>
+ <input semantic="INTERPOLATION" source="#Cube_rotation_euler_X-interpolation"/>
+ </sampler>
+ <channel source="#Cube_rotation_euler_X-sampler" target="Cube/rotationX.ANGLE"/>
+ </animation>
+ <animation id="Cube_rotation_euler_Y">
+ <source id="Cube_rotation_euler_Y-input">
+ <float_array id="Cube_rotation_euler_Y-input-array" count="4">0 0.8333333 1.666667 2.5</float_array>
+ <technique_common>
+ <accessor source="#Cube_rotation_euler_Y-input-array" count="4" stride="1">
+ <param name="TIME" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Cube_rotation_euler_Y-output">
+ <float_array id="Cube_rotation_euler_Y-output-array" count="4">0 0 0 0</float_array>
+ <technique_common>
+ <accessor source="#Cube_rotation_euler_Y-output-array" count="4" stride="1">
+ <param name="ANGLE" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Cube_rotation_euler_Y-interpolation">
+ <Name_array id="Cube_rotation_euler_Y-interpolation-array" count="4">LINEAR LINEAR LINEAR LINEAR</Name_array>
+ <technique_common>
+ <accessor source="#Cube_rotation_euler_Y-interpolation-array" count="4" stride="1">
+ <param name="INTERPOLATION" type="name"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <sampler id="Cube_rotation_euler_Y-sampler">
+ <input semantic="INPUT" source="#Cube_rotation_euler_Y-input"/>
+ <input semantic="OUTPUT" source="#Cube_rotation_euler_Y-output"/>
+ <input semantic="INTERPOLATION" source="#Cube_rotation_euler_Y-interpolation"/>
+ </sampler>
+ <channel source="#Cube_rotation_euler_Y-sampler" target="Cube/rotationY.ANGLE"/>
+ </animation>
+ <animation id="Cube_rotation_euler_Z">
+ <source id="Cube_rotation_euler_Z-input">
+ <float_array id="Cube_rotation_euler_Z-input-array" count="4">0 0.8333333 1.666667 2.5</float_array>
+ <technique_common>
+ <accessor source="#Cube_rotation_euler_Z-input-array" count="4" stride="1">
+ <param name="TIME" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Cube_rotation_euler_Z-output">
+ <float_array id="Cube_rotation_euler_Z-output-array" count="4">0 -120 -240 -360</float_array>
+ <technique_common>
+ <accessor source="#Cube_rotation_euler_Z-output-array" count="4" stride="1">
+ <param name="ANGLE" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Cube_rotation_euler_Z-interpolation">
+ <Name_array id="Cube_rotation_euler_Z-interpolation-array" count="4">LINEAR LINEAR LINEAR LINEAR</Name_array>
+ <technique_common>
+ <accessor source="#Cube_rotation_euler_Z-interpolation-array" count="4" stride="1">
+ <param name="INTERPOLATION" type="name"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <sampler id="Cube_rotation_euler_Z-sampler">
+ <input semantic="INPUT" source="#Cube_rotation_euler_Z-input"/>
+ <input semantic="OUTPUT" source="#Cube_rotation_euler_Z-output"/>
+ <input semantic="INTERPOLATION" source="#Cube_rotation_euler_Z-interpolation"/>
+ </sampler>
+ <channel source="#Cube_rotation_euler_Z-sampler" target="Cube/rotationZ.ANGLE"/>
+ </animation>
+ </library_animations>
+ <library_controllers/>
+ <library_visual_scenes>
+ <visual_scene id="Scene" name="Scene">
+ <node id="GearBottom" name="GearBottom" type="NODE">
+ <translate sid="location">0 0 2.19514</translate>
+ <rotate sid="rotationZ">0 0 1 0</rotate>
+ <rotate sid="rotationY">0 1 0 0</rotate>
+ <rotate sid="rotationX">1 0 0 180</rotate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#Cylinder_005-mesh" name="GearBottom">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="Material_001-material" target="#Material_001-material"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <node id="Cube" name="Cube" type="NODE">
+ <translate sid="location">0 0 3.419647</translate>
+ <rotate sid="rotationZ">0 0 1 0</rotate>
+ <rotate sid="rotationY">0 1 0 0</rotate>
+ <rotate sid="rotationX">1 0 0 0</rotate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#Cube-mesh" name="Cube"/>
+ <node id="GearTop" name="GearTop" type="NODE">
+ <translate sid="location">0 0 1.179928</translate>
+ <rotate sid="rotationZ">0 0 1 0</rotate>
+ <rotate sid="rotationY">0 1 0 0</rotate>
+ <rotate sid="rotationX">1 0 0 0</rotate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#Cylinder_001-mesh" name="GearTop">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="Material_001-material" target="#Material_001-material"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <node id="GearLeft" name="GearLeft" type="NODE">
+ <translate sid="location">-1.1934 0 -0.01806307</translate>
+ <rotate sid="rotationZ">0 0 1 0</rotate>
+ <rotate sid="rotationY">0 1 0 0</rotate>
+ <rotate sid="rotationX">1 0 0 0</rotate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#Cylinder_003-mesh" name="GearLeft">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="Material_002-material" target="#Material_002-material"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <node id="GearRight" name="GearRight" type="NODE">
+ <translate sid="location">1.176492 0 -0.01806307</translate>
+ <rotate sid="rotationZ">0 0 1 0</rotate>
+ <rotate sid="rotationY">0 1 0 0</rotate>
+ <rotate sid="rotationX">1 0 0 0</rotate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#Cylinder_004-mesh" name="GearRight">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="Material-material" target="#Material-material"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <node id="GearTop_001" name="GearTop_001" type="NODE">
+ <translate sid="location">-0.6745979 2.553027 -1.187106</translate>
+ <rotate sid="rotationZ">0 0 1 0</rotate>
+ <rotate sid="rotationY">0 1 0 0</rotate>
+ <rotate sid="rotationX">1 0 0 0</rotate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#Cylinder_006-mesh" name="GearTop_001">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="Material_001-material" target="#Material_001-material"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ </node>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_visual_scene url="#Scene"/>
+ </scene>
+</COLLADA> \ No newline at end of file
diff --git a/tests/manual/anim-viewer/main.cpp b/tests/manual/anim-viewer/main.cpp
new file mode 100644
index 000000000..4110cca0f
--- /dev/null
+++ b/tests/manual/anim-viewer/main.cpp
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <Qt3DQuickExtras/qt3dquickwindow.h>
+
+#include <QGuiApplication>
+#include <QQuickView>
+
+int main(int argc, char* argv[])
+{
+ QGuiApplication app(argc, argv);
+ QQuickView view;
+
+ view.setSource(QUrl("qrc:/main.qml"));
+ view.show();
+
+ return app.exec();
+}
diff --git a/tests/manual/anim-viewer/main.qml b/tests/manual/anim-viewer/main.qml
new file mode 100644
index 000000000..95a4900e3
--- /dev/null
+++ b/tests/manual/anim-viewer/main.qml
@@ -0,0 +1,240 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0 as Quick
+import QtQuick.Layouts 1.3
+import QtQuick.Controls 1.4
+import QtQuick.Controls.Styles 1.4
+
+import Qt3D.Core 2.0
+import Qt3D.Render 2.0
+import Qt3D.Input 2.0
+import Qt3D.Extras 2.2
+import QtQuick.Scene3D 2.0
+
+
+Quick.Item {
+
+ width: 1250
+ height: 900
+
+ ColumnLayout {
+
+ anchors.fill: parent
+ anchors.margins: 0
+
+ Quick.Rectangle {
+ id: background
+ width: 1250
+ height: 700
+
+ color: "red"
+
+ Scene3D {
+
+ anchors.fill: parent
+ multisample: true
+ focus: true
+
+ aspects: ["input", "logic"]
+
+ Entity {
+ components: [
+ RenderSettings {
+ activeFrameGraph: ForwardRenderer {
+ clearColor: Qt.rgba(0, 0.5, 1, 1)
+ camera: camera
+ }
+ },
+ // Event Source will be set by the Qt3DQuickWindow
+ InputSettings { }
+ ]
+
+ Camera {
+ id: camera
+ projectionType: CameraLens.PerspectiveProjection
+ fieldOfView: 45
+ aspectRatio: 16/9
+ nearPlane : 0.1
+ farPlane : 1000.0
+ position: Qt.vector3d( 0.0, 1.0, 10.0 )
+ upVector: Qt.vector3d( 0.0, 1.0, 0.0 )
+ viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 )
+ }
+
+ FirstPersonCameraController {
+ camera: camera
+ }
+
+ Entity {
+ id: scene2
+ components: [
+ Transform {
+ scale: 0.2
+ translation: Qt.vector3d(0.0, 0.0, 0.0)
+ },
+ SceneLoader {
+ id: animEntity
+ source: "qrc:/assets/gears.dae"
+
+ AnimationController {
+ id: animator
+ property bool initialized : false
+ onPositionChanged: {
+ slider.value = position
+ }
+ }
+ Quick.PropertyAnimation {
+ id: animPosition
+ target: animator
+ property: "position"
+ loops: Quick.Animation.Infinite
+ from: 0.0
+ }
+ onStatusChanged: {
+ console.log(status)
+ if (status === SceneLoader.Ready) {
+
+ animator.entity = null
+ animator.entity = scene2
+ animator.activeAnimationGroup = 0
+ var group = animator.getGroup(0)
+ animPosition.to = group.duration
+ animPosition.duration = group.duration * 1000
+ slider.maximumValue = group.duration
+
+ var animList = []
+ var groups = animator.animationGroups
+ for (var i = 0; i < groups.length; i++) {
+ if (groups[i].name === "")
+ groups[i].name = "UnnamedAnim" + i;
+ animList.push(groups[i].name)
+ }
+ comboBox.model = animList
+
+ animator.initialized = true
+ comboBox.currentIndex = 0
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+
+ ComboBox {
+ id: animationSelector
+ anchors.topMargin: 10
+ anchors.top: background.bottom
+ implicitWidth: 400
+ model: [ "Gears", "Blend Shape" ]
+ onCurrentIndexChanged: {
+
+ if (animPosition.running) {
+ animPosition.stop()
+ animator.position = 0
+ slider.value = 0
+ }
+
+ if (currentText === "Gears" && animEntity.source !== "qrc:/assets/gears.dae")
+ animEntity.source = "qrc:/assets/gears.dae"
+ else if (currentText === "Blend Shape"
+ && animEntity.source !== "qrc:/assets/blendshapeanimation.dae") {
+ animEntity.source = "qrc:/assets/blendshapeanimation.dae"
+ }
+ }
+ }
+
+ ComboBox {
+ id: comboBox
+ anchors.topMargin: 10
+ anchors.top: animationSelector.bottom
+ implicitWidth: 400
+ onCurrentIndexChanged: {
+ if (animator.initialized) {
+ animator.activeAnimationGroup = currentIndex
+ var group = animator.getGroup(currentIndex)
+ animPosition.to = group.duration
+ animPosition.duration = group.duration * 1000
+ slider.maximumValue = group.duration
+ }
+ }
+ }
+
+ RowLayout {
+ anchors.left: parent.left
+
+ Button {
+ text: "play"
+ onClicked: {
+ if (!animPosition.running || animPosition.paused)
+ animPosition.start()
+ }
+ }
+ Button {
+ text: "stop"
+ onClicked: {
+ if (animPosition.running) {
+ animPosition.stop()
+ animator.position = 0
+ slider.value = 0
+ }
+ }
+ }
+ Button {
+ text: "pause"
+ onClicked: {
+ if (!animPosition.paused && animPosition.running)
+ animPosition.pause()
+ }
+ }
+ }
+ Slider {
+ id: slider
+ anchors.bottomMargin: 10
+ anchors.left: parent.left
+ anchors.right: parent.right
+ value: 0.0
+ onValueChanged: {
+ if (pressed) {
+ animPosition.stop()
+ animator.position = value
+ }
+ }
+ }
+ }
+}
diff --git a/tests/manual/anim-viewer/qml.qrc b/tests/manual/anim-viewer/qml.qrc
new file mode 100644
index 000000000..d6fe69605
--- /dev/null
+++ b/tests/manual/anim-viewer/qml.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ <file>assets/gears.dae</file>
+ <file>assets/blendshapeanimation.dae</file>
+ </qresource>
+</RCC>
diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro
index a2ca61758..0c42b72f0 100644
--- a/tests/manual/manual.pro
+++ b/tests/manual/manual.pro
@@ -38,7 +38,9 @@ SUBDIRS += \
rendercapture-qml \
additional-attributes-qml \
dynamic-model-loader-qml \
- animation-keyframe-simple
+ animation-keyframe-simple \
+ mesh-morphing \
+ anim-viewer
qtHaveModule(widgets): {
SUBDIRS += \
diff --git a/tests/manual/mesh-morphing/main.cpp b/tests/manual/mesh-morphing/main.cpp
new file mode 100644
index 000000000..4ae791181
--- /dev/null
+++ b/tests/manual/mesh-morphing/main.cpp
@@ -0,0 +1,180 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QPropertyAnimation>
+
+#include <Qt3DInput/QInputAspect>
+
+#include <Qt3DRender/qcamera.h>
+#include <Qt3DExtras/qcylindermesh.h>
+#include <Qt3DExtras/QPhongMaterial>
+#include <Qt3DExtras/QMorphPhongMaterial>
+#include <Qt3DExtras/QVertexBlendAnimation>
+#include <Qt3DExtras/QMorphTarget>
+#include <Qt3DExtras/QCylinderGeometry>
+
+#include <Qt3DCore/qentity.h>
+#include <Qt3DCore/qtransform.h>
+#include <Qt3DCore/qaspectengine.h>
+
+#include <Qt3DExtras/qt3dwindow.h>
+#include <Qt3DExtras/QForwardRenderer>
+#include <Qt3DExtras/qfirstpersoncameracontroller.h>
+
+int main(int argc, char **argv)
+{
+ QGuiApplication app(argc, argv);
+ Qt3DExtras::Qt3DWindow view;
+
+ // Root entity
+ Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity();
+
+ // Camera
+ Qt3DRender::QCamera *camera = view.camera();
+ camera->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f);
+ camera->setPosition(QVector3D(0, 2, 20.0f));
+ camera->setUpVector(QVector3D(0, 1, 0));
+ camera->setViewCenter(QVector3D(0, 0, 0));
+
+ // For camera controls
+ Qt3DExtras::QFirstPersonCameraController *cameraController
+ = new Qt3DExtras::QFirstPersonCameraController(rootEntity);
+ cameraController->setCamera(camera);
+
+ view.defaultFrameGraph()->setCamera(camera);
+ view.defaultFrameGraph()->setClearColor(Qt::gray);
+
+ // Transform for mesh
+ Qt3DCore::QTransform *transform = new Qt3DCore::QTransform;
+ transform->setTranslation(QVector3D(0,-1,-1));
+
+ // Base mesh to morph
+ Qt3DExtras::QCylinderMesh *mesh = new Qt3DExtras::QCylinderMesh(rootEntity);
+ mesh->setRings(6);
+ mesh->setSlices(20);
+
+ // create morh targets from geometry
+ Qt3DExtras::QCylinderGeometry *cylinder1 = new Qt3DExtras::QCylinderGeometry(rootEntity);
+ Qt3DExtras::QCylinderGeometry *cylinder2 = new Qt3DExtras::QCylinderGeometry(rootEntity);
+ Qt3DExtras::QCylinderGeometry *cylinder3 = new Qt3DExtras::QCylinderGeometry(rootEntity);
+
+ cylinder1->setRings(6);
+ cylinder1->setSlices(20);
+ cylinder1->setLength(2.0f);
+ cylinder1->setRadius(1.0f);
+
+ cylinder2->setRings(6);
+ cylinder2->setSlices(20);
+ cylinder2->setLength(1.0f);
+ cylinder2->setRadius(5.0f);
+
+ cylinder3->setRings(6);
+ cylinder3->setSlices(20);
+ cylinder3->setLength(9.0f);
+ cylinder3->setRadius(1.0f);
+
+ QStringList attributes;
+ attributes.push_back(Qt3DRender::QAttribute::defaultPositionAttributeName());
+ attributes.push_back(Qt3DRender::QAttribute::defaultNormalAttributeName());
+
+ QVector<Qt3DExtras::QMorphTarget*> morphTargets;
+ morphTargets.push_back(Qt3DExtras::QMorphTarget::fromGeometry(cylinder1, attributes));
+ morphTargets.push_back(Qt3DExtras::QMorphTarget::fromGeometry(cylinder2, attributes));
+ morphTargets.push_back(Qt3DExtras::QMorphTarget::fromGeometry(cylinder3, attributes));
+ morphTargets.push_back(morphTargets.first());
+
+ Qt3DExtras::QVertexBlendAnimation *animation = new Qt3DExtras::QVertexBlendAnimation;
+ QVector<float> times;
+ times.push_back(0.0f);
+ times.push_back(5.0f);
+ times.push_back(8.0f);
+ times.push_back(12.0f);
+
+ animation->setTargetPositions(times);
+ animation->setTarget(mesh);
+ animation->setMorphTargets(morphTargets);
+
+ // Material
+ Qt3DExtras::QMorphPhongMaterial *material = new Qt3DExtras::QMorphPhongMaterial(rootEntity);
+ material->setDiffuse(Qt::red);
+
+ QObject::connect(animation, &Qt3DExtras::QVertexBlendAnimation::interpolatorChanged,
+ material, &Qt3DExtras::QMorphPhongMaterial::setInterpolator);
+
+ // Cylinder
+ Qt3DCore::QEntity *morphingEntity = new Qt3DCore::QEntity(rootEntity);
+ morphingEntity->addComponent(mesh);
+ morphingEntity->addComponent(transform);
+ morphingEntity->addComponent(material);
+
+ // Cylinder shape data
+ Qt3DExtras::QCylinderMesh *cylinderMesh = new Qt3DExtras::QCylinderMesh();
+ cylinderMesh->setRadius(1);
+ cylinderMesh->setLength(3);
+ cylinderMesh->setRings(100);
+ cylinderMesh->setSlices(20);
+
+ // Transform for cylinder
+ Qt3DCore::QTransform *cylinderTransform = new Qt3DCore::QTransform;
+ cylinderTransform->setScale(0.5f);
+ cylinderTransform->setRotation(QQuaternion::fromAxisAndAngle(QVector3D(1, 0, 0), 45.0f));
+
+ // Material
+ Qt3DExtras::QPhongMaterial *cylinderMaterial = new Qt3DExtras::QPhongMaterial(rootEntity);
+ cylinderMaterial->setDiffuse(Qt::red);
+
+ // Cylinder
+ Qt3DCore::QEntity *cylinder = new Qt3DCore::QEntity(rootEntity);
+ cylinder->addComponent(cylinderMesh);
+ cylinder->addComponent(cylinderTransform);
+ cylinder->addComponent(cylinderMaterial);
+
+ QPropertyAnimation* anim = new QPropertyAnimation(animation);
+ anim->setDuration(5000);
+ anim->setEndValue(QVariant::fromValue(12.0f));
+ anim->setStartValue(QVariant::fromValue(0.0f));
+ anim->setLoopCount(-1);
+ anim->setTargetObject(animation);
+ anim->setPropertyName("position");
+ anim->start();
+
+ // Set root object of the scene
+ view.setRootEntity(rootEntity);
+ view.show();
+
+ return app.exec();
+}
diff --git a/tests/manual/mesh-morphing/mesh-morphing.pro b/tests/manual/mesh-morphing/mesh-morphing.pro
new file mode 100644
index 000000000..ad2a31b8b
--- /dev/null
+++ b/tests/manual/mesh-morphing/mesh-morphing.pro
@@ -0,0 +1,10 @@
+!include( ../manual.pri ) {
+ error( "Couldn't find the manual.pri file!" )
+}
+
+QT += 3dcore 3drender 3dquick 3dinput quick qml 3dextras 3dquickextras
+
+SOURCES += \
+ main.cpp
+
+RESOURCES +=
diff --git a/tests/manual/mesh-morphing/mesh-morphing.qrc b/tests/manual/mesh-morphing/mesh-morphing.qrc
new file mode 100644
index 000000000..7646d2b36
--- /dev/null
+++ b/tests/manual/mesh-morphing/mesh-morphing.qrc
@@ -0,0 +1 @@
+<RCC/>