summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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/>