summaryrefslogtreecommitdiffstats
path: root/examples/vulkan
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2017-03-24 14:54:24 +0100
committerLaszlo Agocs <laszlo.agocs@qt.io>2017-03-29 10:58:06 +0000
commitc72b821b5911842757a3929fb287471ad5d457ea (patch)
tree07aace2498733596acc411cf096fcff998485c42 /examples/vulkan
parente7a7931ba1e4fd6d80674c73e6e9e9a8099b9391 (diff)
Add the Vulkan cube example
Features a little bit more than a cube, though. Change-Id: I636d4875ba9ccf722ed3caab97f14570be785748 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'examples/vulkan')
-rw-r--r--examples/vulkan/doc/images/hellovulkancubes.pngbin0 -> 98495 bytes
-rw-r--r--examples/vulkan/doc/src/hellovulkancubes.qdoc58
-rw-r--r--examples/vulkan/hellovulkancubes/camera.cpp112
-rw-r--r--examples/vulkan/hellovulkancubes/camera.h80
-rw-r--r--examples/vulkan/hellovulkancubes/color.frag12
-rw-r--r--examples/vulkan/hellovulkancubes/color.vert14
-rw-r--r--examples/vulkan/hellovulkancubes/color_frag.spvbin0 -> 616 bytes
-rw-r--r--examples/vulkan/hellovulkancubes/color_phong.frag39
-rw-r--r--examples/vulkan/hellovulkancubes/color_phong.vert32
-rw-r--r--examples/vulkan/hellovulkancubes/color_phong_frag.spvbin0 -> 3364 bytes
-rw-r--r--examples/vulkan/hellovulkancubes/color_phong_vert.spvbin0 -> 2268 bytes
-rw-r--r--examples/vulkan/hellovulkancubes/color_vert.spvbin0 -> 744 bytes
-rw-r--r--examples/vulkan/hellovulkancubes/hellovulkancubes.pro24
-rw-r--r--examples/vulkan/hellovulkancubes/hellovulkancubes.qrc10
-rw-r--r--examples/vulkan/hellovulkancubes/main.cpp92
-rw-r--r--examples/vulkan/hellovulkancubes/mainwindow.cpp117
-rw-r--r--examples/vulkan/hellovulkancubes/mainwindow.h83
-rw-r--r--examples/vulkan/hellovulkancubes/mesh.cpp98
-rw-r--r--examples/vulkan/hellovulkancubes/mesh.h79
-rw-r--r--examples/vulkan/hellovulkancubes/renderer.cpp1048
-rw-r--r--examples/vulkan/hellovulkancubes/renderer.h158
-rw-r--r--examples/vulkan/hellovulkancubes/shader.cpp94
-rw-r--r--examples/vulkan/hellovulkancubes/shader.h77
-rw-r--r--examples/vulkan/hellovulkancubes/vulkanwindow.cpp134
-rw-r--r--examples/vulkan/hellovulkancubes/vulkanwindow.h85
-rw-r--r--examples/vulkan/shared/block.bufbin0 -> 4256 bytes
-rw-r--r--examples/vulkan/shared/block.txt100
-rw-r--r--examples/vulkan/shared/objconvert.js241
-rw-r--r--examples/vulkan/shared/qt_logo.bufbin0 -> 125600 bytes
-rw-r--r--examples/vulkan/shared/qt_logo.txt2912
-rw-r--r--examples/vulkan/vulkan.pro5
31 files changed, 5703 insertions, 1 deletions
diff --git a/examples/vulkan/doc/images/hellovulkancubes.png b/examples/vulkan/doc/images/hellovulkancubes.png
new file mode 100644
index 0000000000..c3d819c047
--- /dev/null
+++ b/examples/vulkan/doc/images/hellovulkancubes.png
Binary files differ
diff --git a/examples/vulkan/doc/src/hellovulkancubes.qdoc b/examples/vulkan/doc/src/hellovulkancubes.qdoc
new file mode 100644
index 0000000000..934d2015a1
--- /dev/null
+++ b/examples/vulkan/doc/src/hellovulkancubes.qdoc
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example hellovulkancubes
+ \title Hello Vulkan Cubes Example
+ \ingroup examples-vulkan
+ \brief Shows the basics of using QVulkanWindow
+
+ The \e{Hello Vulkan Cubes Example} shows more advanced usage of QVulkanWindow.
+
+ \image hellovulkancubes.png
+
+ In this example there is a mesh loaded from a file and two different
+ materials and corresponding graphics pipelines. The rounded cubes are drawn
+ using instancing and feature a Phong lighting model with a single
+ directional light.
+
+ Unlike hellovulkantexture and hellovulkantriangle, the uniform buffer
+ handling takes an alternative approach here: dynamic uniform buffers are
+ used instead of multiple descriptor sets.
+
+ The example requires QtConcurrent since it demonstrates simple usage of
+ QtConcurrent::run(), QFuture, and QFutureWatcher in combination of
+ QVulkanWindow. Mesh and shader data loading, the potentially expensive
+ graphics pipeline construction, and the building of the frame command buffer
+ are all done in separate worker threads.
+
+ The scene is embedded into a widget-based user interface. The QVulkanWindow
+ subclass handles mouse and keyboard input as well since it provides a
+ first-person style camera in order to allow moving around in the scene.
+
+ \include examples-run.qdocinc
+*/
diff --git a/examples/vulkan/hellovulkancubes/camera.cpp b/examples/vulkan/hellovulkancubes/camera.cpp
new file mode 100644
index 0000000000..64dee03154
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/camera.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "camera.h"
+
+Camera::Camera(const QVector3D &pos)
+ : m_forward(0.0f, 0.0f, -1.0f),
+ m_right(1.0f, 0.0f, 0.0f),
+ m_up(0.0f, 1.0f, 0.0f),
+ m_pos(pos),
+ m_yaw(0.0f),
+ m_pitch(0.0f)
+{
+}
+
+static inline void clamp360(float *v)
+{
+ if (*v > 360.0f)
+ *v -= 360.0f;
+ if (*v < -360.0f)
+ *v += 360.0f;
+}
+
+void Camera::yaw(float degrees)
+{
+ m_yaw += degrees;
+ clamp360(&m_yaw);
+ m_yawMatrix.setToIdentity();
+ m_yawMatrix.rotate(m_yaw, 0, 1, 0);
+
+ QMatrix4x4 rotMat = m_pitchMatrix * m_yawMatrix;
+ m_forward = (QVector4D(0.0f, 0.0f, -1.0f, 0.0f) * rotMat).toVector3D();
+ m_right = (QVector4D(1.0f, 0.0f, 0.0f, 0.0f) * rotMat).toVector3D();
+}
+
+void Camera::pitch(float degrees)
+{
+ m_pitch += degrees;
+ clamp360(&m_pitch);
+ m_pitchMatrix.setToIdentity();
+ m_pitchMatrix.rotate(m_pitch, 1, 0, 0);
+
+ QMatrix4x4 rotMat = m_pitchMatrix * m_yawMatrix;
+ m_forward = (QVector4D(0.0f, 0.0f, -1.0f, 0.0f) * rotMat).toVector3D();
+ m_up = (QVector4D(0.0f, 1.0f, 0.0f, 0.0f) * rotMat).toVector3D();
+}
+
+void Camera::walk(float amount)
+{
+ m_pos[0] += amount * m_forward.x();
+ m_pos[2] += amount * m_forward.z();
+}
+
+void Camera::strafe(float amount)
+{
+ m_pos[0] += amount * m_right.x();
+ m_pos[2] += amount * m_right.z();
+}
+
+QMatrix4x4 Camera::viewMatrix() const
+{
+ QMatrix4x4 m = m_pitchMatrix * m_yawMatrix;
+ m.translate(-m_pos);
+ return m;
+}
diff --git a/examples/vulkan/hellovulkancubes/camera.h b/examples/vulkan/hellovulkancubes/camera.h
new file mode 100644
index 0000000000..c5c579f066
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/camera.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CAMERA_H
+#define CAMERA_H
+
+#include <QVector3D>
+#include <QMatrix4x4>
+
+class Camera
+{
+public:
+ Camera(const QVector3D &pos);
+
+ void yaw(float degrees);
+ void pitch(float degrees);
+ void walk(float amount);
+ void strafe(float amount);
+
+ QMatrix4x4 viewMatrix() const;
+
+private:
+ QVector3D m_forward;
+ QVector3D m_right;
+ QVector3D m_up;
+ QVector3D m_pos;
+ float m_yaw;
+ float m_pitch;
+ QMatrix4x4 m_yawMatrix;
+ QMatrix4x4 m_pitchMatrix;
+};
+
+#endif
diff --git a/examples/vulkan/hellovulkancubes/color.frag b/examples/vulkan/hellovulkancubes/color.frag
new file mode 100644
index 0000000000..3b04955963
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/color.frag
@@ -0,0 +1,12 @@
+#version 440
+
+layout(push_constant) uniform PC {
+ layout(offset = 64) vec3 color;
+} pc;
+
+layout(location = 0) out vec4 fragColor;
+
+void main()
+{
+ fragColor = vec4(pc.color, 1.0);
+}
diff --git a/examples/vulkan/hellovulkancubes/color.vert b/examples/vulkan/hellovulkancubes/color.vert
new file mode 100644
index 0000000000..19bf815819
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/color.vert
@@ -0,0 +1,14 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+layout(push_constant) uniform PC {
+ mat4 mvp;
+} pc;
+
+void main()
+{
+ gl_Position = pc.mvp * position;
+}
diff --git a/examples/vulkan/hellovulkancubes/color_frag.spv b/examples/vulkan/hellovulkancubes/color_frag.spv
new file mode 100644
index 0000000000..bd72984ffe
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/color_frag.spv
Binary files differ
diff --git a/examples/vulkan/hellovulkancubes/color_phong.frag b/examples/vulkan/hellovulkancubes/color_phong.frag
new file mode 100644
index 0000000000..8b0c715f3b
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/color_phong.frag
@@ -0,0 +1,39 @@
+#version 440
+
+layout(location = 0) in vec3 vECVertNormal;
+layout(location = 1) in vec3 vECVertPos;
+layout(location = 2) flat in vec3 vDiffuseAdjust;
+
+layout(std140, binding = 1) uniform buf {
+ vec3 ECCameraPosition;
+ vec3 ka;
+ vec3 kd;
+ vec3 ks;
+ // Have one light only for now.
+ vec3 ECLightPosition;
+ vec3 attenuation;
+ vec3 color;
+ float intensity;
+ float specularExp;
+} ubuf;
+
+layout(location = 0) out vec4 fragColor;
+
+void main()
+{
+ vec3 unnormL = ubuf.ECLightPosition - vECVertPos;
+ float dist = length(unnormL);
+ float att = 1.0 / (ubuf.attenuation.x + ubuf.attenuation.y * dist + ubuf.attenuation.z * dist * dist);
+
+ vec3 N = normalize(vECVertNormal);
+ vec3 L = normalize(unnormL);
+ float NL = max(0.0, dot(N, L));
+ vec3 dColor = att * ubuf.intensity * ubuf.color * NL;
+
+ vec3 R = reflect(-L, N);
+ vec3 V = normalize(ubuf.ECCameraPosition - vECVertPos);
+ float RV = max(0.0, dot(R, V));
+ vec3 sColor = att * ubuf.intensity * ubuf.color * pow(RV, ubuf.specularExp);
+
+ fragColor = vec4(ubuf.ka + (ubuf.kd + vDiffuseAdjust) * dColor + ubuf.ks * sColor, 1.0);
+}
diff --git a/examples/vulkan/hellovulkancubes/color_phong.vert b/examples/vulkan/hellovulkancubes/color_phong.vert
new file mode 100644
index 0000000000..a1d1552685
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/color_phong.vert
@@ -0,0 +1,32 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec3 normal;
+
+// Instanced attributes to variate the translation of the model and the diffuse
+// color of the material.
+layout(location = 2) in vec3 instTranslate;
+layout(location = 3) in vec3 instDiffuseAdjust;
+
+out gl_PerVertex { vec4 gl_Position; };
+layout(location = 0) out vec3 vECVertNormal;
+layout(location = 1) out vec3 vECVertPos;
+layout(location = 2) flat out vec3 vDiffuseAdjust;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 vp;
+ mat4 model;
+ mat3 modelNormal;
+} ubuf;
+
+void main()
+{
+ vECVertNormal = normalize(ubuf.modelNormal * normal);
+ mat4 t = mat4(1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ instTranslate.x, instTranslate.y, instTranslate.z, 1);
+ vECVertPos = vec3(t * ubuf.model * position);
+ vDiffuseAdjust = instDiffuseAdjust;
+ gl_Position = ubuf.vp * t * ubuf.model * position;
+}
diff --git a/examples/vulkan/hellovulkancubes/color_phong_frag.spv b/examples/vulkan/hellovulkancubes/color_phong_frag.spv
new file mode 100644
index 0000000000..a1a413533b
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/color_phong_frag.spv
Binary files differ
diff --git a/examples/vulkan/hellovulkancubes/color_phong_vert.spv b/examples/vulkan/hellovulkancubes/color_phong_vert.spv
new file mode 100644
index 0000000000..3ede21e007
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/color_phong_vert.spv
Binary files differ
diff --git a/examples/vulkan/hellovulkancubes/color_vert.spv b/examples/vulkan/hellovulkancubes/color_vert.spv
new file mode 100644
index 0000000000..3f708b7d07
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/color_vert.spv
Binary files differ
diff --git a/examples/vulkan/hellovulkancubes/hellovulkancubes.pro b/examples/vulkan/hellovulkancubes/hellovulkancubes.pro
new file mode 100644
index 0000000000..f9a9c3cff1
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/hellovulkancubes.pro
@@ -0,0 +1,24 @@
+QT += widgets concurrent
+
+HEADERS += \
+ mainwindow.h \
+ vulkanwindow.h \
+ renderer.h \
+ mesh.h \
+ shader.h \
+ camera.h
+
+SOURCES += \
+ main.cpp \
+ mainwindow.cpp \
+ vulkanwindow.cpp \
+ renderer.cpp \
+ mesh.cpp \
+ shader.cpp \
+ camera.cpp
+
+RESOURCES += hellovulkancubes.qrc
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/vulkan/hellovulkancubes
+INSTALLS += target
diff --git a/examples/vulkan/hellovulkancubes/hellovulkancubes.qrc b/examples/vulkan/hellovulkancubes/hellovulkancubes.qrc
new file mode 100644
index 0000000000..7b085e1875
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/hellovulkancubes.qrc
@@ -0,0 +1,10 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="block.buf">../shared/block.buf</file>
+ <file alias="qt_logo.buf">../shared/qt_logo.buf</file>
+ <file>color_phong_vert.spv</file>
+ <file>color_phong_frag.spv</file>
+ <file>color_vert.spv</file>
+ <file>color_frag.spv</file>
+</qresource>
+</RCC>
diff --git a/examples/vulkan/hellovulkancubes/main.cpp b/examples/vulkan/hellovulkancubes/main.cpp
new file mode 100644
index 0000000000..4ec4d48645
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/main.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QApplication>
+#include <QLoggingCategory>
+#include "mainwindow.h"
+#include "vulkanwindow.h"
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+
+ const bool dbg = qEnvironmentVariableIntValue("QT_VK_DEBUG");
+
+ QVulkanInstance inst;
+
+ if (dbg) {
+ QLoggingCategory::setFilterRules(QStringLiteral("qt.vulkan=true"));
+
+#ifndef Q_OS_ANDROID
+ inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
+#else
+ inst.setLayers(QByteArrayList()
+ << "VK_LAYER_GOOGLE_threading"
+ << "VK_LAYER_LUNARG_parameter_validation"
+ << "VK_LAYER_LUNARG_object_tracker"
+ << "VK_LAYER_LUNARG_core_validation"
+ << "VK_LAYER_LUNARG_image"
+ << "VK_LAYER_LUNARG_swapchain"
+ << "VK_LAYER_GOOGLE_unique_objects");
+#endif
+ }
+
+ if (!inst.create())
+ qFatal("Failed to create Vulkan instance: %d", inst.errorCode());
+
+ VulkanWindow *vulkanWindow = new VulkanWindow(dbg);
+ vulkanWindow->setVulkanInstance(&inst);
+
+ MainWindow mainWindow(vulkanWindow);
+ mainWindow.resize(1024, 768);
+ mainWindow.show();
+
+ return app.exec();
+}
diff --git a/examples/vulkan/hellovulkancubes/mainwindow.cpp b/examples/vulkan/hellovulkancubes/mainwindow.cpp
new file mode 100644
index 0000000000..2be7d237af
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/mainwindow.cpp
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mainwindow.h"
+#include "vulkanwindow.h"
+#include <QApplication>
+#include <QLabel>
+#include <QPushButton>
+#include <QLCDNumber>
+#include <QCheckBox>
+#include <QGridLayout>
+
+MainWindow::MainWindow(VulkanWindow *vulkanWindow)
+{
+ QWidget *wrapper = QWidget::createWindowContainer(vulkanWindow);
+ wrapper->setFocusPolicy(Qt::StrongFocus);
+ wrapper->setFocus();
+
+ infoLabel = new QLabel;
+ infoLabel->setFrameStyle(QFrame::Box | QFrame::Raised);
+ infoLabel->setAlignment(Qt::AlignCenter);
+ infoLabel->setText(tr("This example demonstrates instanced drawing\nof a mesh loaded from a file.\n"
+ "Uses a Phong material with a single light.\n"
+ "Also demonstrates dynamic uniform buffers\nand a bit of threading with QtConcurrent.\n"
+ "Uses 4x MSAA when available.\n"
+ "Comes with an FPS camera.\n"
+ "Hit [Shift+]WASD to walk and strafe.\nPress and move mouse to look around.\n"
+ "Click Add New to increase the number of instances."));
+
+ meshSwitch = new QCheckBox(tr("&Use Qt logo"));
+ meshSwitch->setFocusPolicy(Qt::NoFocus); // do not interfere with vulkanWindow's keyboard input
+
+ counterLcd = new QLCDNumber(5);
+ counterLcd->setSegmentStyle(QLCDNumber::Filled);
+ counterLcd->display(m_count);
+
+ newButton = new QPushButton(tr("&Add new"));
+ newButton->setFocusPolicy(Qt::NoFocus);
+ quitButton = new QPushButton(tr("&Quit"));
+ quitButton->setFocusPolicy(Qt::NoFocus);
+ pauseButton = new QPushButton(tr("&Pause"));
+ pauseButton->setFocusPolicy(Qt::NoFocus);
+
+ connect(quitButton, &QPushButton::clicked, qApp, &QCoreApplication::quit);
+ connect(newButton, &QPushButton::clicked, vulkanWindow, [=] {
+ vulkanWindow->addNew();
+ m_count = vulkanWindow->instanceCount();
+ counterLcd->display(m_count);
+ });
+ connect(pauseButton, &QPushButton::clicked, vulkanWindow, &VulkanWindow::togglePaused);
+ connect(meshSwitch, &QCheckBox::clicked, vulkanWindow, &VulkanWindow::meshSwitched);
+
+ QGridLayout *layout = new QGridLayout;
+ layout->addWidget(infoLabel, 0, 2);
+ layout->addWidget(meshSwitch, 1, 2);
+ layout->addWidget(createLabel(tr("INSTANCES")), 2, 2);
+ layout->addWidget(counterLcd, 3, 2);
+ layout->addWidget(newButton, 4, 2);
+ layout->addWidget(pauseButton, 5, 2);
+ layout->addWidget(quitButton, 6, 2);
+ layout->addWidget(wrapper, 0, 0, 7, 2);
+ setLayout(layout);
+}
+
+QLabel *MainWindow::createLabel(const QString &text)
+{
+ QLabel *lbl = new QLabel(text);
+ lbl->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
+ return lbl;
+}
diff --git a/examples/vulkan/hellovulkancubes/mainwindow.h b/examples/vulkan/hellovulkancubes/mainwindow.h
new file mode 100644
index 0000000000..4109709959
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/mainwindow.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QWidget>
+
+QT_BEGIN_NAMESPACE
+class QLCDNumber;
+class QLabel;
+class QPushButton;
+class QCheckBox;
+QT_END_NAMESPACE
+
+class VulkanWindow;
+
+class MainWindow : public QWidget
+{
+public:
+ MainWindow(VulkanWindow *vulkanWindow);
+
+private:
+ QLabel *createLabel(const QString &text);
+
+ QLabel *infoLabel;
+ QCheckBox *meshSwitch;
+ QLCDNumber *counterLcd;
+ QPushButton *newButton;
+ QPushButton *quitButton;
+ QPushButton *pauseButton;
+
+ int m_count = 128;
+};
+
+#endif
diff --git a/examples/vulkan/hellovulkancubes/mesh.cpp b/examples/vulkan/hellovulkancubes/mesh.cpp
new file mode 100644
index 0000000000..fcc45bfd57
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/mesh.cpp
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mesh.h"
+#include <QtConcurrentRun>
+#include <QFile>
+
+void Mesh::load(const QString &fn)
+{
+ reset();
+ m_maybeRunning = true;
+ m_future = QtConcurrent::run([fn]() {
+ MeshData md;
+ QFile f(fn);
+ if (!f.open(QIODevice::ReadOnly)) {
+ qWarning("Failed to open %s", qPrintable(fn));
+ return md;
+ }
+ QByteArray buf = f.readAll();
+ const char *p = buf.constData();
+ quint32 format;
+ memcpy(&format, p, 4);
+ if (format != 1) {
+ qWarning("Invalid format in %s", qPrintable(fn));
+ return md;
+ }
+ int ofs = 4;
+ memcpy(&md.vertexCount, p + ofs, 4);
+ ofs += 4;
+ memcpy(md.aabb, p + ofs, 6 * 4);
+ ofs += 6 * 4;
+ const int byteCount = md.vertexCount * 8 * 4;
+ md.geom.resize(byteCount);
+ memcpy(md.geom.data(), p + ofs, byteCount);
+ return md;
+ });
+}
+
+MeshData *Mesh::data()
+{
+ if (m_maybeRunning && !m_data.isValid())
+ m_data = m_future.result();
+
+ return &m_data;
+}
+
+void Mesh::reset()
+{
+ *data() = MeshData();
+ m_maybeRunning = false;
+}
diff --git a/examples/vulkan/hellovulkancubes/mesh.h b/examples/vulkan/hellovulkancubes/mesh.h
new file mode 100644
index 0000000000..cb6ee9c830
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/mesh.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MESH_H
+#define MESH_H
+
+#include <QString>
+#include <QFuture>
+
+struct MeshData
+{
+ bool isValid() const { return vertexCount > 0; }
+ int vertexCount = 0;
+ float aabb[6];
+ QByteArray geom; // x, y, z, u, v, nx, ny, nz
+};
+
+class Mesh
+{
+public:
+ void load(const QString &fn);
+ MeshData *data();
+ bool isValid() { return data()->isValid(); }
+ void reset();
+
+private:
+ bool m_maybeRunning = false;
+ QFuture<MeshData> m_future;
+ MeshData m_data;
+};
+
+#endif
diff --git a/examples/vulkan/hellovulkancubes/renderer.cpp b/examples/vulkan/hellovulkancubes/renderer.cpp
new file mode 100644
index 0000000000..96ae6020a7
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/renderer.cpp
@@ -0,0 +1,1048 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "renderer.h"
+#include <QVulkanFunctions>
+#include <QtConcurrentRun>
+#include <QTime>
+
+static float quadVert[] = {
+ -1, -1, 0,
+ -1, 1, 0,
+ 1, -1, 0,
+ 1, 1, 0
+};
+
+#define DBG Q_UNLIKELY(m_window->isDebugEnabled())
+
+const int MAX_INSTANCES = 16384;
+const VkDeviceSize PER_INSTANCE_DATA_SIZE = 6 * sizeof(float); // instTranslate, instDiffuseAdjust
+
+static inline VkDeviceSize aligned(VkDeviceSize v, VkDeviceSize byteAlign)
+{
+ return (v + byteAlign - 1) & ~(byteAlign - 1);
+}
+
+Renderer::Renderer(VulkanWindow *w, int initialCount)
+ : m_window(w),
+ // Have the light positioned just behind the default camera position, looking forward.
+ m_lightPos(0.0f, 0.0f, 25.0f),
+ m_cam(QVector3D(0.0f, 0.0f, 20.0f)), // starting camera position
+ m_instCount(initialCount)
+{
+ qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
+
+ m_floorModel.translate(0, -5, 0);
+ m_floorModel.rotate(-90, 1, 0, 0);
+ m_floorModel.scale(20, 100, 1);
+
+ m_blockMesh.load(QStringLiteral(":/block.buf"));
+ m_logoMesh.load(QStringLiteral(":/qt_logo.buf"));
+
+ QObject::connect(&m_frameWatcher, &QFutureWatcherBase::finished, [this] {
+ if (m_framePending) {
+ m_framePending = false;
+ m_window->frameReady();
+ m_window->requestUpdate();
+ }
+ });
+}
+
+void Renderer::preInitResources()
+{
+ QSet<int> sampleCounts = m_window->supportedSampleCounts();
+ if (DBG)
+ qDebug() << "Supported sample counts:" << sampleCounts;
+ if (sampleCounts.contains(4)) {
+ if (DBG)
+ qDebug("Requesting 4x MSAA");
+ m_window->setSampleCount(4);
+ }
+}
+
+void Renderer::initResources()
+{
+ if (DBG)
+ qDebug("Renderer init");
+
+ m_animating = true;
+ m_framePending = false;
+
+ QVulkanInstance *inst = m_window->vulkanInstance();
+ VkDevice dev = m_window->device();
+ const VkPhysicalDeviceLimits *pdevLimits = &m_window->physicalDeviceProperties()->limits;
+ const VkDeviceSize uniAlign = pdevLimits->minUniformBufferOffsetAlignment;
+
+ m_devFuncs = inst->deviceFunctions(dev);
+
+ // Note the std140 packing rules. A vec3 still has an alignment of 16,
+ // while a mat3 is like 3 * vec3.
+ m_itemMaterial.vertUniSize = aligned(2 * 64 + 48, uniAlign); // see color_phong.vert
+ m_itemMaterial.fragUniSize = aligned(6 * 16 + 12 + 2 * 4, uniAlign); // see color_phong.frag
+
+ if (!m_itemMaterial.vs.isValid())
+ m_itemMaterial.vs.load(inst, dev, QStringLiteral(":/color_phong_vert.spv"));
+ if (!m_itemMaterial.fs.isValid())
+ m_itemMaterial.fs.load(inst, dev, QStringLiteral(":/color_phong_frag.spv"));
+
+ if (!m_floorMaterial.vs.isValid())
+ m_floorMaterial.vs.load(inst, dev, QStringLiteral(":/color_vert.spv"));
+ if (!m_floorMaterial.fs.isValid())
+ m_floorMaterial.fs.load(inst, dev, QStringLiteral(":/color_frag.spv"));
+
+ m_pipelinesFuture = QtConcurrent::run(this, &Renderer::createPipelines);
+}
+
+void Renderer::createPipelines()
+{
+ VkDevice dev = m_window->device();
+
+ VkPipelineCacheCreateInfo pipelineCacheInfo;
+ memset(&pipelineCacheInfo, 0, sizeof(pipelineCacheInfo));
+ pipelineCacheInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
+ VkResult err = m_devFuncs->vkCreatePipelineCache(dev, &pipelineCacheInfo, nullptr, &m_pipelineCache);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create pipeline cache: %d", err);
+
+ createItemPipeline();
+ createFloorPipeline();
+}
+
+void Renderer::createItemPipeline()
+{
+ VkDevice dev = m_window->device();
+
+ // Vertex layout.
+ VkVertexInputBindingDescription vertexBindingDesc[] = {
+ {
+ 0, // binding
+ 8 * sizeof(float),
+ VK_VERTEX_INPUT_RATE_VERTEX
+ },
+ {
+ 1,
+ 6 * sizeof(float),
+ VK_VERTEX_INPUT_RATE_INSTANCE
+ }
+ };
+ VkVertexInputAttributeDescription vertexAttrDesc[] = {
+ { // position
+ 0, // location
+ 0, // binding
+ VK_FORMAT_R32G32B32_SFLOAT,
+ 0 // offset
+ },
+ { // normal
+ 1,
+ 0,
+ VK_FORMAT_R32G32B32_SFLOAT,
+ 5 * sizeof(float)
+ },
+ { // instTranslate
+ 2,
+ 1,
+ VK_FORMAT_R32G32B32_SFLOAT,
+ 0
+ },
+ { // instDiffuseAdjust
+ 3,
+ 1,
+ VK_FORMAT_R32G32B32_SFLOAT,
+ 3 * sizeof(float)
+ }
+ };
+
+ VkPipelineVertexInputStateCreateInfo vertexInputInfo;
+ vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+ vertexInputInfo.pNext = nullptr;
+ vertexInputInfo.flags = 0;
+ vertexInputInfo.vertexBindingDescriptionCount = sizeof(vertexBindingDesc) / sizeof(vertexBindingDesc[0]);
+ vertexInputInfo.pVertexBindingDescriptions = vertexBindingDesc;
+ vertexInputInfo.vertexAttributeDescriptionCount = sizeof(vertexAttrDesc) / sizeof(vertexAttrDesc[0]);
+ vertexInputInfo.pVertexAttributeDescriptions = vertexAttrDesc;
+
+ // Descriptor set layout.
+ VkDescriptorPoolSize descPoolSizes[] = {
+ { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 2 }
+ };
+ VkDescriptorPoolCreateInfo descPoolInfo;
+ memset(&descPoolInfo, 0, sizeof(descPoolInfo));
+ descPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+ descPoolInfo.maxSets = 1; // a single set is enough due to the dynamic uniform buffer
+ descPoolInfo.poolSizeCount = sizeof(descPoolSizes) / sizeof(descPoolSizes[0]);
+ descPoolInfo.pPoolSizes = descPoolSizes;
+ VkResult err = m_devFuncs->vkCreateDescriptorPool(dev, &descPoolInfo, nullptr, &m_itemMaterial.descPool);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create descriptor pool: %d", err);
+
+ VkDescriptorSetLayoutBinding layoutBindings[] =
+ {
+ {
+ 0, // binding
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
+ 1, // descriptorCount
+ VK_SHADER_STAGE_VERTEX_BIT,
+ nullptr
+ },
+ {
+ 1,
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
+ 1,
+ VK_SHADER_STAGE_FRAGMENT_BIT,
+ nullptr
+ }
+ };
+ VkDescriptorSetLayoutCreateInfo descLayoutInfo = {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+ nullptr,
+ 0,
+ sizeof(layoutBindings) / sizeof(layoutBindings[0]),
+ layoutBindings
+ };
+ err = m_devFuncs->vkCreateDescriptorSetLayout(dev, &descLayoutInfo, nullptr, &m_itemMaterial.descSetLayout);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create descriptor set layout: %d", err);
+
+ VkDescriptorSetAllocateInfo descSetAllocInfo = {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ nullptr,
+ m_itemMaterial.descPool,
+ 1,
+ &m_itemMaterial.descSetLayout
+ };
+ err = m_devFuncs->vkAllocateDescriptorSets(dev, &descSetAllocInfo, &m_itemMaterial.descSet);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to allocate descriptor set: %d", err);
+
+ // Graphics pipeline.
+ VkPipelineLayoutCreateInfo pipelineLayoutInfo;
+ memset(&pipelineLayoutInfo, 0, sizeof(pipelineLayoutInfo));
+ pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ pipelineLayoutInfo.setLayoutCount = 1;
+ pipelineLayoutInfo.pSetLayouts = &m_itemMaterial.descSetLayout;
+
+ err = m_devFuncs->vkCreatePipelineLayout(dev, &pipelineLayoutInfo, nullptr, &m_itemMaterial.pipelineLayout);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create pipeline layout: %d", err);
+
+ VkGraphicsPipelineCreateInfo pipelineInfo;
+ memset(&pipelineInfo, 0, sizeof(pipelineInfo));
+ pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+
+ VkPipelineShaderStageCreateInfo shaderStages[2] = {
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ nullptr,
+ 0,
+ VK_SHADER_STAGE_VERTEX_BIT,
+ m_itemMaterial.vs.data()->shaderModule,
+ "main",
+ nullptr
+ },
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ nullptr,
+ 0,
+ VK_SHADER_STAGE_FRAGMENT_BIT,
+ m_itemMaterial.fs.data()->shaderModule,
+ "main",
+ nullptr
+ }
+ };
+ pipelineInfo.stageCount = 2;
+ pipelineInfo.pStages = shaderStages;
+
+ pipelineInfo.pVertexInputState = &vertexInputInfo;
+
+ VkPipelineInputAssemblyStateCreateInfo ia;
+ memset(&ia, 0, sizeof(ia));
+ ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+ ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ pipelineInfo.pInputAssemblyState = &ia;
+
+ VkPipelineViewportStateCreateInfo vp;
+ memset(&vp, 0, sizeof(vp));
+ vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+ vp.viewportCount = 1;
+ vp.scissorCount = 1;
+ pipelineInfo.pViewportState = &vp;
+
+ VkPipelineRasterizationStateCreateInfo rs;
+ memset(&rs, 0, sizeof(rs));
+ rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+ rs.polygonMode = VK_POLYGON_MODE_FILL;
+ rs.cullMode = VK_CULL_MODE_BACK_BIT;
+ rs.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
+ rs.lineWidth = 1.0f;
+ pipelineInfo.pRasterizationState = &rs;
+
+ VkPipelineMultisampleStateCreateInfo ms;
+ memset(&ms, 0, sizeof(ms));
+ ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+ ms.rasterizationSamples = m_window->sampleCountFlagBits();
+ pipelineInfo.pMultisampleState = &ms;
+
+ VkPipelineDepthStencilStateCreateInfo ds;
+ memset(&ds, 0, sizeof(ds));
+ ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
+ ds.depthTestEnable = VK_TRUE;
+ ds.depthWriteEnable = VK_TRUE;
+ ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
+ pipelineInfo.pDepthStencilState = &ds;
+
+ VkPipelineColorBlendStateCreateInfo cb;
+ memset(&cb, 0, sizeof(cb));
+ cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
+ VkPipelineColorBlendAttachmentState att;
+ memset(&att, 0, sizeof(att));
+ att.colorWriteMask = 0xF;
+ cb.attachmentCount = 1;
+ cb.pAttachments = &att;
+ pipelineInfo.pColorBlendState = &cb;
+
+ VkDynamicState dynEnable[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
+ VkPipelineDynamicStateCreateInfo dyn;
+ memset(&dyn, 0, sizeof(dyn));
+ dyn.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
+ dyn.dynamicStateCount = sizeof(dynEnable) / sizeof(VkDynamicState);
+ dyn.pDynamicStates = dynEnable;
+ pipelineInfo.pDynamicState = &dyn;
+
+ pipelineInfo.layout = m_itemMaterial.pipelineLayout;
+ pipelineInfo.renderPass = m_window->defaultRenderPass();
+
+ err = m_devFuncs->vkCreateGraphicsPipelines(dev, m_pipelineCache, 1, &pipelineInfo, nullptr, &m_itemMaterial.pipeline);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create graphics pipeline: %d", err);
+}
+
+void Renderer::createFloorPipeline()
+{
+ VkDevice dev = m_window->device();
+
+ // Vertex layout.
+ VkVertexInputBindingDescription vertexBindingDesc = {
+ 0, // binding
+ 3 * sizeof(float),
+ VK_VERTEX_INPUT_RATE_VERTEX
+ };
+ VkVertexInputAttributeDescription vertexAttrDesc[] = {
+ { // position
+ 0, // location
+ 0, // binding
+ VK_FORMAT_R32G32B32_SFLOAT,
+ 0 // offset
+ },
+ };
+
+ VkPipelineVertexInputStateCreateInfo vertexInputInfo;
+ vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+ vertexInputInfo.pNext = nullptr;
+ vertexInputInfo.flags = 0;
+ vertexInputInfo.vertexBindingDescriptionCount = 1;
+ vertexInputInfo.pVertexBindingDescriptions = &vertexBindingDesc;
+ vertexInputInfo.vertexAttributeDescriptionCount = sizeof(vertexAttrDesc) / sizeof(vertexAttrDesc[0]);
+ vertexInputInfo.pVertexAttributeDescriptions = vertexAttrDesc;
+
+ // Do not bother with uniform buffers and descriptors, all the data fits
+ // into the spec mandated minimum of 128 bytes for push constants.
+ VkPushConstantRange pcr[] = {
+ // mvp
+ {
+ VK_SHADER_STAGE_VERTEX_BIT,
+ 0,
+ 64
+ },
+ // color
+ {
+ VK_SHADER_STAGE_FRAGMENT_BIT,
+ 64,
+ 12
+ }
+ };
+
+ VkPipelineLayoutCreateInfo pipelineLayoutInfo;
+ memset(&pipelineLayoutInfo, 0, sizeof(pipelineLayoutInfo));
+ pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ pipelineLayoutInfo.pushConstantRangeCount = sizeof(pcr) / sizeof(pcr[0]);
+ pipelineLayoutInfo.pPushConstantRanges = pcr;
+
+ VkResult err = m_devFuncs->vkCreatePipelineLayout(dev, &pipelineLayoutInfo, nullptr, &m_floorMaterial.pipelineLayout);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create pipeline layout: %d", err);
+
+ VkGraphicsPipelineCreateInfo pipelineInfo;
+ memset(&pipelineInfo, 0, sizeof(pipelineInfo));
+ pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+
+ VkPipelineShaderStageCreateInfo shaderStages[2] = {
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ nullptr,
+ 0,
+ VK_SHADER_STAGE_VERTEX_BIT,
+ m_floorMaterial.vs.data()->shaderModule,
+ "main",
+ nullptr
+ },
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ nullptr,
+ 0,
+ VK_SHADER_STAGE_FRAGMENT_BIT,
+ m_floorMaterial.fs.data()->shaderModule,
+ "main",
+ nullptr
+ }
+ };
+ pipelineInfo.stageCount = 2;
+ pipelineInfo.pStages = shaderStages;
+
+ pipelineInfo.pVertexInputState = &vertexInputInfo;
+
+ VkPipelineInputAssemblyStateCreateInfo ia;
+ memset(&ia, 0, sizeof(ia));
+ ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+ ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
+ pipelineInfo.pInputAssemblyState = &ia;
+
+ VkPipelineViewportStateCreateInfo vp;
+ memset(&vp, 0, sizeof(vp));
+ vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+ vp.viewportCount = 1;
+ vp.scissorCount = 1;
+ pipelineInfo.pViewportState = &vp;
+
+ VkPipelineRasterizationStateCreateInfo rs;
+ memset(&rs, 0, sizeof(rs));
+ rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+ rs.polygonMode = VK_POLYGON_MODE_FILL;
+ rs.cullMode = VK_CULL_MODE_BACK_BIT;
+ rs.frontFace = VK_FRONT_FACE_CLOCKWISE;
+ rs.lineWidth = 1.0f;
+ pipelineInfo.pRasterizationState = &rs;
+
+ VkPipelineMultisampleStateCreateInfo ms;
+ memset(&ms, 0, sizeof(ms));
+ ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+ ms.rasterizationSamples = m_window->sampleCountFlagBits();
+ pipelineInfo.pMultisampleState = &ms;
+
+ VkPipelineDepthStencilStateCreateInfo ds;
+ memset(&ds, 0, sizeof(ds));
+ ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
+ ds.depthTestEnable = VK_TRUE;
+ ds.depthWriteEnable = VK_TRUE;
+ ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
+ pipelineInfo.pDepthStencilState = &ds;
+
+ VkPipelineColorBlendStateCreateInfo cb;
+ memset(&cb, 0, sizeof(cb));
+ cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
+ VkPipelineColorBlendAttachmentState att;
+ memset(&att, 0, sizeof(att));
+ att.colorWriteMask = 0xF;
+ cb.attachmentCount = 1;
+ cb.pAttachments = &att;
+ pipelineInfo.pColorBlendState = &cb;
+
+ VkDynamicState dynEnable[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
+ VkPipelineDynamicStateCreateInfo dyn;
+ memset(&dyn, 0, sizeof(dyn));
+ dyn.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
+ dyn.dynamicStateCount = sizeof(dynEnable) / sizeof(VkDynamicState);
+ dyn.pDynamicStates = dynEnable;
+ pipelineInfo.pDynamicState = &dyn;
+
+ pipelineInfo.layout = m_floorMaterial.pipelineLayout;
+ pipelineInfo.renderPass = m_window->defaultRenderPass();
+
+ err = m_devFuncs->vkCreateGraphicsPipelines(dev, m_pipelineCache, 1, &pipelineInfo, nullptr, &m_floorMaterial.pipeline);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create graphics pipeline: %d", err);
+}
+
+void Renderer::initSwapChainResources()
+{
+ m_proj = *m_window->clipCorrectionMatrix();
+ const QSize sz = m_window->swapChainImageSize();
+ m_proj.perspective(45.0f, sz.width() / (float) sz.height(), 0.01f, 1000.0f);
+ markViewProjDirty();
+}
+
+void Renderer::releaseSwapChainResources()
+{
+ // It is important to finish the pending frame right here since this is the
+ // last opportunity to act with all resources intact.
+ m_frameWatcher.waitForFinished();
+ // Cannot count on the finished() signal being emitted before returning
+ // from here.
+ if (m_framePending) {
+ m_framePending = false;
+ m_window->frameReady();
+ }
+}
+
+void Renderer::releaseResources()
+{
+ if (DBG)
+ qDebug("Renderer release");
+
+ m_pipelinesFuture.waitForFinished();
+
+ VkDevice dev = m_window->device();
+
+ if (m_itemMaterial.descSetLayout) {
+ m_devFuncs->vkDestroyDescriptorSetLayout(dev, m_itemMaterial.descSetLayout, nullptr);
+ m_itemMaterial.descSetLayout = VK_NULL_HANDLE;
+ }
+
+ if (m_itemMaterial.descPool) {
+ m_devFuncs->vkDestroyDescriptorPool(dev, m_itemMaterial.descPool, nullptr);
+ m_itemMaterial.descPool = VK_NULL_HANDLE;
+ }
+
+ if (m_itemMaterial.pipeline) {
+ m_devFuncs->vkDestroyPipeline(dev, m_itemMaterial.pipeline, nullptr);
+ m_itemMaterial.pipeline = VK_NULL_HANDLE;
+ }
+
+ if (m_itemMaterial.pipelineLayout) {
+ m_devFuncs->vkDestroyPipelineLayout(dev, m_itemMaterial.pipelineLayout, nullptr);
+ m_itemMaterial.pipelineLayout = VK_NULL_HANDLE;
+ }
+
+ if (m_floorMaterial.pipeline) {
+ m_devFuncs->vkDestroyPipeline(dev, m_floorMaterial.pipeline, nullptr);
+ m_floorMaterial.pipeline = VK_NULL_HANDLE;
+ }
+
+ if (m_floorMaterial.pipelineLayout) {
+ m_devFuncs->vkDestroyPipelineLayout(dev, m_floorMaterial.pipelineLayout, nullptr);
+ m_floorMaterial.pipelineLayout = VK_NULL_HANDLE;
+ }
+
+ if (m_pipelineCache) {
+ m_devFuncs->vkDestroyPipelineCache(dev, m_pipelineCache, nullptr);
+ m_pipelineCache = VK_NULL_HANDLE;
+ }
+
+ if (m_blockVertexBuf) {
+ m_devFuncs->vkDestroyBuffer(dev, m_blockVertexBuf, nullptr);
+ m_blockVertexBuf = VK_NULL_HANDLE;
+ }
+
+ if (m_logoVertexBuf) {
+ m_devFuncs->vkDestroyBuffer(dev, m_logoVertexBuf, nullptr);
+ m_logoVertexBuf = VK_NULL_HANDLE;
+ }
+
+ if (m_floorVertexBuf) {
+ m_devFuncs->vkDestroyBuffer(dev, m_floorVertexBuf, nullptr);
+ m_floorVertexBuf = VK_NULL_HANDLE;
+ }
+
+ if (m_uniBuf) {
+ m_devFuncs->vkDestroyBuffer(dev, m_uniBuf, nullptr);
+ m_uniBuf = VK_NULL_HANDLE;
+ }
+
+ if (m_bufMem) {
+ m_devFuncs->vkFreeMemory(dev, m_bufMem, nullptr);
+ m_bufMem = VK_NULL_HANDLE;
+ }
+
+ if (m_instBuf) {
+ m_devFuncs->vkDestroyBuffer(dev, m_instBuf, nullptr);
+ m_instBuf = VK_NULL_HANDLE;
+ }
+
+ if (m_instBufMem) {
+ m_devFuncs->vkFreeMemory(dev, m_instBufMem, nullptr);
+ m_instBufMem = VK_NULL_HANDLE;
+ }
+
+ if (m_itemMaterial.vs.isValid()) {
+ m_devFuncs->vkDestroyShaderModule(dev, m_itemMaterial.vs.data()->shaderModule, nullptr);
+ m_itemMaterial.vs.reset();
+ }
+ if (m_itemMaterial.fs.isValid()) {
+ m_devFuncs->vkDestroyShaderModule(dev, m_itemMaterial.fs.data()->shaderModule, nullptr);
+ m_itemMaterial.fs.reset();
+ }
+
+ if (m_floorMaterial.vs.isValid()) {
+ m_devFuncs->vkDestroyShaderModule(dev, m_floorMaterial.vs.data()->shaderModule, nullptr);
+ m_floorMaterial.vs.reset();
+ }
+ if (m_floorMaterial.fs.isValid()) {
+ m_devFuncs->vkDestroyShaderModule(dev, m_floorMaterial.fs.data()->shaderModule, nullptr);
+ m_floorMaterial.fs.reset();
+ }
+}
+
+void Renderer::ensureBuffers()
+{
+ if (m_blockVertexBuf)
+ return;
+
+ VkDevice dev = m_window->device();
+ const int concurrentFrameCount = m_window->concurrentFrameCount();
+
+ // Vertex buffer for the block.
+ VkBufferCreateInfo bufInfo;
+ memset(&bufInfo, 0, sizeof(bufInfo));
+ bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ const int blockMeshByteCount = m_blockMesh.data()->vertexCount * 8 * sizeof(float);
+ bufInfo.size = blockMeshByteCount;
+ bufInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+ VkResult err = m_devFuncs->vkCreateBuffer(dev, &bufInfo, nullptr, &m_blockVertexBuf);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create vertex buffer: %d", err);
+
+ VkMemoryRequirements blockVertMemReq;
+ m_devFuncs->vkGetBufferMemoryRequirements(dev, m_blockVertexBuf, &blockVertMemReq);
+
+ // Vertex buffer for the logo.
+ const int logoMeshByteCount = m_logoMesh.data()->vertexCount * 8 * sizeof(float);
+ bufInfo.size = logoMeshByteCount;
+ bufInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+ err = m_devFuncs->vkCreateBuffer(dev, &bufInfo, nullptr, &m_logoVertexBuf);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create vertex buffer: %d", err);
+
+ VkMemoryRequirements logoVertMemReq;
+ m_devFuncs->vkGetBufferMemoryRequirements(dev, m_logoVertexBuf, &logoVertMemReq);
+
+ // Vertex buffer for the floor.
+ bufInfo.size = sizeof(quadVert);
+ err = m_devFuncs->vkCreateBuffer(dev, &bufInfo, nullptr, &m_floorVertexBuf);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create vertex buffer: %d", err);
+
+ VkMemoryRequirements floorVertMemReq;
+ m_devFuncs->vkGetBufferMemoryRequirements(dev, m_floorVertexBuf, &floorVertMemReq);
+
+ // Uniform buffer. Instead of using multiple descriptor sets, we take a
+ // different approach: have a single dynamic uniform buffer and specify the
+ // active-frame-specific offset at the time of binding the descriptor set.
+ bufInfo.size = (m_itemMaterial.vertUniSize + m_itemMaterial.fragUniSize) * concurrentFrameCount;
+ bufInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
+ err = m_devFuncs->vkCreateBuffer(dev, &bufInfo, nullptr, &m_uniBuf);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create uniform buffer: %d", err);
+
+ VkMemoryRequirements uniMemReq;
+ m_devFuncs->vkGetBufferMemoryRequirements(dev, m_uniBuf, &uniMemReq);
+
+ // Allocate memory for everything at once.
+ VkDeviceSize logoVertStartOffset = aligned(0 + blockVertMemReq.size, logoVertMemReq.alignment);
+ VkDeviceSize floorVertStartOffset = aligned(logoVertStartOffset + logoVertMemReq.size, floorVertMemReq.alignment);
+ m_itemMaterial.uniMemStartOffset = aligned(floorVertStartOffset + floorVertMemReq.size, uniMemReq.alignment);
+ VkMemoryAllocateInfo memAllocInfo = {
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ nullptr,
+ m_itemMaterial.uniMemStartOffset + uniMemReq.size,
+ m_window->hostVisibleMemoryIndex()
+ };
+ err = m_devFuncs->vkAllocateMemory(dev, &memAllocInfo, nullptr, &m_bufMem);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to allocate memory: %d", err);
+
+ err = m_devFuncs->vkBindBufferMemory(dev, m_blockVertexBuf, m_bufMem, 0);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to bind vertex buffer memory: %d", err);
+ err = m_devFuncs->vkBindBufferMemory(dev, m_logoVertexBuf, m_bufMem, logoVertStartOffset);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to bind vertex buffer memory: %d", err);
+ err = m_devFuncs->vkBindBufferMemory(dev, m_floorVertexBuf, m_bufMem, floorVertStartOffset);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to bind vertex buffer memory: %d", err);
+ err = m_devFuncs->vkBindBufferMemory(dev, m_uniBuf, m_bufMem, m_itemMaterial.uniMemStartOffset);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to bind uniform buffer memory: %d", err);
+
+ // Copy vertex data.
+ quint8 *p;
+ err = m_devFuncs->vkMapMemory(dev, m_bufMem, 0, m_itemMaterial.uniMemStartOffset, 0, reinterpret_cast<void **>(&p));
+ if (err != VK_SUCCESS)
+ qFatal("Failed to map memory: %d", err);
+ memcpy(p, m_blockMesh.data()->geom.constData(), blockMeshByteCount);
+ memcpy(p + logoVertStartOffset, m_logoMesh.data()->geom.constData(), logoMeshByteCount);
+ memcpy(p + floorVertStartOffset, quadVert, sizeof(quadVert));
+ m_devFuncs->vkUnmapMemory(dev, m_bufMem);
+
+ // Write descriptors for the uniform buffers in the vertex and fragment shaders.
+ VkDescriptorBufferInfo vertUni = { m_uniBuf, 0, m_itemMaterial.vertUniSize };
+ VkDescriptorBufferInfo fragUni = { m_uniBuf, m_itemMaterial.vertUniSize, m_itemMaterial.fragUniSize };
+
+ VkWriteDescriptorSet descWrite[2];
+ memset(descWrite, 0, sizeof(descWrite));
+ descWrite[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ descWrite[0].dstSet = m_itemMaterial.descSet;
+ descWrite[0].dstBinding = 0;
+ descWrite[0].descriptorCount = 1;
+ descWrite[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
+ descWrite[0].pBufferInfo = &vertUni;
+
+ descWrite[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ descWrite[1].dstSet = m_itemMaterial.descSet;
+ descWrite[1].dstBinding = 1;
+ descWrite[1].descriptorCount = 1;
+ descWrite[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
+ descWrite[1].pBufferInfo = &fragUni;
+
+ m_devFuncs->vkUpdateDescriptorSets(dev, 2, descWrite, 0, nullptr);
+}
+
+void Renderer::ensureInstanceBuffer()
+{
+ if (m_instCount == m_preparedInstCount && m_instBuf)
+ return;
+
+ Q_ASSERT(m_instCount <= MAX_INSTANCES);
+
+ VkDevice dev = m_window->device();
+
+ // allocate only once, for the maximum instance count
+ if (!m_instBuf) {
+ VkBufferCreateInfo bufInfo;
+ memset(&bufInfo, 0, sizeof(bufInfo));
+ bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ bufInfo.size = MAX_INSTANCES * PER_INSTANCE_DATA_SIZE;
+ bufInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+
+ // Keep a copy of the data since we may lose all graphics resources on
+ // unexpose, and reinitializing to new random positions afterwards
+ // would not be nice.
+ m_instData.resize(bufInfo.size);
+
+ VkResult err = m_devFuncs->vkCreateBuffer(dev, &bufInfo, nullptr, &m_instBuf);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create instance buffer: %d", err);
+
+ VkMemoryRequirements memReq;
+ m_devFuncs->vkGetBufferMemoryRequirements(dev, m_instBuf, &memReq);
+ if (DBG)
+ qDebug("Allocating %u bytes for instance data", uint32_t(memReq.size));
+
+ VkMemoryAllocateInfo memAllocInfo = {
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ nullptr,
+ memReq.size,
+ m_window->hostVisibleMemoryIndex()
+ };
+ err = m_devFuncs->vkAllocateMemory(dev, &memAllocInfo, nullptr, &m_instBufMem);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to allocate memory: %d", err);
+
+ err = m_devFuncs->vkBindBufferMemory(dev, m_instBuf, m_instBufMem, 0);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to bind instance buffer memory: %d", err);
+ }
+
+ if (m_instCount != m_preparedInstCount) {
+ if (DBG)
+ qDebug("Preparing instances %d..%d", m_preparedInstCount, m_instCount - 1);
+ char *p = m_instData.data();
+ p += m_preparedInstCount * PER_INSTANCE_DATA_SIZE;
+ auto gen = [](float a, float b) { return float((qrand() % int(b - a + 1)) + a); };
+ for (int i = m_preparedInstCount; i < m_instCount; ++i) {
+ // Apply a random translation to each instance of the mesh.
+ float t[] = { gen(-5, 5), gen(-4, 6), gen(-30, 5) };
+ memcpy(p, t, 12);
+ // Apply a random adjustment to the diffuse color for each instance. (default is 0.7)
+ float d[] = { gen(-6, 3) / 10.0f, gen(-6, 3) / 10.0f, gen(-6, 3) / 10.0f };
+ memcpy(p + 12, d, 12);
+ p += PER_INSTANCE_DATA_SIZE;
+ }
+ m_preparedInstCount = m_instCount;
+ }
+
+ quint8 *p;
+ VkResult err = m_devFuncs->vkMapMemory(dev, m_instBufMem, 0, m_instCount * PER_INSTANCE_DATA_SIZE, 0,
+ reinterpret_cast<void **>(&p));
+ if (err != VK_SUCCESS)
+ qFatal("Failed to map memory: %d", err);
+ memcpy(p, m_instData.constData(), m_instData.size());
+ m_devFuncs->vkUnmapMemory(dev, m_instBufMem);
+}
+
+void Renderer::getMatrices(QMatrix4x4 *vp, QMatrix4x4 *model, QMatrix3x3 *modelNormal, QVector3D *eyePos)
+{
+ model->setToIdentity();
+ if (m_useLogo)
+ model->rotate(90, 1, 0, 0);
+ model->rotate(m_rotation, 1, 1, 0);
+
+ *modelNormal = model->normalMatrix();
+
+ QMatrix4x4 view = m_cam.viewMatrix();
+ *vp = m_proj * view;
+
+ *eyePos = view.inverted().column(3).toVector3D();
+}
+
+void Renderer::writeFragUni(quint8 *p, const QVector3D &eyePos)
+{
+ float ECCameraPosition[] = { eyePos.x(), eyePos.y(), eyePos.z() };
+ memcpy(p, ECCameraPosition, 12);
+ p += 16;
+
+ // Material
+ float ka[] = { 0.05f, 0.05f, 0.05f };
+ memcpy(p, ka, 12);
+ p += 16;
+
+ float kd[] = { 0.7f, 0.7f, 0.7f };
+ memcpy(p, kd, 12);
+ p += 16;
+
+ float ks[] = { 0.66f, 0.66f, 0.66f };
+ memcpy(p, ks, 12);
+ p += 16;
+
+ // Light parameters
+ float ECLightPosition[] = { m_lightPos.x(), m_lightPos.y(), m_lightPos.z() };
+ memcpy(p, ECLightPosition, 12);
+ p += 16;
+
+ float att[] = { 1, 0, 0 };
+ memcpy(p, att, 12);
+ p += 16;
+
+ float color[] = { 1.0f, 1.0f, 1.0f };
+ memcpy(p, color, 12);
+ p += 12; // next we have two floats which have an alignment of 4, hence 12 only
+
+ float intensity = 0.8f;
+ memcpy(p, &intensity, 4);
+ p += 4;
+
+ float specularExp = 150.0f;
+ memcpy(p, &specularExp, 4);
+ p += 4;
+}
+
+void Renderer::startNextFrame()
+{
+ // For demonstration purposes offload the command buffer generation onto a
+ // worker thread and continue with the frame submission only when it has
+ // finished.
+ Q_ASSERT(!m_framePending);
+ m_framePending = true;
+ QFuture<void> future = QtConcurrent::run(this, &Renderer::buildFrame);
+ m_frameWatcher.setFuture(future);
+}
+
+void Renderer::buildFrame()
+{
+ QMutexLocker locker(&m_guiMutex);
+
+ ensureBuffers();
+ ensureInstanceBuffer();
+ m_pipelinesFuture.waitForFinished();
+
+ VkCommandBuffer cb = m_window->currentCommandBuffer();
+ const QSize sz = m_window->swapChainImageSize();
+
+ VkClearColorValue clearColor = { 0.67f, 0.84f, 0.9f, 1.0f };
+ VkClearDepthStencilValue clearDS = { 1, 0 };
+ VkClearValue clearValues[3];
+ memset(clearValues, 0, sizeof(clearValues));
+ clearValues[0].color = clearValues[2].color = clearColor;
+ clearValues[1].depthStencil = clearDS;
+
+ VkRenderPassBeginInfo rpBeginInfo;
+ memset(&rpBeginInfo, 0, sizeof(rpBeginInfo));
+ rpBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ rpBeginInfo.renderPass = m_window->defaultRenderPass();
+ rpBeginInfo.framebuffer = m_window->currentFramebuffer();
+ rpBeginInfo.renderArea.extent.width = sz.width();
+ rpBeginInfo.renderArea.extent.height = sz.height();
+ rpBeginInfo.clearValueCount = m_window->sampleCountFlagBits() > VK_SAMPLE_COUNT_1_BIT ? 3 : 2;
+ rpBeginInfo.pClearValues = clearValues;
+ VkCommandBuffer cmdBuf = m_window->currentCommandBuffer();
+ m_devFuncs->vkCmdBeginRenderPass(cmdBuf, &rpBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+
+ VkViewport viewport = {
+ 0, 0,
+ float(sz.width()), float(sz.height()),
+ 0, 1
+ };
+ m_devFuncs->vkCmdSetViewport(cb, 0, 1, &viewport);
+
+ VkRect2D scissor = {
+ { 0, 0 },
+ { uint32_t(sz.width()), uint32_t(sz.height()) }
+ };
+ m_devFuncs->vkCmdSetScissor(cb, 0, 1, &scissor);
+
+ buildDrawCallsForFloor();
+ buildDrawCallsForItems();
+
+ m_devFuncs->vkCmdEndRenderPass(cmdBuf);
+}
+
+void Renderer::buildDrawCallsForItems()
+{
+ VkDevice dev = m_window->device();
+ VkCommandBuffer cb = m_window->currentCommandBuffer();
+
+ m_devFuncs->vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_itemMaterial.pipeline);
+
+ VkDeviceSize vbOffset = 0;
+ m_devFuncs->vkCmdBindVertexBuffers(cb, 0, 1, m_useLogo ? &m_logoVertexBuf : &m_blockVertexBuf, &vbOffset);
+ m_devFuncs->vkCmdBindVertexBuffers(cb, 1, 1, &m_instBuf, &vbOffset);
+
+ // Now provide offsets so that the two dynamic buffers point to the
+ // beginning of the vertex and fragment uniform data for the current frame.
+ uint32_t frameUniOffset = m_window->currentFrame() * (m_itemMaterial.vertUniSize + m_itemMaterial.fragUniSize);
+ uint32_t frameUniOffsets[] = { frameUniOffset, frameUniOffset };
+ m_devFuncs->vkCmdBindDescriptorSets(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_itemMaterial.pipelineLayout, 0, 1,
+ &m_itemMaterial.descSet, 2, frameUniOffsets);
+
+ if (m_animating)
+ m_rotation += 0.5;
+
+ if (m_animating || m_vpDirty) {
+ if (m_vpDirty)
+ --m_vpDirty;
+ QMatrix4x4 vp, model;
+ QMatrix3x3 modelNormal;
+ QVector3D eyePos;
+ getMatrices(&vp, &model, &modelNormal, &eyePos);
+
+ // Map the uniform data for the current frame, ignore the geometry data at
+ // the beginning and the uniforms for other frames.
+ quint8 *p;
+ VkResult err = m_devFuncs->vkMapMemory(dev, m_bufMem,
+ m_itemMaterial.uniMemStartOffset + frameUniOffset,
+ m_itemMaterial.vertUniSize + m_itemMaterial.fragUniSize,
+ 0, reinterpret_cast<void **>(&p));
+ if (err != VK_SUCCESS)
+ qFatal("Failed to map memory: %d", err);
+
+ // Vertex shader uniforms
+ memcpy(p, vp.constData(), 64);
+ memcpy(p + 64, model.constData(), 64);
+ const float *mnp = modelNormal.constData();
+ memcpy(p + 128, mnp, 12);
+ memcpy(p + 128 + 16, mnp + 3, 12);
+ memcpy(p + 128 + 32, mnp + 6, 12);
+
+ // Fragment shader uniforms
+ p += m_itemMaterial.vertUniSize;
+ writeFragUni(p, eyePos);
+
+ m_devFuncs->vkUnmapMemory(dev, m_bufMem);
+ }
+
+ m_devFuncs->vkCmdDraw(cb, (m_useLogo ? m_logoMesh.data() : m_blockMesh.data())->vertexCount, m_instCount, 0, 0);
+}
+
+void Renderer::buildDrawCallsForFloor()
+{
+ VkCommandBuffer cb = m_window->currentCommandBuffer();
+
+ m_devFuncs->vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_floorMaterial.pipeline);
+
+ VkDeviceSize vbOffset = 0;
+ m_devFuncs->vkCmdBindVertexBuffers(cb, 0, 1, &m_floorVertexBuf, &vbOffset);
+
+ QMatrix4x4 mvp = m_proj * m_cam.viewMatrix() * m_floorModel;
+ m_devFuncs->vkCmdPushConstants(cb, m_floorMaterial.pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, 64, mvp.constData());
+ float color[] = { 0.67f, 1.0f, 0.2f };
+ m_devFuncs->vkCmdPushConstants(cb, m_floorMaterial.pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 64, 12, color);
+
+ m_devFuncs->vkCmdDraw(cb, 4, 1, 0, 0);
+}
+
+void Renderer::addNew()
+{
+ QMutexLocker locker(&m_guiMutex);
+ m_instCount = qMin(m_instCount + 16, MAX_INSTANCES);
+}
+
+void Renderer::yaw(float degrees)
+{
+ QMutexLocker locker(&m_guiMutex);
+ m_cam.yaw(degrees);
+ markViewProjDirty();
+}
+
+void Renderer::pitch(float degrees)
+{
+ QMutexLocker locker(&m_guiMutex);
+ m_cam.pitch(degrees);
+ markViewProjDirty();
+}
+
+void Renderer::walk(float amount)
+{
+ QMutexLocker locker(&m_guiMutex);
+ m_cam.walk(amount);
+ markViewProjDirty();
+}
+
+void Renderer::strafe(float amount)
+{
+ QMutexLocker locker(&m_guiMutex);
+ m_cam.strafe(amount);
+ markViewProjDirty();
+}
+
+void Renderer::setUseLogo(bool b)
+{
+ QMutexLocker locker(&m_guiMutex);
+ m_useLogo = b;
+ if (!m_animating)
+ m_window->requestUpdate();
+}
diff --git a/examples/vulkan/hellovulkancubes/renderer.h b/examples/vulkan/hellovulkancubes/renderer.h
new file mode 100644
index 0000000000..60bb48377e
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/renderer.h
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RENDERER_H
+#define RENDERER_H
+
+#include "vulkanwindow.h"
+#include "mesh.h"
+#include "shader.h"
+#include "camera.h"
+#include <QFutureWatcher>
+#include <QMutex>
+
+class Renderer : public QVulkanWindowRenderer
+{
+public:
+ Renderer(VulkanWindow *w, int initialCount);
+
+ void preInitResources() override;
+ void initResources() override;
+ void initSwapChainResources() override;
+ void releaseSwapChainResources() override;
+ void releaseResources() override;
+
+ void startNextFrame() override;
+
+ bool animating() const { return m_animating; }
+ void setAnimating(bool a) { m_animating = a; }
+
+ int instanceCount() const { return m_instCount; }
+ void addNew();
+
+ void yaw(float degrees);
+ void pitch(float degrees);
+ void walk(float amount);
+ void strafe(float amount);
+
+ void setUseLogo(bool b);
+
+private:
+ void createPipelines();
+ void createItemPipeline();
+ void createFloorPipeline();
+ void ensureBuffers();
+ void ensureInstanceBuffer();
+ void getMatrices(QMatrix4x4 *mvp, QMatrix4x4 *model, QMatrix3x3 *modelNormal, QVector3D *eyePos);
+ void writeFragUni(quint8 *p, const QVector3D &eyePos);
+ void buildFrame();
+ void buildDrawCallsForItems();
+ void buildDrawCallsForFloor();
+
+ void markViewProjDirty() { m_vpDirty = m_window->concurrentFrameCount(); }
+
+ VulkanWindow *m_window;
+ QVulkanDeviceFunctions *m_devFuncs;
+
+ bool m_useLogo = false;
+ Mesh m_blockMesh;
+ Mesh m_logoMesh;
+ VkBuffer m_blockVertexBuf = VK_NULL_HANDLE;
+ VkBuffer m_logoVertexBuf = VK_NULL_HANDLE;
+ struct {
+ VkDeviceSize vertUniSize;
+ VkDeviceSize fragUniSize;
+ VkDeviceSize uniMemStartOffset;
+ Shader vs;
+ Shader fs;
+ VkDescriptorPool descPool = VK_NULL_HANDLE;
+ VkDescriptorSetLayout descSetLayout = VK_NULL_HANDLE;
+ VkDescriptorSet descSet;
+ VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
+ VkPipeline pipeline = VK_NULL_HANDLE;
+ } m_itemMaterial;
+
+ VkBuffer m_floorVertexBuf = VK_NULL_HANDLE;
+ struct {
+ Shader vs;
+ Shader fs;
+ VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
+ VkPipeline pipeline = VK_NULL_HANDLE;
+ } m_floorMaterial;
+
+ VkDeviceMemory m_bufMem = VK_NULL_HANDLE;
+ VkBuffer m_uniBuf = VK_NULL_HANDLE;
+
+ VkPipelineCache m_pipelineCache = VK_NULL_HANDLE;
+ QFuture<void> m_pipelinesFuture;
+
+ QVector3D m_lightPos;
+ Camera m_cam;
+
+ QMatrix4x4 m_proj;
+ int m_vpDirty = 0;
+ QMatrix4x4 m_floorModel;
+
+ bool m_animating;
+ float m_rotation = 0.0f;
+
+ int m_instCount;
+ int m_preparedInstCount = 0;
+ QByteArray m_instData;
+ VkBuffer m_instBuf = VK_NULL_HANDLE;
+ VkDeviceMemory m_instBufMem = VK_NULL_HANDLE;
+
+ QFutureWatcher<void> m_frameWatcher;
+ bool m_framePending;
+
+ QMutex m_guiMutex;
+};
+
+#endif
diff --git a/examples/vulkan/hellovulkancubes/shader.cpp b/examples/vulkan/hellovulkancubes/shader.cpp
new file mode 100644
index 0000000000..e1c01c6842
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/shader.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "shader.h"
+#include <QtConcurrentRun>
+#include <QFile>
+#include <QVulkanDeviceFunctions>
+
+void Shader::load(QVulkanInstance *inst, VkDevice dev, const QString &fn)
+{
+ reset();
+ m_maybeRunning = true;
+ m_future = QtConcurrent::run([inst, dev, fn]() {
+ ShaderData sd;
+ QFile f(fn);
+ if (!f.open(QIODevice::ReadOnly)) {
+ qWarning("Failed to open %s", qPrintable(fn));
+ return sd;
+ }
+ QByteArray blob = f.readAll();
+ VkShaderModuleCreateInfo shaderInfo;
+ memset(&shaderInfo, 0, sizeof(shaderInfo));
+ shaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+ shaderInfo.codeSize = blob.size();
+ shaderInfo.pCode = reinterpret_cast<const uint32_t *>(blob.constData());
+ VkResult err = inst->deviceFunctions(dev)->vkCreateShaderModule(dev, &shaderInfo, nullptr, &sd.shaderModule);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create shader module: %d", err);
+ return sd;
+ }
+ return sd;
+ });
+}
+
+ShaderData *Shader::data()
+{
+ if (m_maybeRunning && !m_data.isValid())
+ m_data = m_future.result();
+
+ return &m_data;
+}
+
+void Shader::reset()
+{
+ *data() = ShaderData();
+ m_maybeRunning = false;
+}
diff --git a/examples/vulkan/hellovulkancubes/shader.h b/examples/vulkan/hellovulkancubes/shader.h
new file mode 100644
index 0000000000..265868d2b0
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/shader.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SHADER_H
+#define SHADER_H
+
+#include <QVulkanInstance>
+#include <QFuture>
+
+struct ShaderData
+{
+ bool isValid() const { return shaderModule != VK_NULL_HANDLE; }
+ VkShaderModule shaderModule = VK_NULL_HANDLE;
+};
+
+class Shader
+{
+public:
+ void load(QVulkanInstance *inst, VkDevice dev, const QString &fn);
+ ShaderData *data();
+ bool isValid() { return data()->isValid(); }
+ void reset();
+
+private:
+ bool m_maybeRunning = false;
+ QFuture<ShaderData> m_future;
+ ShaderData m_data;
+};
+
+#endif
diff --git a/examples/vulkan/hellovulkancubes/vulkanwindow.cpp b/examples/vulkan/hellovulkancubes/vulkanwindow.cpp
new file mode 100644
index 0000000000..9a4eaf1901
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/vulkanwindow.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "vulkanwindow.h"
+#include "renderer.h"
+#include <QMouseEvent>
+#include <QKeyEvent>
+
+VulkanWindow::VulkanWindow(bool dbg)
+ : m_debug(dbg)
+{
+}
+
+QVulkanWindowRenderer *VulkanWindow::createRenderer()
+{
+ m_renderer = new Renderer(this, 128);
+ return m_renderer;
+}
+
+void VulkanWindow::addNew()
+{
+ m_renderer->addNew();
+}
+
+void VulkanWindow::togglePaused()
+{
+ m_renderer->setAnimating(!m_renderer->animating());
+}
+
+void VulkanWindow::meshSwitched(bool enable)
+{
+ m_renderer->setUseLogo(enable);
+}
+
+void VulkanWindow::mousePressEvent(QMouseEvent *e)
+{
+ m_pressed = true;
+ m_lastPos = e->pos();
+}
+
+void VulkanWindow::mouseReleaseEvent(QMouseEvent *)
+{
+ m_pressed = false;
+}
+
+void VulkanWindow::mouseMoveEvent(QMouseEvent *e)
+{
+ if (!m_pressed)
+ return;
+
+ int dx = e->pos().x() - m_lastPos.x();
+ int dy = e->pos().y() - m_lastPos.y();
+
+ if (dy)
+ m_renderer->pitch(dy / 10.0f);
+
+ if (dx)
+ m_renderer->yaw(dx / 10.0f);
+
+ m_lastPos = e->pos();
+}
+
+void VulkanWindow::keyPressEvent(QKeyEvent *e)
+{
+ const float amount = e->modifiers().testFlag(Qt::ShiftModifier) ? 1.0f : 0.1f;
+ switch (e->key()) {
+ case Qt::Key_W:
+ m_renderer->walk(amount);
+ break;
+ case Qt::Key_S:
+ m_renderer->walk(-amount);
+ break;
+ case Qt::Key_A:
+ m_renderer->strafe(-amount);
+ break;
+ case Qt::Key_D:
+ m_renderer->strafe(amount);
+ break;
+ default:
+ break;
+ }
+}
+
+int VulkanWindow::instanceCount() const
+{
+ return m_renderer->instanceCount();
+}
diff --git a/examples/vulkan/hellovulkancubes/vulkanwindow.h b/examples/vulkan/hellovulkancubes/vulkanwindow.h
new file mode 100644
index 0000000000..d085c0bde7
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/vulkanwindow.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef VULKANWINDOW_H
+#define VULKANWINDOW_H
+
+#include <QVulkanWindow>
+
+class Renderer;
+
+class VulkanWindow : public QVulkanWindow
+{
+public:
+ VulkanWindow(bool dbg);
+
+ QVulkanWindowRenderer *createRenderer() override;
+
+ bool isDebugEnabled() const { return m_debug; }
+ int instanceCount() const;
+
+public slots:
+ void addNew();
+ void togglePaused();
+ void meshSwitched(bool enable);
+
+private:
+ void mousePressEvent(QMouseEvent *) override;
+ void mouseReleaseEvent(QMouseEvent *) override;
+ void mouseMoveEvent(QMouseEvent *) override;
+ void keyPressEvent(QKeyEvent *) override;
+
+ bool m_debug;
+ Renderer *m_renderer;
+ bool m_pressed = false;
+ QPoint m_lastPos;
+};
+
+#endif
diff --git a/examples/vulkan/shared/block.buf b/examples/vulkan/shared/block.buf
new file mode 100644
index 0000000000..28ec2620bd
--- /dev/null
+++ b/examples/vulkan/shared/block.buf
Binary files differ
diff --git a/examples/vulkan/shared/block.txt b/examples/vulkan/shared/block.txt
new file mode 100644
index 0000000000..a6b66b83cc
--- /dev/null
+++ b/examples/vulkan/shared/block.txt
@@ -0,0 +1,100 @@
+# Blender v2.78 (sub 0) OBJ File: ''
+# www.blender.org
+mtllib block.mtl
+o Cube_Cube.001
+v 0.450000 -0.500000 -0.450000
+v 0.450000 -0.500000 0.450000
+v -0.450000 -0.500000 0.450000
+v -0.450000 -0.500000 -0.450000
+v -0.500000 0.450000 0.450000
+v -0.500000 0.450000 -0.450000
+v -0.500000 -0.450000 -0.450000
+v -0.500000 -0.450000 0.450000
+v -0.450000 0.500000 -0.450000
+v -0.450000 0.500000 0.450000
+v 0.450000 0.500000 0.450000
+v 0.450000 0.500000 -0.450000
+v -0.450000 0.450000 -0.500000
+v 0.450000 0.450000 -0.500000
+v 0.450000 -0.450000 -0.500000
+v -0.450000 -0.450000 -0.500000
+v 0.450000 0.450000 0.500000
+v -0.450000 0.450000 0.500000
+v -0.450000 -0.450000 0.500000
+v 0.450000 -0.450000 0.500000
+v 0.500000 -0.450000 -0.450000
+v 0.500000 0.450000 -0.450000
+v 0.500000 -0.450000 0.450000
+v 0.500000 0.450000 0.450000
+vn 0.0000 -1.0000 -0.0000
+vn -1.0000 0.0000 0.0000
+vn 0.0000 1.0000 0.0000
+vn 0.0000 0.0000 -1.0000
+vn 0.0000 -0.0000 1.0000
+vn 0.5774 -0.5773 -0.5774
+vn 0.5774 0.5774 -0.5774
+vn 0.5774 -0.5774 0.5774
+vn 0.5774 0.5773 0.5774
+vn -0.5774 -0.5773 -0.5774
+vn -0.5773 0.5774 -0.5774
+vn -0.5774 -0.5774 0.5774
+vn -0.5774 0.5773 0.5774
+vn 0.7071 0.0000 -0.7071
+vn 0.7071 0.7071 0.0000
+vn 0.7071 -0.0000 0.7071
+vn 0.7071 -0.7071 -0.0000
+vn 0.0000 0.7071 0.7071
+vn -0.7071 -0.0000 0.7071
+vn 0.0000 -0.7071 0.7071
+vn -0.7071 0.7071 0.0000
+vn -0.7071 0.0000 -0.7071
+vn -0.7071 -0.7071 -0.0000
+vn 0.0000 0.7071 -0.7071
+vn 0.0000 -0.7071 -0.7071
+vn 1.0000 0.0000 0.0000
+usemtl None
+s 1
+f 2//1 4//1 1//1
+f 6//2 8//2 5//2
+f 10//3 12//3 9//3
+f 14//4 16//4 13//4
+f 18//5 20//5 17//5
+f 15//6 21//6 1//6
+f 14//7 12//7 22//7
+f 20//8 2//8 23//8
+f 11//9 17//9 24//9
+f 16//10 4//10 7//10
+f 9//11 13//11 6//11
+f 8//12 3//12 19//12
+f 10//13 5//13 18//13
+f 14//14 21//14 15//14
+f 11//15 22//15 12//15
+f 20//16 24//16 17//16
+f 1//17 23//17 2//17
+f 10//18 17//18 11//18
+f 8//19 18//19 5//19
+f 2//20 19//20 3//20
+f 9//21 5//21 10//21
+f 16//22 6//22 13//22
+f 3//23 7//23 4//23
+f 12//24 13//24 9//24
+f 4//25 15//25 1//25
+f 24//26 21//26 22//26
+f 2//1 3//1 4//1
+f 6//2 7//2 8//2
+f 10//3 11//3 12//3
+f 14//4 15//4 16//4
+f 18//5 19//5 20//5
+f 14//14 22//14 21//14
+f 11//15 24//15 22//15
+f 20//16 23//16 24//16
+f 1//17 21//17 23//17
+f 10//18 18//18 17//18
+f 8//19 19//19 18//19
+f 2//20 20//20 19//20
+f 9//21 6//21 5//21
+f 16//22 7//22 6//22
+f 3//23 8//23 7//23
+f 12//24 14//24 13//24
+f 4//25 16//25 15//25
+f 24//26 23//26 21//26
diff --git a/examples/vulkan/shared/objconvert.js b/examples/vulkan/shared/objconvert.js
new file mode 100644
index 0000000000..9b49e3cdac
--- /dev/null
+++ b/examples/vulkan/shared/objconvert.js
@@ -0,0 +1,241 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+var fs = require('fs');
+
+var metadata = {
+ vertexCount: 0,
+ aabb: [[null, null], [null, null], [null, null]],
+ emitVertex: function(v) {
+ ++metadata.vertexCount;
+ var aabb = metadata.aabb;
+ if (aabb[0][0] === null || v[0] < aabb[0][0]) // min x
+ aabb[0][0] = v[0];
+ if (aabb[0][1] === null || v[0] > aabb[0][1]) // max x
+ aabb[0][1] = v[0];
+ if (aabb[1][0] === null || v[1] < aabb[1][0]) // min y
+ aabb[1][0] = v[1];
+ if (aabb[1][1] === null || v[1] > aabb[1][1]) // max y
+ aabb[1][1] = v[1];
+ if (aabb[2][0] === null || v[2] < aabb[2][0]) // min z
+ aabb[2][0] = v[2];
+ if (aabb[2][1] === null || v[2] > aabb[2][1]) // max z
+ aabb[2][1] = v[2];
+ },
+ getBuffer: function() {
+ var aabb = metadata.aabb;
+ console.log(metadata.vertexCount + " vertices");
+ console.log("AABB: " + aabb[0][0] + ".." + aabb[0][1]
+ + ", " + aabb[1][0] + ".." + aabb[1][1]
+ + ", " + aabb[2][0] + ".." + aabb[2][1]);
+ var buf = new Buffer((2 + 6) * 4);
+ var format = 1, p = 0;
+ buf.writeUInt32LE(format, p++);
+ buf.writeUInt32LE(metadata.vertexCount, p++ * 4);
+ for (var i = 0; i < 3; ++i) {
+ buf.writeFloatLE(aabb[i][0], p++ * 4);
+ buf.writeFloatLE(aabb[i][1], p++ * 4);
+ }
+ return buf;
+ }
+};
+
+function makeVec(s, n) {
+ var v = [];
+ s.split(' ').forEach(function (coordStr) {
+ var coord = parseFloat(coordStr);
+ if (!isNaN(coord))
+ v.push(coord);
+ });
+ if (v.length != n) {
+ console.error("Wrong vector size, expected " + n + ", got " + v.length);
+ process.exit();
+ }
+ return v;
+}
+
+function parseObj(filename, callback) {
+ fs.readFile(filename, "ascii", function (err, data) {
+ if (err)
+ throw err;
+ var groupCount = 0;
+ var parsed = { 'vertices': [], 'normals': [], 'texcoords': [], 'links': [] };
+ var missingTexCount = 0, missingNormCount = 0;
+ data.split('\n').forEach(function (line) {
+ var s = line.trim();
+ if (!s.length || groupCount > 1)
+ return;
+ if (s[0] === '#')
+ return;
+ if (s[0] === 'g') {
+ ++groupCount;
+ } else if (s.substr(0, 2) === "v ") {
+ parsed.vertices.push(makeVec(s, 3));
+ } else if (s.substr(0, 3) === "vn ") {
+ parsed.normals.push(makeVec(s, 3));
+ } else if (s.substr(0, 3) === "vt ") {
+ parsed.texcoords.push(makeVec(s, 2));
+ } else if (s.substr(0, 2) === "f ") {
+ var refs = s.split(' ');
+ var vertCount = refs.length - 1;
+ if (vertCount != 3)
+ console.warn("Face " + parsed.links.length / 3 + " has " + vertCount + " vertices! (not triangulated?)");
+ for (var i = 1, ie = Math.min(4, refs.length); i < ie; ++i) {
+ var refComps = refs[i].split('/');
+ var vertIndex = parseInt(refComps[0]) - 1;
+ var texIndex = -1;
+ if (refComps.length >= 2 && refComps[1].length)
+ texIndex = parseInt(refComps[1]) - 1;
+ var normIndex = -1;
+ if (refComps.length >= 3 && refComps[2].length)
+ normIndex = parseInt(refComps[2]) - 1;
+ parsed.links.push([vertIndex, texIndex, normIndex]);
+ if (texIndex == -1)
+ ++missingTexCount;
+ if (normIndex == -1)
+ ++missingNormCount;
+ }
+ }
+ });
+ console.log(missingTexCount + " missing texture coordinates, " + missingNormCount + " missing normals");
+ callback(parsed);
+ });
+}
+
+function fillVert(src, index, dst, elemCount, isVertexCoord) {
+ var vertex = [];
+ if (index >= 0) {
+ for (var i = 0; i < elemCount; ++i) {
+ var elem = src[index][i];
+ if (isVertexCoord)
+ vertex.push(elem);
+ dst.buf.writeFloatLE(elem, dst.bufptr++ * 4);
+ }
+ if (vertex.length == 3)
+ metadata.emitVertex(vertex);
+ } else {
+ if (isVertexCoord) {
+ console.error("Missing vertex");
+ process.exit();
+ }
+ for (var i = 0; i < elemCount; ++i)
+ dst.buf.writeFloatLE(0, dst.bufptr++ * 4);
+ }
+ return vertex;
+}
+
+function normalize(v) {
+ var len = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
+ if (len == 0.0 || len == 1.0)
+ return;
+ len = Math.sqrt(len);
+ return [ v[0] / len, v[1] / len, v[2] / len ];
+}
+
+function surfaceNormal(a, b, c) {
+ var u = [ b[0] - a[0], b[1] - a[1], b[2] - a[2] ];
+ var v = [ c[0] - a[0], c[1] - a[1], c[2] - a[2] ];
+ var result = [ u[1] * v[2] - u[2] * v[1],
+ u[2] * v[0] - u[0] * v[2],
+ u[0] * v[1] - u[1] * v[0] ];
+ return normalize(result);
+}
+
+function objDataToBuf(parsed) {
+ var floatCount = parsed.links.length * (3 + 2 + 3);
+ var buf = new Buffer(floatCount * 4);
+ var dst = { 'buf': buf, 'bufptr': 0 };
+ var tri = [];
+ var genNormals = false;
+ var genNormCount = 0;
+ for (var i = 0; i < parsed.links.length; ++i) {
+ var link = parsed.links[i];
+ var vertIndex = link[0], texIndex = link[1], normIndex = link[2];
+ tri.push(fillVert(parsed.vertices, vertIndex, dst, 3, true));
+ fillVert(parsed.texcoords, texIndex, dst, 2);
+ fillVert(parsed.normals, normIndex, dst, 3);
+ if (normIndex == -1)
+ genNormals = true;
+ if (tri.length == 3) {
+ if (genNormals) {
+ var norm = surfaceNormal(tri[0], tri[1], tri[2]);
+ for (var nvIdx = 0; nvIdx < 3; ++nvIdx) {
+ dst.buf.writeFloatLE(norm[0], (dst.bufptr - 3 - nvIdx * 8) * 4);
+ dst.buf.writeFloatLE(norm[1], (dst.bufptr - 2 - nvIdx * 8) * 4);
+ dst.buf.writeFloatLE(norm[2], (dst.bufptr - 1 - nvIdx * 8) * 4);
+ }
+ genNormCount += 3;
+ }
+ tri = [];
+ }
+ }
+ if (genNormCount)
+ console.log("Generated " + genNormCount + " normals");
+ return buf;
+}
+
+var inFilename = process.argv[2];
+var outFilename = process.argv[3];
+
+if (process.argv.length < 4) {
+ console.log("Usage: objconvert file.obj file.buf");
+ process.exit();
+}
+
+parseObj(inFilename, function (parsed) {
+ var buf = objDataToBuf(parsed);
+ var f = fs.createWriteStream(outFilename);
+ f.on("error", function (e) { console.error(e); });
+ f.write(metadata.getBuffer());
+ f.write(buf);
+ f.end();
+ console.log("Written to " + outFilename + ", format is:");
+ console.log(" uint32 version, uint32 vertex_count, float32 aabb[6], vertex_count * (float32 vertex[3], float32 texcoord[2], float32 normal[3])");
+});
diff --git a/examples/vulkan/shared/qt_logo.buf b/examples/vulkan/shared/qt_logo.buf
new file mode 100644
index 0000000000..316ec41aee
--- /dev/null
+++ b/examples/vulkan/shared/qt_logo.buf
Binary files differ
diff --git a/examples/vulkan/shared/qt_logo.txt b/examples/vulkan/shared/qt_logo.txt
new file mode 100644
index 0000000000..167b8a4caf
--- /dev/null
+++ b/examples/vulkan/shared/qt_logo.txt
@@ -0,0 +1,2912 @@
+# Blender v2.77 (sub 0) OBJ File: 'qt_logo.blend'
+# www.blender.org
+o qt_logo_qt_logo_mesh
+v 0.500000 0.030000 -0.271909
+v 0.500000 0.030000 -0.234087
+v 0.500000 0.030000 0.229669
+v 0.361282 0.030000 0.368353
+v -0.369121 0.030000 0.368353
+v -0.403885 0.030000 0.368353
+v -0.500000 0.030000 0.368353
+v -0.500000 0.030000 0.272263
+v -0.500000 0.030000 0.234440
+v -0.500000 0.030000 -0.229316
+v -0.361282 0.030000 -0.368000
+v 0.369121 0.030000 -0.368000
+v 0.403886 0.030000 -0.368000
+v 0.500000 0.030000 -0.368000
+v -0.014123 0.030000 0.177038
+v -0.008432 0.030000 0.172481
+v -0.003036 0.030000 0.167611
+v 0.002070 0.030000 0.162429
+v 0.006887 0.030000 0.156934
+v 0.011418 0.030000 0.151127
+v 0.015664 0.030000 0.145008
+v 0.019629 0.030000 0.138577
+v 0.023315 0.030000 0.131833
+v 0.026724 0.030000 0.124776
+v 0.029858 0.030000 0.117408
+v 0.032720 0.030000 0.109727
+v 0.035255 0.030000 0.101769
+v 0.037575 0.030000 0.093399
+v 0.039680 0.030000 0.084618
+v 0.041569 0.030000 0.075425
+v 0.043240 0.030000 0.065820
+v 0.044692 0.030000 0.055804
+v 0.045923 0.030000 0.045375
+v 0.046934 0.030000 0.034535
+v 0.047722 0.030000 0.023284
+v 0.048286 0.030000 0.011620
+v 0.048626 0.030000 -0.000455
+v 0.048739 0.030000 -0.012942
+v 0.048469 0.030000 -0.031775
+v 0.047658 0.030000 -0.049771
+v 0.046305 0.030000 -0.066929
+v 0.044409 0.030000 -0.083249
+v 0.041969 0.030000 -0.098732
+v 0.038983 0.030000 -0.113377
+v 0.035450 0.030000 -0.127184
+v 0.031369 0.030000 -0.140154
+v 0.026739 0.030000 -0.152286
+v 0.021559 0.030000 -0.163580
+v 0.015828 0.030000 -0.174037
+v 0.009543 0.030000 -0.183656
+v 0.002656 0.030000 -0.192551
+v -0.005054 0.030000 -0.200667
+v -0.013585 0.030000 -0.208004
+v -0.022937 0.030000 -0.214563
+v -0.033107 0.030000 -0.220347
+v -0.044095 0.030000 -0.225355
+v -0.055900 0.030000 -0.229590
+v -0.068520 0.030000 -0.233052
+v -0.081954 0.030000 -0.235742
+v -0.096201 0.030000 -0.237663
+v -0.111260 0.030000 -0.238814
+v -0.127130 0.030000 -0.239198
+v -0.143000 0.030000 -0.238808
+v -0.158061 0.030000 -0.237638
+v -0.172312 0.030000 -0.235689
+v -0.185753 0.030000 -0.232963
+v -0.198385 0.030000 -0.229461
+v -0.210208 0.030000 -0.225185
+v -0.221221 0.030000 -0.220134
+v -0.231425 0.030000 -0.214311
+v -0.240819 0.030000 -0.207716
+v -0.249404 0.030000 -0.200351
+v -0.257179 0.030000 -0.192217
+v -0.264144 0.030000 -0.183315
+v -0.270435 0.030000 -0.173618
+v -0.276186 0.030000 -0.163098
+v -0.281394 0.030000 -0.151754
+v -0.286059 0.030000 -0.139586
+v -0.290179 0.030000 -0.126595
+v -0.293754 0.030000 -0.112781
+v -0.296782 0.030000 -0.098143
+v -0.299263 0.030000 -0.082682
+v -0.301194 0.030000 -0.066397
+v -0.302575 0.030000 -0.049288
+v -0.303404 0.030000 -0.031357
+v -0.303681 0.030000 -0.012601
+v -0.303411 0.030000 0.006061
+v -0.302602 0.030000 0.023884
+v -0.301253 0.030000 0.040864
+v -0.299364 0.030000 0.056999
+v -0.296935 0.030000 0.072288
+v -0.293967 0.030000 0.086726
+v -0.290460 0.030000 0.100313
+v -0.286412 0.030000 0.113046
+v -0.281825 0.030000 0.124922
+v -0.276698 0.030000 0.135939
+v -0.271032 0.030000 0.146095
+v -0.264826 0.030000 0.155387
+v -0.257932 0.030000 0.163877
+v -0.250200 0.030000 0.171629
+v -0.241634 0.030000 0.178643
+v -0.232233 0.030000 0.184918
+v -0.221998 0.030000 0.190455
+v -0.210932 0.030000 0.195254
+v -0.199035 0.030000 0.199315
+v -0.186309 0.030000 0.202637
+v -0.172754 0.030000 0.205221
+v -0.158371 0.030000 0.207067
+v -0.143163 0.030000 0.208174
+v -0.127130 0.030000 0.208543
+v -0.122805 0.030000 0.208515
+v -0.118691 0.030000 0.208431
+v -0.114786 0.030000 0.208293
+v -0.111086 0.030000 0.208101
+v -0.107590 0.030000 0.207858
+v -0.104294 0.030000 0.207563
+v -0.101198 0.030000 0.207219
+v -0.098298 0.030000 0.206827
+v -0.095593 0.030000 0.206387
+v -0.093079 0.030000 0.205901
+v -0.090754 0.030000 0.205370
+v -0.088616 0.030000 0.204795
+v -0.032379 0.030000 0.297137
+v 0.032720 0.030000 0.266811
+v 0.027981 0.030000 0.259139
+v 0.022692 0.030000 0.250576
+v 0.017036 0.030000 0.241420
+v 0.011197 0.030000 0.231966
+v 0.005358 0.030000 0.222513
+v -0.000298 0.030000 0.213356
+v -0.005587 0.030000 0.204794
+v -0.010326 0.030000 0.197122
+v -0.014331 0.030000 0.190638
+v -0.017419 0.030000 0.185639
+v -0.019406 0.030000 0.182422
+v -0.020109 0.030000 0.181283
+v 0.291411 0.030000 0.137327
+v 0.286764 0.030000 0.137511
+v 0.281577 0.030000 0.137715
+v 0.276031 0.030000 0.137934
+v 0.270305 0.030000 0.138160
+v 0.264578 0.030000 0.138386
+v 0.259032 0.030000 0.138605
+v 0.253845 0.030000 0.138810
+v 0.249198 0.030000 0.138993
+v 0.245271 0.030000 0.139148
+v 0.242243 0.030000 0.139267
+v 0.240294 0.030000 0.139344
+v 0.239605 0.030000 0.139372
+v 0.235884 0.030000 0.139286
+v 0.232394 0.030000 0.139029
+v 0.229135 0.030000 0.138600
+v 0.226110 0.030000 0.137996
+v 0.223322 0.030000 0.137217
+v 0.220774 0.030000 0.136262
+v 0.218466 0.030000 0.135130
+v 0.216403 0.030000 0.133819
+v 0.214585 0.030000 0.132328
+v 0.213017 0.030000 0.130656
+v 0.211699 0.030000 0.128802
+v 0.210634 0.030000 0.126764
+v 0.209732 0.030000 0.124535
+v 0.208903 0.030000 0.121937
+v 0.208147 0.030000 0.118969
+v 0.207465 0.030000 0.115633
+v 0.206860 0.030000 0.111927
+v 0.206331 0.030000 0.107853
+v 0.205880 0.030000 0.103409
+v 0.205509 0.030000 0.098596
+v 0.205218 0.030000 0.093413
+v 0.205009 0.030000 0.087862
+v 0.204882 0.030000 0.081942
+v 0.204840 0.030000 0.075652
+v 0.204840 0.030000 -0.063713
+v 0.292093 0.030000 -0.063713
+v 0.292093 0.030000 -0.122662
+v 0.204840 0.030000 -0.122662
+v 0.204840 0.030000 -0.214664
+v 0.136333 0.030000 -0.214664
+v 0.136333 0.030000 -0.122662
+v 0.087935 0.030000 -0.122662
+v 0.087935 0.030000 -0.064054
+v 0.136333 0.030000 -0.064054
+v 0.136333 0.030000 -0.050850
+v 0.136333 0.030000 -0.036113
+v 0.136333 0.030000 -0.020353
+v 0.136333 0.030000 -0.004083
+v 0.136333 0.030000 0.012188
+v 0.136333 0.030000 0.027947
+v 0.136333 0.030000 0.042685
+v 0.136333 0.030000 0.055889
+v 0.136333 0.030000 0.067048
+v 0.136333 0.030000 0.075652
+v 0.136333 0.030000 0.081189
+v 0.136333 0.030000 0.083148
+v 0.136475 0.030000 0.094258
+v 0.136899 0.030000 0.104757
+v 0.137605 0.030000 0.114646
+v 0.138592 0.030000 0.123924
+v 0.139858 0.030000 0.132592
+v 0.141403 0.030000 0.140649
+v 0.143224 0.030000 0.148096
+v 0.145321 0.030000 0.154932
+v 0.147692 0.030000 0.161158
+v 0.150337 0.030000 0.166773
+v 0.153254 0.030000 0.171778
+v 0.156442 0.030000 0.176172
+v 0.159999 0.030000 0.180091
+v 0.164025 0.030000 0.183669
+v 0.168520 0.030000 0.186906
+v 0.173483 0.030000 0.189802
+v 0.178915 0.030000 0.192358
+v 0.184816 0.030000 0.194573
+v 0.191185 0.030000 0.196447
+v 0.198023 0.030000 0.197980
+v 0.205330 0.030000 0.199173
+v 0.213105 0.030000 0.200024
+v 0.221349 0.030000 0.200536
+v 0.230061 0.030000 0.200706
+v 0.233945 0.030000 0.200649
+v 0.238099 0.030000 0.200479
+v 0.242523 0.030000 0.200195
+v 0.247217 0.030000 0.199797
+v 0.252180 0.030000 0.199286
+v 0.257413 0.030000 0.198662
+v 0.262916 0.030000 0.197923
+v 0.268689 0.030000 0.197071
+v 0.274732 0.030000 0.196106
+v 0.281044 0.030000 0.195027
+v 0.287626 0.030000 0.193834
+v 0.294479 0.030000 0.192528
+v -0.042504 0.030000 -0.131451
+v -0.039308 0.030000 -0.123910
+v -0.036421 0.030000 -0.115714
+v -0.033843 0.030000 -0.106862
+v -0.031573 0.030000 -0.097352
+v -0.029610 0.030000 -0.087182
+v -0.027952 0.030000 -0.076353
+v -0.026597 0.030000 -0.064862
+v -0.025546 0.030000 -0.052708
+v -0.024797 0.030000 -0.039891
+v -0.024348 0.030000 -0.026409
+v -0.024199 0.030000 -0.012261
+v -0.024348 0.030000 0.001795
+v -0.024794 0.030000 0.015166
+v -0.025536 0.030000 0.027852
+v -0.026572 0.030000 0.039848
+v -0.027902 0.030000 0.051154
+v -0.029525 0.030000 0.061767
+v -0.031438 0.030000 0.071683
+v -0.033641 0.030000 0.080902
+v -0.036133 0.030000 0.089420
+v -0.038913 0.030000 0.097236
+v -0.041979 0.030000 0.104346
+v -0.045331 0.030000 0.110749
+v -0.049179 0.030000 0.116548
+v -0.053569 0.030000 0.121850
+v -0.058501 0.030000 0.126652
+v -0.063975 0.030000 0.130954
+v -0.069995 0.030000 0.134754
+v -0.076559 0.030000 0.138051
+v -0.083671 0.030000 0.140844
+v -0.091330 0.030000 0.143132
+v -0.099539 0.030000 0.144914
+v -0.108298 0.030000 0.146188
+v -0.117608 0.030000 0.146953
+v -0.127471 0.030000 0.147209
+v -0.137341 0.030000 0.146947
+v -0.146670 0.030000 0.146161
+v -0.155456 0.030000 0.144855
+v -0.163700 0.030000 0.143031
+v -0.171399 0.030000 0.140692
+v -0.178553 0.030000 0.137838
+v -0.185160 0.030000 0.134474
+v -0.191219 0.030000 0.130601
+v -0.196729 0.030000 0.126221
+v -0.201689 0.030000 0.121337
+v -0.206097 0.030000 0.115952
+v -0.209952 0.030000 0.110067
+v -0.213382 0.030000 0.103587
+v -0.216513 0.030000 0.096412
+v -0.219346 0.030000 0.088547
+v -0.221881 0.030000 0.079993
+v -0.224118 0.030000 0.070753
+v -0.226057 0.030000 0.060830
+v -0.227697 0.030000 0.050224
+v -0.229039 0.030000 0.038940
+v -0.230083 0.030000 0.026978
+v -0.230828 0.030000 0.014343
+v -0.231276 0.030000 0.001035
+v -0.231425 0.030000 -0.012942
+v -0.231269 0.030000 -0.027005
+v -0.230801 0.030000 -0.040404
+v -0.230024 0.030000 -0.053140
+v -0.228938 0.030000 -0.065215
+v -0.227544 0.030000 -0.076633
+v -0.225844 0.030000 -0.087395
+v -0.223838 0.030000 -0.097504
+v -0.221528 0.030000 -0.106963
+v -0.218915 0.030000 -0.115773
+v -0.216000 0.030000 -0.123937
+v -0.212785 0.030000 -0.131458
+v -0.209271 0.030000 -0.138337
+v -0.205266 0.030000 -0.144620
+v -0.200750 0.030000 -0.150350
+v -0.195723 0.030000 -0.155529
+v -0.190184 0.030000 -0.160157
+v -0.184134 0.030000 -0.164237
+v -0.177573 0.030000 -0.167769
+v -0.170501 0.030000 -0.170754
+v -0.162917 0.030000 -0.173194
+v -0.154823 0.030000 -0.175090
+v -0.146217 0.030000 -0.176442
+v -0.137100 0.030000 -0.177253
+v -0.127471 0.030000 -0.177523
+v -0.117843 0.030000 -0.177253
+v -0.108727 0.030000 -0.176442
+v -0.100125 0.030000 -0.175090
+v -0.092037 0.030000 -0.173194
+v -0.084466 0.030000 -0.170754
+v -0.077411 0.030000 -0.167769
+v -0.070875 0.030000 -0.164237
+v -0.064859 0.030000 -0.160157
+v -0.059363 0.030000 -0.155529
+v -0.054389 0.030000 -0.150350
+v -0.049939 0.030000 -0.144620
+v -0.046012 0.030000 -0.138337
+v 0.500000 -0.030000 -0.271909
+v 0.500000 -0.030000 -0.234087
+v 0.500000 -0.030000 0.229669
+v 0.361282 -0.030000 0.368353
+v -0.369121 -0.030000 0.368353
+v -0.403885 -0.030000 0.368353
+v -0.500000 -0.030000 0.368353
+v -0.500000 -0.030000 0.272263
+v -0.500000 -0.030000 0.234440
+v -0.500000 -0.030000 -0.229316
+v -0.361282 -0.030000 -0.368000
+v 0.369121 -0.030000 -0.368000
+v 0.403886 -0.030000 -0.368000
+v 0.500000 -0.030000 -0.368000
+v -0.014123 -0.030000 0.177038
+v -0.008432 -0.030000 0.172481
+v -0.003036 -0.030000 0.167611
+v 0.002070 -0.030000 0.162429
+v 0.006887 -0.030000 0.156934
+v 0.011418 -0.030000 0.151127
+v 0.015664 -0.030000 0.145008
+v 0.019629 -0.030000 0.138577
+v 0.023315 -0.030000 0.131833
+v 0.026724 -0.030000 0.124776
+v 0.029858 -0.030000 0.117408
+v 0.032720 -0.030000 0.109727
+v 0.035255 -0.030000 0.101769
+v 0.037575 -0.030000 0.093399
+v 0.039680 -0.030000 0.084618
+v 0.041569 -0.030000 0.075425
+v 0.043240 -0.030000 0.065820
+v 0.044692 -0.030000 0.055804
+v 0.045923 -0.030000 0.045375
+v 0.046934 -0.030000 0.034535
+v 0.047722 -0.030000 0.023284
+v 0.048286 -0.030000 0.011620
+v 0.048626 -0.030000 -0.000455
+v 0.048739 -0.030000 -0.012942
+v 0.048469 -0.030000 -0.031775
+v 0.047658 -0.030000 -0.049771
+v 0.046305 -0.030000 -0.066929
+v 0.044409 -0.030000 -0.083249
+v 0.041969 -0.030000 -0.098732
+v 0.038983 -0.030000 -0.113377
+v 0.035450 -0.030000 -0.127184
+v 0.031369 -0.030000 -0.140154
+v 0.026739 -0.030000 -0.152286
+v 0.021559 -0.030000 -0.163580
+v 0.015828 -0.030000 -0.174037
+v 0.009543 -0.030000 -0.183656
+v 0.002656 -0.030000 -0.192551
+v -0.005054 -0.030000 -0.200667
+v -0.013585 -0.030000 -0.208004
+v -0.022937 -0.030000 -0.214563
+v -0.033107 -0.030000 -0.220347
+v -0.044095 -0.030000 -0.225355
+v -0.055900 -0.030000 -0.229590
+v -0.068520 -0.030000 -0.233052
+v -0.081954 -0.030000 -0.235742
+v -0.096201 -0.030000 -0.237663
+v -0.111260 -0.030000 -0.238814
+v -0.127130 -0.030000 -0.239198
+v -0.143000 -0.030000 -0.238808
+v -0.158061 -0.030000 -0.237638
+v -0.172312 -0.030000 -0.235689
+v -0.185753 -0.030000 -0.232963
+v -0.198385 -0.030000 -0.229461
+v -0.210208 -0.030000 -0.225185
+v -0.221221 -0.030000 -0.220134
+v -0.231425 -0.030000 -0.214311
+v -0.240819 -0.030000 -0.207716
+v -0.249404 -0.030000 -0.200351
+v -0.257179 -0.030000 -0.192217
+v -0.264144 -0.030000 -0.183315
+v -0.270435 -0.030000 -0.173618
+v -0.276186 -0.030000 -0.163098
+v -0.281394 -0.030000 -0.151754
+v -0.286059 -0.030000 -0.139586
+v -0.290179 -0.030000 -0.126595
+v -0.293754 -0.030000 -0.112781
+v -0.296782 -0.030000 -0.098143
+v -0.299263 -0.030000 -0.082682
+v -0.301194 -0.030000 -0.066397
+v -0.302575 -0.030000 -0.049288
+v -0.303404 -0.030000 -0.031357
+v -0.303681 -0.030000 -0.012601
+v -0.303411 -0.030000 0.006061
+v -0.302602 -0.030000 0.023884
+v -0.301253 -0.030000 0.040864
+v -0.299364 -0.030000 0.056999
+v -0.296935 -0.030000 0.072288
+v -0.293967 -0.030000 0.086726
+v -0.290460 -0.030000 0.100313
+v -0.286412 -0.030000 0.113046
+v -0.281825 -0.030000 0.124922
+v -0.276698 -0.030000 0.135939
+v -0.271032 -0.030000 0.146095
+v -0.264826 -0.030000 0.155387
+v -0.257932 -0.030000 0.163877
+v -0.250200 -0.030000 0.171629
+v -0.241634 -0.030000 0.178643
+v -0.232233 -0.030000 0.184918
+v -0.221998 -0.030000 0.190455
+v -0.210932 -0.030000 0.195254
+v -0.199035 -0.030000 0.199315
+v -0.186309 -0.030000 0.202637
+v -0.172754 -0.030000 0.205221
+v -0.158371 -0.030000 0.207067
+v -0.143163 -0.030000 0.208174
+v -0.127130 -0.030000 0.208543
+v -0.122805 -0.030000 0.208515
+v -0.118691 -0.030000 0.208431
+v -0.114786 -0.030000 0.208293
+v -0.111086 -0.030000 0.208101
+v -0.107590 -0.030000 0.207858
+v -0.104294 -0.030000 0.207563
+v -0.101198 -0.030000 0.207219
+v -0.098298 -0.030000 0.206827
+v -0.095593 -0.030000 0.206387
+v -0.093079 -0.030000 0.205901
+v -0.090754 -0.030000 0.205370
+v -0.088616 -0.030000 0.204795
+v -0.032379 -0.030000 0.297137
+v 0.032720 -0.030000 0.266811
+v 0.027981 -0.030000 0.259139
+v 0.022692 -0.030000 0.250576
+v 0.017036 -0.030000 0.241420
+v 0.011197 -0.030000 0.231966
+v 0.005358 -0.030000 0.222513
+v -0.000298 -0.030000 0.213356
+v -0.005587 -0.030000 0.204794
+v -0.010326 -0.030000 0.197122
+v -0.014331 -0.030000 0.190638
+v -0.017419 -0.030000 0.185639
+v -0.019406 -0.030000 0.182422
+v -0.020109 -0.030000 0.181283
+v 0.291411 -0.030000 0.137327
+v 0.286764 -0.030000 0.137511
+v 0.281577 -0.030000 0.137715
+v 0.276031 -0.030000 0.137934
+v 0.270305 -0.030000 0.138160
+v 0.264578 -0.030000 0.138386
+v 0.259032 -0.030000 0.138605
+v 0.253845 -0.030000 0.138810
+v 0.249198 -0.030000 0.138993
+v 0.245271 -0.030000 0.139148
+v 0.242243 -0.030000 0.139267
+v 0.240294 -0.030000 0.139344
+v 0.239605 -0.030000 0.139372
+v 0.235884 -0.030000 0.139286
+v 0.232394 -0.030000 0.139029
+v 0.229135 -0.030000 0.138600
+v 0.226110 -0.030000 0.137996
+v 0.223322 -0.030000 0.137217
+v 0.220774 -0.030000 0.136262
+v 0.218466 -0.030000 0.135130
+v 0.216403 -0.030000 0.133819
+v 0.214585 -0.030000 0.132328
+v 0.213017 -0.030000 0.130656
+v 0.211699 -0.030000 0.128802
+v 0.210634 -0.030000 0.126764
+v 0.209732 -0.030000 0.124535
+v 0.208903 -0.030000 0.121937
+v 0.208147 -0.030000 0.118969
+v 0.207465 -0.030000 0.115633
+v 0.206860 -0.030000 0.111927
+v 0.206331 -0.030000 0.107853
+v 0.205880 -0.030000 0.103409
+v 0.205509 -0.030000 0.098596
+v 0.205218 -0.030000 0.093413
+v 0.205009 -0.030000 0.087862
+v 0.204882 -0.030000 0.081942
+v 0.204840 -0.030000 0.075652
+v 0.204840 -0.030000 -0.063713
+v 0.292093 -0.030000 -0.063713
+v 0.292093 -0.030000 -0.122662
+v 0.204840 -0.030000 -0.122662
+v 0.204840 -0.030000 -0.214664
+v 0.136333 -0.030000 -0.214664
+v 0.136333 -0.030000 -0.122662
+v 0.087935 -0.030000 -0.122662
+v 0.087935 -0.030000 -0.064054
+v 0.136333 -0.030000 -0.064054
+v 0.136333 -0.030000 -0.050850
+v 0.136333 -0.030000 -0.036113
+v 0.136333 -0.030000 -0.020353
+v 0.136333 -0.030000 -0.004083
+v 0.136333 -0.030000 0.012188
+v 0.136333 -0.030000 0.027947
+v 0.136333 -0.030000 0.042685
+v 0.136333 -0.030000 0.055889
+v 0.136333 -0.030000 0.067048
+v 0.136333 -0.030000 0.075652
+v 0.136333 -0.030000 0.081189
+v 0.136333 -0.030000 0.083148
+v 0.136475 -0.030000 0.094258
+v 0.136899 -0.030000 0.104757
+v 0.137605 -0.030000 0.114646
+v 0.138592 -0.030000 0.123924
+v 0.139858 -0.030000 0.132592
+v 0.141403 -0.030000 0.140649
+v 0.143224 -0.030000 0.148096
+v 0.145321 -0.030000 0.154932
+v 0.147692 -0.030000 0.161158
+v 0.150337 -0.030000 0.166773
+v 0.153254 -0.030000 0.171778
+v 0.156442 -0.030000 0.176172
+v 0.159999 -0.030000 0.180091
+v 0.164025 -0.030000 0.183669
+v 0.168520 -0.030000 0.186906
+v 0.173483 -0.030000 0.189802
+v 0.178915 -0.030000 0.192358
+v 0.184816 -0.030000 0.194573
+v 0.191185 -0.030000 0.196447
+v 0.198023 -0.030000 0.197980
+v 0.205330 -0.030000 0.199173
+v 0.213105 -0.030000 0.200024
+v 0.221349 -0.030000 0.200536
+v 0.230061 -0.030000 0.200706
+v 0.233945 -0.030000 0.200649
+v 0.238099 -0.030000 0.200479
+v 0.242523 -0.030000 0.200195
+v 0.247217 -0.030000 0.199797
+v 0.252180 -0.030000 0.199286
+v 0.257413 -0.030000 0.198662
+v 0.262916 -0.030000 0.197923
+v 0.268689 -0.030000 0.197071
+v 0.274732 -0.030000 0.196106
+v 0.281044 -0.030000 0.195027
+v 0.287626 -0.030000 0.193834
+v 0.294479 -0.030000 0.192528
+v -0.042504 -0.030000 -0.131451
+v -0.039308 -0.030000 -0.123910
+v -0.036421 -0.030000 -0.115714
+v -0.033843 -0.030000 -0.106862
+v -0.031573 -0.030000 -0.097352
+v -0.029610 -0.030000 -0.087182
+v -0.027952 -0.030000 -0.076353
+v -0.026597 -0.030000 -0.064862
+v -0.025546 -0.030000 -0.052708
+v -0.024797 -0.030000 -0.039891
+v -0.024348 -0.030000 -0.026409
+v -0.024199 -0.030000 -0.012261
+v -0.024348 -0.030000 0.001795
+v -0.024794 -0.030000 0.015166
+v -0.025536 -0.030000 0.027852
+v -0.026572 -0.030000 0.039848
+v -0.027902 -0.030000 0.051154
+v -0.029525 -0.030000 0.061767
+v -0.031438 -0.030000 0.071683
+v -0.033641 -0.030000 0.080902
+v -0.036133 -0.030000 0.089420
+v -0.038913 -0.030000 0.097236
+v -0.041979 -0.030000 0.104346
+v -0.045331 -0.030000 0.110749
+v -0.049179 -0.030000 0.116548
+v -0.053569 -0.030000 0.121850
+v -0.058501 -0.030000 0.126652
+v -0.063975 -0.030000 0.130954
+v -0.069995 -0.030000 0.134754
+v -0.076559 -0.030000 0.138051
+v -0.083671 -0.030000 0.140844
+v -0.091330 -0.030000 0.143132
+v -0.099539 -0.030000 0.144914
+v -0.108298 -0.030000 0.146188
+v -0.117608 -0.030000 0.146953
+v -0.127471 -0.030000 0.147209
+v -0.137341 -0.030000 0.146947
+v -0.146670 -0.030000 0.146161
+v -0.155456 -0.030000 0.144855
+v -0.163700 -0.030000 0.143031
+v -0.171399 -0.030000 0.140692
+v -0.178553 -0.030000 0.137838
+v -0.185160 -0.030000 0.134474
+v -0.191219 -0.030000 0.130601
+v -0.196729 -0.030000 0.126221
+v -0.201689 -0.030000 0.121337
+v -0.206097 -0.030000 0.115952
+v -0.209952 -0.030000 0.110067
+v -0.213382 -0.030000 0.103587
+v -0.216513 -0.030000 0.096412
+v -0.219346 -0.030000 0.088547
+v -0.221881 -0.030000 0.079993
+v -0.224118 -0.030000 0.070753
+v -0.226057 -0.030000 0.060830
+v -0.227697 -0.030000 0.050224
+v -0.229039 -0.030000 0.038940
+v -0.230083 -0.030000 0.026978
+v -0.230828 -0.030000 0.014343
+v -0.231276 -0.030000 0.001035
+v -0.231425 -0.030000 -0.012942
+v -0.231269 -0.030000 -0.027005
+v -0.230801 -0.030000 -0.040404
+v -0.230024 -0.030000 -0.053140
+v -0.228938 -0.030000 -0.065215
+v -0.227544 -0.030000 -0.076633
+v -0.225844 -0.030000 -0.087395
+v -0.223838 -0.030000 -0.097504
+v -0.221528 -0.030000 -0.106963
+v -0.218915 -0.030000 -0.115773
+v -0.216000 -0.030000 -0.123937
+v -0.212785 -0.030000 -0.131458
+v -0.209271 -0.030000 -0.138337
+v -0.205266 -0.030000 -0.144620
+v -0.200750 -0.030000 -0.150350
+v -0.195723 -0.030000 -0.155529
+v -0.190184 -0.030000 -0.160157
+v -0.184134 -0.030000 -0.164237
+v -0.177573 -0.030000 -0.167769
+v -0.170501 -0.030000 -0.170754
+v -0.162917 -0.030000 -0.173194
+v -0.154823 -0.030000 -0.175090
+v -0.146217 -0.030000 -0.176442
+v -0.137100 -0.030000 -0.177253
+v -0.127471 -0.030000 -0.177523
+v -0.117843 -0.030000 -0.177253
+v -0.108727 -0.030000 -0.176442
+v -0.100125 -0.030000 -0.175090
+v -0.092037 -0.030000 -0.173194
+v -0.084466 -0.030000 -0.170754
+v -0.077411 -0.030000 -0.167769
+v -0.070875 -0.030000 -0.164237
+v -0.064859 -0.030000 -0.160157
+v -0.059363 -0.030000 -0.155529
+v -0.054389 -0.030000 -0.150350
+v -0.049939 -0.030000 -0.144620
+v -0.046012 -0.030000 -0.138337
+v 0.500000 -0.030000 -0.271909
+v 0.500000 0.030000 -0.271909
+v 0.500000 -0.030000 -0.234087
+v 0.500000 0.030000 -0.234087
+v 0.500000 -0.030000 0.229669
+v 0.500000 0.030000 0.229669
+v 0.361282 -0.030000 0.368353
+v 0.361282 0.030000 0.368353
+v -0.369121 -0.030000 0.368353
+v -0.369121 0.030000 0.368353
+v -0.403885 -0.030000 0.368353
+v -0.403885 0.030000 0.368353
+v -0.500000 -0.030000 0.368353
+v -0.500000 0.030000 0.368353
+v -0.500000 -0.030000 0.272263
+v -0.500000 0.030000 0.272263
+v -0.500000 -0.030000 0.234440
+v -0.500000 0.030000 0.234440
+v -0.500000 -0.030000 -0.229316
+v -0.500000 0.030000 -0.229316
+v -0.361282 -0.030000 -0.368000
+v -0.361282 0.030000 -0.368000
+v 0.369121 -0.030000 -0.368000
+v 0.369121 0.030000 -0.368000
+v 0.403886 -0.030000 -0.368000
+v 0.403886 0.030000 -0.368000
+v 0.500000 -0.030000 -0.368000
+v 0.500000 0.030000 -0.368000
+v -0.014123 -0.030000 0.177038
+v -0.014123 0.030000 0.177038
+v -0.008432 -0.030000 0.172481
+v -0.008432 0.030000 0.172481
+v -0.003036 -0.030000 0.167611
+v -0.003036 0.030000 0.167611
+v 0.002070 -0.030000 0.162429
+v 0.002070 0.030000 0.162429
+v 0.006887 -0.030000 0.156934
+v 0.006887 0.030000 0.156934
+v 0.011418 -0.030000 0.151127
+v 0.011418 0.030000 0.151127
+v 0.015664 -0.030000 0.145008
+v 0.015664 0.030000 0.145008
+v 0.019629 -0.030000 0.138577
+v 0.019629 0.030000 0.138577
+v 0.023315 -0.030000 0.131833
+v 0.023315 0.030000 0.131833
+v 0.026724 -0.030000 0.124776
+v 0.026724 0.030000 0.124776
+v 0.029858 -0.030000 0.117408
+v 0.029858 0.030000 0.117408
+v 0.032720 -0.030000 0.109727
+v 0.032720 0.030000 0.109727
+v 0.035255 -0.030000 0.101769
+v 0.035255 0.030000 0.101769
+v 0.037575 -0.030000 0.093399
+v 0.037575 0.030000 0.093399
+v 0.039680 -0.030000 0.084618
+v 0.039680 0.030000 0.084618
+v 0.041569 -0.030000 0.075425
+v 0.041569 0.030000 0.075425
+v 0.043240 -0.030000 0.065820
+v 0.043240 0.030000 0.065820
+v 0.044692 -0.030000 0.055804
+v 0.044692 0.030000 0.055804
+v 0.045923 -0.030000 0.045375
+v 0.045923 0.030000 0.045375
+v 0.046934 -0.030000 0.034535
+v 0.046934 0.030000 0.034535
+v 0.047722 -0.030000 0.023284
+v 0.047722 0.030000 0.023284
+v 0.048286 -0.030000 0.011620
+v 0.048286 0.030000 0.011620
+v 0.048626 -0.030000 -0.000455
+v 0.048626 0.030000 -0.000455
+v 0.048739 -0.030000 -0.012942
+v 0.048739 0.030000 -0.012942
+v 0.048469 -0.030000 -0.031775
+v 0.048469 0.030000 -0.031775
+v 0.047658 -0.030000 -0.049771
+v 0.047658 0.030000 -0.049771
+v 0.046305 -0.030000 -0.066929
+v 0.046305 0.030000 -0.066929
+v 0.044409 -0.030000 -0.083249
+v 0.044409 0.030000 -0.083249
+v 0.041969 -0.030000 -0.098732
+v 0.041969 0.030000 -0.098732
+v 0.038983 -0.030000 -0.113377
+v 0.038983 0.030000 -0.113377
+v 0.035450 -0.030000 -0.127184
+v 0.035450 0.030000 -0.127184
+v 0.031369 -0.030000 -0.140154
+v 0.031369 0.030000 -0.140154
+v 0.026739 -0.030000 -0.152286
+v 0.026739 0.030000 -0.152286
+v 0.021559 -0.030000 -0.163580
+v 0.021559 0.030000 -0.163580
+v 0.015828 -0.030000 -0.174037
+v 0.015828 0.030000 -0.174037
+v 0.009543 -0.030000 -0.183656
+v 0.009543 0.030000 -0.183656
+v 0.002656 -0.030000 -0.192551
+v 0.002656 0.030000 -0.192551
+v -0.005054 -0.030000 -0.200667
+v -0.005054 0.030000 -0.200667
+v -0.013585 -0.030000 -0.208004
+v -0.013585 0.030000 -0.208004
+v -0.022937 -0.030000 -0.214563
+v -0.022937 0.030000 -0.214563
+v -0.033107 -0.030000 -0.220347
+v -0.033107 0.030000 -0.220347
+v -0.044095 -0.030000 -0.225355
+v -0.044095 0.030000 -0.225355
+v -0.055900 -0.030000 -0.229590
+v -0.055900 0.030000 -0.229590
+v -0.068520 -0.030000 -0.233052
+v -0.068520 0.030000 -0.233052
+v -0.081954 -0.030000 -0.235742
+v -0.081954 0.030000 -0.235742
+v -0.096201 -0.030000 -0.237663
+v -0.096201 0.030000 -0.237663
+v -0.111260 -0.030000 -0.238814
+v -0.111260 0.030000 -0.238814
+v -0.127130 -0.030000 -0.239198
+v -0.127130 0.030000 -0.239198
+v -0.143000 -0.030000 -0.238808
+v -0.143000 0.030000 -0.238808
+v -0.158061 -0.030000 -0.237638
+v -0.158061 0.030000 -0.237638
+v -0.172312 -0.030000 -0.235689
+v -0.172312 0.030000 -0.235689
+v -0.185753 -0.030000 -0.232963
+v -0.185753 0.030000 -0.232963
+v -0.198385 -0.030000 -0.229461
+v -0.198385 0.030000 -0.229461
+v -0.210208 -0.030000 -0.225185
+v -0.210208 0.030000 -0.225185
+v -0.221221 -0.030000 -0.220134
+v -0.221221 0.030000 -0.220134
+v -0.231425 -0.030000 -0.214311
+v -0.231425 0.030000 -0.214311
+v -0.240819 -0.030000 -0.207716
+v -0.240819 0.030000 -0.207716
+v -0.249404 -0.030000 -0.200351
+v -0.249404 0.030000 -0.200351
+v -0.257179 -0.030000 -0.192217
+v -0.257179 0.030000 -0.192217
+v -0.264144 -0.030000 -0.183315
+v -0.264144 0.030000 -0.183315
+v -0.270435 -0.030000 -0.173618
+v -0.270435 0.030000 -0.173618
+v -0.276186 -0.030000 -0.163098
+v -0.276186 0.030000 -0.163098
+v -0.281394 -0.030000 -0.151754
+v -0.281394 0.030000 -0.151754
+v -0.286059 -0.030000 -0.139586
+v -0.286059 0.030000 -0.139586
+v -0.290179 -0.030000 -0.126595
+v -0.290179 0.030000 -0.126595
+v -0.293754 -0.030000 -0.112781
+v -0.293754 0.030000 -0.112781
+v -0.296782 -0.030000 -0.098143
+v -0.296782 0.030000 -0.098143
+v -0.299263 -0.030000 -0.082682
+v -0.299263 0.030000 -0.082682
+v -0.301194 -0.030000 -0.066397
+v -0.301194 0.030000 -0.066397
+v -0.302575 -0.030000 -0.049288
+v -0.302575 0.030000 -0.049288
+v -0.303404 -0.030000 -0.031357
+v -0.303404 0.030000 -0.031357
+v -0.303681 -0.030000 -0.012601
+v -0.303681 0.030000 -0.012601
+v -0.303411 -0.030000 0.006061
+v -0.303411 0.030000 0.006061
+v -0.302602 -0.030000 0.023884
+v -0.302602 0.030000 0.023884
+v -0.301253 -0.030000 0.040864
+v -0.301253 0.030000 0.040864
+v -0.299364 -0.030000 0.056999
+v -0.299364 0.030000 0.056999
+v -0.296935 -0.030000 0.072288
+v -0.296935 0.030000 0.072288
+v -0.293967 -0.030000 0.086726
+v -0.293967 0.030000 0.086726
+v -0.290460 -0.030000 0.100313
+v -0.290460 0.030000 0.100313
+v -0.286412 -0.030000 0.113046
+v -0.286412 0.030000 0.113046
+v -0.281825 -0.030000 0.124922
+v -0.281825 0.030000 0.124922
+v -0.276698 -0.030000 0.135939
+v -0.276698 0.030000 0.135939
+v -0.271032 -0.030000 0.146095
+v -0.271032 0.030000 0.146095
+v -0.264826 -0.030000 0.155387
+v -0.264826 0.030000 0.155387
+v -0.257932 -0.030000 0.163877
+v -0.257932 0.030000 0.163877
+v -0.250200 -0.030000 0.171629
+v -0.250200 0.030000 0.171629
+v -0.241634 -0.030000 0.178643
+v -0.241634 0.030000 0.178643
+v -0.232233 -0.030000 0.184918
+v -0.232233 0.030000 0.184918
+v -0.221998 -0.030000 0.190455
+v -0.221998 0.030000 0.190455
+v -0.210932 -0.030000 0.195254
+v -0.210932 0.030000 0.195254
+v -0.199035 -0.030000 0.199315
+v -0.199035 0.030000 0.199315
+v -0.186309 -0.030000 0.202637
+v -0.186309 0.030000 0.202637
+v -0.172754 -0.030000 0.205221
+v -0.172754 0.030000 0.205221
+v -0.158371 -0.030000 0.207067
+v -0.158371 0.030000 0.207067
+v -0.143163 -0.030000 0.208174
+v -0.143163 0.030000 0.208174
+v -0.127130 -0.030000 0.208543
+v -0.127130 0.030000 0.208543
+v -0.122805 -0.030000 0.208515
+v -0.122805 0.030000 0.208515
+v -0.118691 -0.030000 0.208431
+v -0.118691 0.030000 0.208431
+v -0.114786 -0.030000 0.208293
+v -0.114786 0.030000 0.208293
+v -0.111086 -0.030000 0.208101
+v -0.111086 0.030000 0.208101
+v -0.107590 -0.030000 0.207858
+v -0.107590 0.030000 0.207858
+v -0.104294 -0.030000 0.207563
+v -0.104294 0.030000 0.207563
+v -0.101198 -0.030000 0.207219
+v -0.101198 0.030000 0.207219
+v -0.098298 -0.030000 0.206827
+v -0.098298 0.030000 0.206827
+v -0.095593 -0.030000 0.206387
+v -0.095593 0.030000 0.206387
+v -0.093079 -0.030000 0.205901
+v -0.093079 0.030000 0.205901
+v -0.090754 -0.030000 0.205370
+v -0.090754 0.030000 0.205370
+v -0.088616 -0.030000 0.204795
+v -0.088616 0.030000 0.204795
+v -0.032379 -0.030000 0.297137
+v -0.032379 0.030000 0.297137
+v 0.032720 -0.030000 0.266811
+v 0.032720 0.030000 0.266811
+v 0.027981 -0.030000 0.259139
+v 0.027981 0.030000 0.259139
+v 0.022692 -0.030000 0.250576
+v 0.022692 0.030000 0.250576
+v 0.017036 -0.030000 0.241420
+v 0.017036 0.030000 0.241420
+v 0.011197 -0.030000 0.231966
+v 0.011197 0.030000 0.231966
+v 0.005358 -0.030000 0.222513
+v 0.005358 0.030000 0.222513
+v -0.000298 -0.030000 0.213356
+v -0.000298 0.030000 0.213356
+v -0.005587 -0.030000 0.204794
+v -0.005587 0.030000 0.204794
+v -0.010326 -0.030000 0.197122
+v -0.010326 0.030000 0.197122
+v -0.014331 -0.030000 0.190638
+v -0.014331 0.030000 0.190638
+v -0.017419 -0.030000 0.185639
+v -0.017419 0.030000 0.185639
+v -0.019406 -0.030000 0.182422
+v -0.019406 0.030000 0.182422
+v -0.020109 -0.030000 0.181283
+v -0.020109 0.030000 0.181283
+v 0.291411 -0.030000 0.137327
+v 0.291411 0.030000 0.137327
+v 0.286764 -0.030000 0.137511
+v 0.286764 0.030000 0.137511
+v 0.281577 -0.030000 0.137715
+v 0.281577 0.030000 0.137715
+v 0.276031 -0.030000 0.137934
+v 0.276031 0.030000 0.137934
+v 0.270305 -0.030000 0.138160
+v 0.270305 0.030000 0.138160
+v 0.264578 -0.030000 0.138386
+v 0.264578 0.030000 0.138386
+v 0.259032 -0.030000 0.138605
+v 0.259032 0.030000 0.138605
+v 0.253845 -0.030000 0.138810
+v 0.253845 0.030000 0.138810
+v 0.249198 -0.030000 0.138993
+v 0.249198 0.030000 0.138993
+v 0.245271 -0.030000 0.139148
+v 0.245271 0.030000 0.139148
+v 0.242243 -0.030000 0.139267
+v 0.242243 0.030000 0.139267
+v 0.240294 -0.030000 0.139344
+v 0.240294 0.030000 0.139344
+v 0.239605 -0.030000 0.139372
+v 0.239605 0.030000 0.139372
+v 0.235884 -0.030000 0.139286
+v 0.235884 0.030000 0.139286
+v 0.232394 -0.030000 0.139029
+v 0.232394 0.030000 0.139029
+v 0.229135 -0.030000 0.138600
+v 0.229135 0.030000 0.138600
+v 0.226110 -0.030000 0.137996
+v 0.226110 0.030000 0.137996
+v 0.223322 -0.030000 0.137217
+v 0.223322 0.030000 0.137217
+v 0.220774 -0.030000 0.136262
+v 0.220774 0.030000 0.136262
+v 0.218466 -0.030000 0.135130
+v 0.218466 0.030000 0.135130
+v 0.216403 -0.030000 0.133819
+v 0.216403 0.030000 0.133819
+v 0.214585 -0.030000 0.132328
+v 0.214585 0.030000 0.132328
+v 0.213017 -0.030000 0.130656
+v 0.213017 0.030000 0.130656
+v 0.211699 -0.030000 0.128802
+v 0.211699 0.030000 0.128802
+v 0.210634 -0.030000 0.126764
+v 0.210634 0.030000 0.126764
+v 0.209732 -0.030000 0.124535
+v 0.209732 0.030000 0.124535
+v 0.208903 -0.030000 0.121937
+v 0.208903 0.030000 0.121937
+v 0.208147 -0.030000 0.118969
+v 0.208147 0.030000 0.118969
+v 0.207465 -0.030000 0.115633
+v 0.207465 0.030000 0.115633
+v 0.206860 -0.030000 0.111927
+v 0.206860 0.030000 0.111927
+v 0.206331 -0.030000 0.107853
+v 0.206331 0.030000 0.107853
+v 0.205880 -0.030000 0.103409
+v 0.205880 0.030000 0.103409
+v 0.205509 -0.030000 0.098596
+v 0.205509 0.030000 0.098596
+v 0.205218 -0.030000 0.093413
+v 0.205218 0.030000 0.093413
+v 0.205009 -0.030000 0.087862
+v 0.205009 0.030000 0.087862
+v 0.204882 -0.030000 0.081942
+v 0.204882 0.030000 0.081942
+v 0.204840 -0.030000 0.075652
+v 0.204840 0.030000 0.075652
+v 0.204840 -0.030000 -0.063713
+v 0.204840 0.030000 -0.063713
+v 0.292093 -0.030000 -0.063713
+v 0.292093 0.030000 -0.063713
+v 0.292093 -0.030000 -0.122662
+v 0.292093 0.030000 -0.122662
+v 0.204840 -0.030000 -0.122662
+v 0.204840 0.030000 -0.122662
+v 0.204840 -0.030000 -0.214664
+v 0.204840 0.030000 -0.214664
+v 0.136333 -0.030000 -0.214664
+v 0.136333 0.030000 -0.214664
+v 0.136333 -0.030000 -0.122662
+v 0.136333 0.030000 -0.122662
+v 0.087935 -0.030000 -0.122662
+v 0.087935 0.030000 -0.122662
+v 0.087935 -0.030000 -0.064054
+v 0.087935 0.030000 -0.064054
+v 0.136333 -0.030000 -0.064054
+v 0.136333 0.030000 -0.064054
+v 0.136333 -0.030000 -0.050850
+v 0.136333 0.030000 -0.050850
+v 0.136333 -0.030000 -0.036113
+v 0.136333 0.030000 -0.036113
+v 0.136333 -0.030000 -0.020353
+v 0.136333 0.030000 -0.020353
+v 0.136333 -0.030000 -0.004083
+v 0.136333 0.030000 -0.004083
+v 0.136333 -0.030000 0.012188
+v 0.136333 0.030000 0.012188
+v 0.136333 -0.030000 0.027947
+v 0.136333 0.030000 0.027947
+v 0.136333 -0.030000 0.042685
+v 0.136333 0.030000 0.042685
+v 0.136333 -0.030000 0.055889
+v 0.136333 0.030000 0.055889
+v 0.136333 -0.030000 0.067048
+v 0.136333 0.030000 0.067048
+v 0.136333 -0.030000 0.075652
+v 0.136333 0.030000 0.075652
+v 0.136333 -0.030000 0.081189
+v 0.136333 0.030000 0.081189
+v 0.136333 -0.030000 0.083148
+v 0.136333 0.030000 0.083148
+v 0.136475 -0.030000 0.094258
+v 0.136475 0.030000 0.094258
+v 0.136899 -0.030000 0.104757
+v 0.136899 0.030000 0.104757
+v 0.137605 -0.030000 0.114646
+v 0.137605 0.030000 0.114646
+v 0.138592 -0.030000 0.123924
+v 0.138592 0.030000 0.123924
+v 0.139858 -0.030000 0.132592
+v 0.139858 0.030000 0.132592
+v 0.141403 -0.030000 0.140649
+v 0.141403 0.030000 0.140649
+v 0.143224 -0.030000 0.148096
+v 0.143224 0.030000 0.148096
+v 0.145321 -0.030000 0.154932
+v 0.145321 0.030000 0.154932
+v 0.147692 -0.030000 0.161158
+v 0.147692 0.030000 0.161158
+v 0.150337 -0.030000 0.166773
+v 0.150337 0.030000 0.166773
+v 0.153254 -0.030000 0.171778
+v 0.153254 0.030000 0.171778
+v 0.156442 -0.030000 0.176172
+v 0.156442 0.030000 0.176172
+v 0.159999 -0.030000 0.180091
+v 0.159999 0.030000 0.180091
+v 0.164025 -0.030000 0.183669
+v 0.164025 0.030000 0.183669
+v 0.168520 -0.030000 0.186906
+v 0.168520 0.030000 0.186906
+v 0.173483 -0.030000 0.189802
+v 0.173483 0.030000 0.189802
+v 0.178915 -0.030000 0.192358
+v 0.178915 0.030000 0.192358
+v 0.184816 -0.030000 0.194573
+v 0.184816 0.030000 0.194573
+v 0.191185 -0.030000 0.196447
+v 0.191185 0.030000 0.196447
+v 0.198023 -0.030000 0.197980
+v 0.198023 0.030000 0.197980
+v 0.205330 -0.030000 0.199173
+v 0.205330 0.030000 0.199173
+v 0.213105 -0.030000 0.200024
+v 0.213105 0.030000 0.200024
+v 0.221349 -0.030000 0.200536
+v 0.221349 0.030000 0.200536
+v 0.230061 -0.030000 0.200706
+v 0.230061 0.030000 0.200706
+v 0.233945 -0.030000 0.200649
+v 0.233945 0.030000 0.200649
+v 0.238099 -0.030000 0.200479
+v 0.238099 0.030000 0.200479
+v 0.242523 -0.030000 0.200195
+v 0.242523 0.030000 0.200195
+v 0.247217 -0.030000 0.199797
+v 0.247217 0.030000 0.199797
+v 0.252180 -0.030000 0.199286
+v 0.252180 0.030000 0.199286
+v 0.257413 -0.030000 0.198662
+v 0.257413 0.030000 0.198662
+v 0.262916 -0.030000 0.197923
+v 0.262916 0.030000 0.197923
+v 0.268689 -0.030000 0.197071
+v 0.268689 0.030000 0.197071
+v 0.274732 -0.030000 0.196106
+v 0.274732 0.030000 0.196106
+v 0.281044 -0.030000 0.195027
+v 0.281044 0.030000 0.195027
+v 0.287626 -0.030000 0.193834
+v 0.287626 0.030000 0.193834
+v 0.294479 -0.030000 0.192528
+v 0.294479 0.030000 0.192528
+v -0.042504 -0.030000 -0.131451
+v -0.042504 0.030000 -0.131451
+v -0.039308 -0.030000 -0.123910
+v -0.039308 0.030000 -0.123910
+v -0.036421 -0.030000 -0.115714
+v -0.036421 0.030000 -0.115714
+v -0.033843 -0.030000 -0.106862
+v -0.033843 0.030000 -0.106862
+v -0.031573 -0.030000 -0.097352
+v -0.031573 0.030000 -0.097352
+v -0.029610 -0.030000 -0.087182
+v -0.029610 0.030000 -0.087182
+v -0.027952 -0.030000 -0.076353
+v -0.027952 0.030000 -0.076353
+v -0.026597 -0.030000 -0.064862
+v -0.026597 0.030000 -0.064862
+v -0.025546 -0.030000 -0.052708
+v -0.025546 0.030000 -0.052708
+v -0.024797 -0.030000 -0.039891
+v -0.024797 0.030000 -0.039891
+v -0.024348 -0.030000 -0.026409
+v -0.024348 0.030000 -0.026409
+v -0.024199 -0.030000 -0.012261
+v -0.024199 0.030000 -0.012261
+v -0.024348 -0.030000 0.001795
+v -0.024348 0.030000 0.001795
+v -0.024794 -0.030000 0.015166
+v -0.024794 0.030000 0.015166
+v -0.025536 -0.030000 0.027852
+v -0.025536 0.030000 0.027852
+v -0.026572 -0.030000 0.039848
+v -0.026572 0.030000 0.039848
+v -0.027902 -0.030000 0.051154
+v -0.027902 0.030000 0.051154
+v -0.029525 -0.030000 0.061767
+v -0.029525 0.030000 0.061767
+v -0.031438 -0.030000 0.071683
+v -0.031438 0.030000 0.071683
+v -0.033641 -0.030000 0.080902
+v -0.033641 0.030000 0.080902
+v -0.036133 -0.030000 0.089420
+v -0.036133 0.030000 0.089420
+v -0.038913 -0.030000 0.097236
+v -0.038913 0.030000 0.097236
+v -0.041979 -0.030000 0.104346
+v -0.041979 0.030000 0.104346
+v -0.045331 -0.030000 0.110749
+v -0.045331 0.030000 0.110749
+v -0.049179 -0.030000 0.116548
+v -0.049179 0.030000 0.116548
+v -0.053569 -0.030000 0.121850
+v -0.053569 0.030000 0.121850
+v -0.058501 -0.030000 0.126652
+v -0.058501 0.030000 0.126652
+v -0.063975 -0.030000 0.130954
+v -0.063975 0.030000 0.130954
+v -0.069995 -0.030000 0.134754
+v -0.069995 0.030000 0.134754
+v -0.076559 -0.030000 0.138051
+v -0.076559 0.030000 0.138051
+v -0.083671 -0.030000 0.140844
+v -0.083671 0.030000 0.140844
+v -0.091330 -0.030000 0.143132
+v -0.091330 0.030000 0.143132
+v -0.099539 -0.030000 0.144914
+v -0.099539 0.030000 0.144914
+v -0.108298 -0.030000 0.146188
+v -0.108298 0.030000 0.146188
+v -0.117608 -0.030000 0.146953
+v -0.117608 0.030000 0.146953
+v -0.127471 -0.030000 0.147209
+v -0.127471 0.030000 0.147209
+v -0.137341 -0.030000 0.146947
+v -0.137341 0.030000 0.146947
+v -0.146670 -0.030000 0.146161
+v -0.146670 0.030000 0.146161
+v -0.155456 -0.030000 0.144855
+v -0.155456 0.030000 0.144855
+v -0.163700 -0.030000 0.143031
+v -0.163700 0.030000 0.143031
+v -0.171399 -0.030000 0.140692
+v -0.171399 0.030000 0.140692
+v -0.178553 -0.030000 0.137838
+v -0.178553 0.030000 0.137838
+v -0.185160 -0.030000 0.134474
+v -0.185160 0.030000 0.134474
+v -0.191219 -0.030000 0.130601
+v -0.191219 0.030000 0.130601
+v -0.196729 -0.030000 0.126221
+v -0.196729 0.030000 0.126221
+v -0.201689 -0.030000 0.121337
+v -0.201689 0.030000 0.121337
+v -0.206097 -0.030000 0.115952
+v -0.206097 0.030000 0.115952
+v -0.209952 -0.030000 0.110067
+v -0.209952 0.030000 0.110067
+v -0.213382 -0.030000 0.103587
+v -0.213382 0.030000 0.103587
+v -0.216513 -0.030000 0.096412
+v -0.216513 0.030000 0.096412
+v -0.219346 -0.030000 0.088547
+v -0.219346 0.030000 0.088547
+v -0.221881 -0.030000 0.079993
+v -0.221881 0.030000 0.079993
+v -0.224118 -0.030000 0.070753
+v -0.224118 0.030000 0.070753
+v -0.226057 -0.030000 0.060830
+v -0.226057 0.030000 0.060830
+v -0.227697 -0.030000 0.050224
+v -0.227697 0.030000 0.050224
+v -0.229039 -0.030000 0.038940
+v -0.229039 0.030000 0.038940
+v -0.230083 -0.030000 0.026978
+v -0.230083 0.030000 0.026978
+v -0.230828 -0.030000 0.014343
+v -0.230828 0.030000 0.014343
+v -0.231276 -0.030000 0.001035
+v -0.231276 0.030000 0.001035
+v -0.231425 -0.030000 -0.012942
+v -0.231425 0.030000 -0.012942
+v -0.231269 -0.030000 -0.027005
+v -0.231269 0.030000 -0.027005
+v -0.230801 -0.030000 -0.040404
+v -0.230801 0.030000 -0.040404
+v -0.230024 -0.030000 -0.053140
+v -0.230024 0.030000 -0.053140
+v -0.228938 -0.030000 -0.065215
+v -0.228938 0.030000 -0.065215
+v -0.227544 -0.030000 -0.076633
+v -0.227544 0.030000 -0.076633
+v -0.225844 -0.030000 -0.087395
+v -0.225844 0.030000 -0.087395
+v -0.223838 -0.030000 -0.097504
+v -0.223838 0.030000 -0.097504
+v -0.221528 -0.030000 -0.106963
+v -0.221528 0.030000 -0.106963
+v -0.218915 -0.030000 -0.115773
+v -0.218915 0.030000 -0.115773
+v -0.216000 -0.030000 -0.123937
+v -0.216000 0.030000 -0.123937
+v -0.212785 -0.030000 -0.131458
+v -0.212785 0.030000 -0.131458
+v -0.209271 -0.030000 -0.138337
+v -0.209271 0.030000 -0.138337
+v -0.205266 -0.030000 -0.144620
+v -0.205266 0.030000 -0.144620
+v -0.200750 -0.030000 -0.150350
+v -0.200750 0.030000 -0.150350
+v -0.195723 -0.030000 -0.155529
+v -0.195723 0.030000 -0.155529
+v -0.190184 -0.030000 -0.160157
+v -0.190184 0.030000 -0.160157
+v -0.184134 -0.030000 -0.164237
+v -0.184134 0.030000 -0.164237
+v -0.177573 -0.030000 -0.167769
+v -0.177573 0.030000 -0.167769
+v -0.170501 -0.030000 -0.170754
+v -0.170501 0.030000 -0.170754
+v -0.162917 -0.030000 -0.173194
+v -0.162917 0.030000 -0.173194
+v -0.154823 -0.030000 -0.175090
+v -0.154823 0.030000 -0.175090
+v -0.146217 -0.030000 -0.176442
+v -0.146217 0.030000 -0.176442
+v -0.137100 -0.030000 -0.177253
+v -0.137100 0.030000 -0.177253
+v -0.127471 -0.030000 -0.177523
+v -0.127471 0.030000 -0.177523
+v -0.117843 -0.030000 -0.177253
+v -0.117843 0.030000 -0.177253
+v -0.108727 -0.030000 -0.176442
+v -0.108727 0.030000 -0.176442
+v -0.100125 -0.030000 -0.175090
+v -0.100125 0.030000 -0.175090
+v -0.092037 -0.030000 -0.173194
+v -0.092037 0.030000 -0.173194
+v -0.084466 -0.030000 -0.170754
+v -0.084466 0.030000 -0.170754
+v -0.077411 -0.030000 -0.167769
+v -0.077411 0.030000 -0.167769
+v -0.070875 -0.030000 -0.164237
+v -0.070875 0.030000 -0.164237
+v -0.064859 -0.030000 -0.160157
+v -0.064859 0.030000 -0.160157
+v -0.059363 -0.030000 -0.155529
+v -0.059363 0.030000 -0.155529
+v -0.054389 -0.030000 -0.150350
+v -0.054389 0.030000 -0.150350
+v -0.049939 -0.030000 -0.144620
+v -0.049939 0.030000 -0.144620
+v -0.046012 -0.030000 -0.138337
+v -0.046012 0.030000 -0.138337
+vn 0.0000 1.0000 0.0000
+vn 0.0000 0.0000 1.0000
+vn 0.0000 0.0000 -1.0000
+vn 0.0000 -1.0000 0.0000
+vn 0.0000 -1.0000 -0.0001
+vn 0.0000 -1.0000 0.0001
+vn 1.0000 0.0000 0.0000
+vn 0.9238 0.0000 0.3827
+vn 0.3826 0.0000 0.9239
+vn -0.7071 0.0000 0.7071
+vn -1.0000 0.0000 0.0000
+vn -0.9238 0.0000 -0.3827
+vn -0.3826 0.0000 -0.9239
+vn 0.7071 0.0000 -0.7071
+vn -0.6478 0.0000 -0.7618
+vn -0.6020 0.0000 -0.7985
+vn -0.6914 0.0000 -0.7224
+vn -0.7324 0.0000 -0.6808
+vn -0.7705 0.0000 -0.6374
+vn -0.8053 0.0000 -0.5929
+vn -0.8367 0.0000 -0.5477
+vn -0.8647 0.0000 -0.5023
+vn -0.8367 0.0000 -0.5476
+vn -0.8892 0.0000 -0.4574
+vn -0.9106 0.0000 -0.4133
+vn -0.9289 0.0000 -0.3704
+vn -0.9452 0.0000 -0.3264
+vn -0.9584 0.0000 -0.2854
+vn -0.9682 0.0000 -0.2502
+vn -0.9761 0.0000 -0.2172
+vn -0.9825 0.0000 -0.1863
+vn -0.9875 0.0000 -0.1574
+vn -0.9915 0.0000 -0.1304
+vn -0.9944 0.0000 -0.1050
+vn -0.9967 0.0000 -0.0813
+vn -0.9982 0.0000 -0.0591
+vn -0.9993 0.0000 -0.0382
+vn -0.9998 0.0000 -0.0186
+vn -1.0000 0.0000 0.0026
+vn -0.9995 0.0000 0.0297
+vn -0.9981 0.0000 0.0618
+vn -0.9953 0.0000 0.0970
+vn -0.9908 0.0000 0.1356
+vn -0.9840 0.0000 0.1778
+vn -0.9746 0.0000 0.2239
+vn -0.9617 0.0000 0.2741
+vn -0.9445 0.0000 0.3285
+vn -0.9221 0.0000 0.3869
+vn -0.8935 0.0000 0.4490
+vn -0.8577 0.0000 0.5142
+vn -0.8146 0.0000 0.5800
+vn -0.7588 0.0000 0.6513
+vn -0.6894 0.0000 0.7244
+vn -0.6139 0.0000 0.7894
+vn -0.5349 0.0000 0.8449
+vn -0.4550 0.0000 0.8905
+vn -0.3765 0.0000 0.9264
+vn -0.3013 0.0000 0.9535
+vn -0.2306 0.0000 0.9730
+vn -0.1650 0.0000 0.9863
+vn -0.1050 0.0000 0.9945
+vn -0.0502 0.0000 0.9987
+vn 0.0002 0.0000 1.0000
+vn 0.0510 0.0000 0.9987
+vn 0.1065 0.0000 0.9943
+vn 0.1672 0.0000 0.9859
+vn 0.2331 0.0000 0.9724
+vn 0.3039 0.0000 0.9527
+vn 0.3788 0.0000 0.9254
+vn 0.4567 0.0000 0.8896
+vn 0.5357 0.0000 0.8444
+vn 0.6135 0.0000 0.7896
+vn 0.6878 0.0000 0.7259
+vn 0.7561 0.0000 0.6544
+vn 0.8140 0.0000 0.5808
+vn 0.8588 0.0000 0.5123
+vn 0.8937 0.0000 0.4487
+vn 0.9217 0.0000 0.3878
+vn 0.9438 0.0000 0.3303
+vn 0.9610 0.0000 0.2765
+vn 0.9740 0.0000 0.2266
+vn 0.9836 0.0000 0.1805
+vn 0.9904 0.0000 0.1381
+vn 0.9951 0.0000 0.0991
+vn 0.9980 0.0000 0.0633
+vn 0.9995 0.0000 0.0305
+vn 1.0000 0.0000 0.0001
+vn 0.9995 0.0000 -0.0299
+vn 0.9980 0.0000 -0.0623
+vn 0.9952 0.0000 -0.0978
+vn 0.9906 0.0000 -0.1366
+vn 0.9838 0.0000 -0.1791
+vn 0.9742 0.0000 -0.2257
+vn 0.9610 0.0000 -0.2766
+vn 0.9434 0.0000 -0.3318
+vn 0.9203 0.0000 -0.3913
+vn 0.8905 0.0000 -0.4548
+vn 0.8531 0.0000 -0.5217
+vn 0.8048 0.0000 -0.5935
+vn 0.7431 0.0000 -0.6691
+vn 0.6716 0.0000 -0.7409
+vn 0.5950 0.0000 -0.8037
+vn 0.5161 0.0000 -0.8565
+vn 0.4372 0.0000 -0.8993
+vn 0.3607 0.0000 -0.9326
+vn 0.2880 0.0000 -0.9576
+vn 0.2200 0.0000 -0.9755
+vn 0.1573 0.0000 -0.9875
+vn 0.1000 0.0000 -0.9950
+vn 0.0478 0.0000 -0.9988
+vn 0.0082 0.0000 -0.9999
+vn -0.0134 0.0000 -0.9999
+vn -0.0279 0.0000 -0.9996
+vn -0.0435 0.0000 -0.9990
+vn -0.0606 0.0000 -0.9981
+vn -0.0792 0.0000 -0.9968
+vn -0.0997 0.0000 -0.9950
+vn -0.1223 0.0000 -0.9925
+vn -0.1473 0.0000 -0.9891
+vn -0.1752 0.0000 -0.9845
+vn -0.2063 0.0000 -0.9785
+vn -0.1751 0.0000 -0.9845
+vn -0.2412 0.0000 -0.9705
+vn 0.3714 0.0000 -0.9284
+vn 0.2897 0.0000 -0.9571
+vn -0.9580 0.0000 -0.2867
+vn -0.8508 0.0000 0.5255
+vn -0.9800 0.0000 -0.1990
+vn 0.0394 0.0000 0.9992
+vn -0.6727 0.0000 0.7399
+vn 0.0395 0.0000 0.9992
+vn 0.0083 0.0000 0.9999
+vn -0.0482 0.0000 0.9988
+vn 0.0082 0.0000 0.9999
+vn -0.1021 0.0000 0.9948
+vn -0.1633 0.0000 0.9866
+vn -0.2325 0.0000 0.9726
+vn -0.3102 0.0000 0.9507
+vn -0.3962 0.0000 0.9181
+vn -0.4892 0.0000 0.8722
+vn -0.5863 0.0000 0.8101
+vn -0.6832 0.0000 0.7302
+vn -0.7739 0.0000 0.6333
+vn -0.8527 0.0000 0.5224
+vn -0.9077 0.0000 0.4195
+vn -0.9405 0.0000 0.3398
+vn -0.9612 0.0000 0.2756
+vn -0.9747 0.0000 0.2235
+vn -0.9835 0.0000 0.1807
+vn -0.9894 0.0000 0.1450
+vn -0.9934 0.0000 0.1148
+vn -0.9960 0.0000 0.0889
+vn -0.9978 0.0000 0.0665
+vn -0.9989 0.0000 0.0468
+vn -0.9995 0.0000 0.0295
+vn -0.9999 0.0000 0.0140
+vn -1.0000 0.0000 0.0034
+vn -0.7071 0.0000 -0.7071
+vn 0.7071 0.0000 0.7071
+vn 1.0000 0.0000 -0.0064
+vn 0.9996 0.0000 -0.0266
+vn 0.9984 0.0000 -0.0558
+vn 0.9961 0.0000 -0.0885
+vn 0.9921 0.0000 -0.1252
+vn 0.9861 0.0000 -0.1664
+vn 0.9771 0.0000 -0.2129
+vn 0.9641 0.0000 -0.2655
+vn 0.9458 0.0000 -0.3248
+vn 0.8852 0.0000 -0.4653
+vn 0.8377 0.0000 -0.5461
+vn 0.7761 0.0000 -0.6306
+vn 0.7033 0.0000 -0.7108
+vn 0.6251 0.0000 -0.7805
+vn 0.5448 0.0000 -0.8385
+vn 0.4653 0.0000 -0.8851
+vn 0.3889 0.0000 -0.9213
+vn 0.3170 0.0000 -0.9484
+vn 0.2506 0.0000 -0.9680
+vn 0.3171 0.0000 -0.9484
+vn 0.1900 0.0000 -0.9817
+vn 0.1350 0.0000 -0.9908
+vn 0.0854 0.0000 -0.9963
+vn 0.0407 0.0000 -0.9991
+vn 0.0024 0.0000 -1.0000
+vn -0.0278 0.0000 -0.9996
+vn -0.0525 0.0000 -0.9986
+vn -0.0742 0.0000 -0.9972
+vn -0.0934 0.0000 -0.9956
+vn -0.1105 0.0000 -0.9939
+vn -0.1257 0.0000 -0.9920
+vn -0.1395 0.0000 -0.9902
+vn -0.1519 0.0000 -0.9884
+vn -0.1631 0.0000 -0.9866
+vn -0.1734 0.0000 -0.9848
+vn -0.1827 0.0000 -0.9832
+vn -0.7879 0.0000 -0.6158
+vn 0.9324 0.0000 -0.3614
+vn 0.9064 0.0000 -0.4223
+vn 0.9520 0.0000 -0.3060
+vn 0.9667 0.0000 -0.2559
+vn 0.9775 0.0000 -0.2109
+vn 0.9854 0.0000 -0.1705
+vn 0.9909 0.0000 -0.1342
+vn 0.9948 0.0000 -0.1016
+vn 0.9974 0.0000 -0.0723
+vn 0.9989 0.0000 -0.0458
+vn 0.9998 0.0000 -0.0219
+vn 0.9998 0.0000 0.0219
+vn 0.9989 0.0000 0.0458
+vn 0.9974 0.0000 0.0722
+vn 0.9948 0.0000 0.1014
+vn 0.9910 0.0000 0.1340
+vn 0.9854 0.0000 0.1703
+vn 0.9775 0.0000 0.2110
+vn 0.9665 0.0000 0.2567
+vn 0.9514 0.0000 0.3081
+vn 0.9307 0.0000 0.3657
+vn 0.9027 0.0000 0.4301
+vn 0.8607 0.0000 0.5090
+vn 0.8028 0.0000 0.5962
+vn 0.7350 0.0000 0.6781
+vn 0.6587 0.0000 0.7524
+vn 0.5766 0.0000 0.8170
+vn 0.4919 0.0000 0.8706
+vn 0.4076 0.0000 0.9131
+vn 0.3262 0.0000 0.9453
+vn 0.2493 0.0000 0.9684
+vn 0.1781 0.0000 0.9840
+vn 0.1130 0.0000 0.9936
+vn 0.0539 0.0000 0.9985
+vn -0.0003 0.0000 1.0000
+vn -0.0552 0.0000 0.9984
+vn -0.1155 0.0000 0.9933
+vn -0.1816 0.0000 0.9834
+vn -0.2536 0.0000 0.9673
+vn -0.1816 0.0000 0.9833
+vn -0.3309 0.0000 0.9436
+vn -0.4125 0.0000 0.9109
+vn -0.4968 0.0000 0.8679
+vn -0.5812 0.0000 0.8137
+vn -0.6629 0.0000 0.7487
+vn -0.7388 0.0000 0.6739
+vn -0.8063 0.0000 0.5915
+vn -0.8611 0.0000 0.5084
+vn -0.9008 0.0000 0.4342
+vn -0.9291 0.0000 0.3696
+vn -0.9502 0.0000 0.3116
+vn -0.9656 0.0000 0.2598
+vn -0.9769 0.0000 0.2135
+vn -0.9850 0.0000 0.1723
+vn -0.9908 0.0000 0.1355
+vn -0.9947 0.0000 0.1025
+vn -0.9973 0.0000 0.0729
+vn -0.9989 0.0000 0.0462
+vn -0.9997 0.0000 0.0221
+vn -1.0000 0.0000 -0.0002
+vn -0.9997 0.0000 -0.0229
+vn -0.9988 0.0000 -0.0479
+vn -0.9972 0.0000 -0.0753
+vn -0.9944 0.0000 -0.1054
+vn -0.9903 0.0000 -0.1386
+vn -0.9845 0.0000 -0.1754
+vn -0.9764 0.0000 -0.2159
+vn -0.9654 0.0000 -0.2608
+vn -0.9506 0.0000 -0.3104
+vn -0.9311 0.0000 -0.3648
+vn -0.9055 0.0000 -0.4243
+vn -0.8679 0.0000 -0.4968
+vn -0.8153 0.0000 -0.5790
+vn -0.7525 0.0000 -0.6586
+vn -0.6803 0.0000 -0.7329
+vn -0.6010 0.0000 -0.7992
+vn -0.5172 0.0000 -0.8559
+vn -0.4319 0.0000 -0.9019
+vn -0.3479 0.0000 -0.9375
+vn -0.2673 0.0000 -0.9636
+vn -0.1917 0.0000 -0.9814
+vn -0.1220 0.0000 -0.9925
+vn -0.0583 0.0000 -0.9983
+vn 0.0583 0.0000 -0.9983
+vn 0.1220 0.0000 -0.9925
+vn 0.1919 0.0000 -0.9814
+vn 0.2677 0.0000 -0.9635
+vn 0.3486 0.0000 -0.9373
+vn 0.4330 0.0000 -0.9014
+vn 0.5190 0.0000 -0.8548
+vn 0.6035 0.0000 -0.7973
+vn 0.6836 0.0000 -0.7298
+vn 0.7565 0.0000 -0.6539
+vn 0.8199 0.0000 -0.5724
+vn 0.8704 0.0000 -0.4924
+s off
+f 10//1 12//1 11//1
+f 10//1 13//1 12//1
+f 10//1 14//1 13//1
+f 10//1 1//1 14//1
+f 10//1 63//1 1//1
+f 63//1 62//1 1//1
+f 62//1 2//1 1//1
+f 61//1 2//1 62//1
+f 60//1 2//1 61//1
+f 10//1 64//1 63//1
+f 59//1 2//1 60//1
+f 10//1 65//1 64//1
+f 58//1 2//1 59//1
+f 10//1 66//1 65//1
+f 58//1 178//1 2//1
+f 178//1 176//1 2//1
+f 176//1 3//1 2//1
+f 57//1 178//1 58//1
+f 10//1 67//1 66//1
+f 56//1 178//1 57//1
+f 10//1 68//1 67//1
+f 9//1 75//1 10//1
+f 75//1 74//1 10//1
+f 74//1 73//1 10//1
+f 73//1 72//1 10//1
+f 72//1 71//1 10//1
+f 71//1 70//1 10//1
+f 70//1 69//1 10//1
+f 69//1 68//1 10//1
+f 55//1 178//1 56//1
+f 54//1 179//1 55//1
+f 179//1 178//1 55//1
+f 54//1 180//1 179//1
+f 177//1 176//1 178//1
+f 53//1 180//1 54//1
+f 52//1 180//1 53//1
+f 51//1 180//1 52//1
+f 50//1 180//1 51//1
+f 49//1 180//1 50//1
+f 314//1 316//1 315//1
+f 313//1 316//1 314//1
+f 313//1 317//1 316//1
+f 313//1 318//1 317//1
+f 312//1 318//1 313//1
+f 312//1 319//1 318//1
+f 311//1 319//1 312//1
+f 48//1 180//1 49//1
+f 9//1 76//1 75//1
+f 311//1 320//1 319//1
+f 310//1 320//1 311//1
+f 310//1 321//1 320//1
+f 309//1 321//1 310//1
+f 309//1 322//1 321//1
+f 308//1 322//1 309//1
+f 308//1 323//1 322//1
+f 307//1 323//1 308//1
+f 47//1 180//1 48//1
+f 9//1 77//1 76//1
+f 307//1 324//1 323//1
+f 306//1 324//1 307//1
+f 306//1 325//1 324//1
+f 305//1 325//1 306//1
+f 46//1 180//1 47//1
+f 9//1 78//1 77//1
+f 305//1 326//1 325//1
+f 304//1 326//1 305//1
+f 304//1 327//1 326//1
+f 303//1 327//1 304//1
+f 45//1 180//1 46//1
+f 9//1 79//1 78//1
+f 302//1 327//1 303//1
+f 302//1 232//1 327//1
+f 301//1 232//1 302//1
+f 301//1 233//1 232//1
+f 44//1 181//1 45//1
+f 181//1 180//1 45//1
+f 9//1 80//1 79//1
+f 300//1 233//1 301//1
+f 300//1 234//1 233//1
+f 44//1 182//1 181//1
+f 175//1 3//1 176//1
+f 299//1 234//1 300//1
+f 299//1 235//1 234//1
+f 43//1 182//1 44//1
+f 9//1 81//1 80//1
+f 298//1 235//1 299//1
+f 298//1 236//1 235//1
+f 42//1 182//1 43//1
+f 9//1 82//1 81//1
+f 297//1 236//1 298//1
+f 297//1 237//1 236//1
+f 296//1 237//1 297//1
+f 296//1 238//1 237//1
+f 41//1 182//1 42//1
+f 9//1 83//1 82//1
+f 295//1 238//1 296//1
+f 295//1 239//1 238//1
+f 40//1 182//1 41//1
+f 9//1 84//1 83//1
+f 294//1 239//1 295//1
+f 294//1 240//1 239//1
+f 40//1 183//1 182//1
+f 40//1 184//1 183//1
+f 173//1 175//1 174//1
+f 173//1 3//1 175//1
+f 293//1 240//1 294//1
+f 293//1 241//1 240//1
+f 40//1 185//1 184//1
+f 39//1 185//1 40//1
+f 9//1 85//1 84//1
+f 292//1 241//1 293//1
+f 292//1 242//1 241//1
+f 39//1 186//1 185//1
+f 38//1 186//1 39//1
+f 9//1 86//1 85//1
+f 291//1 242//1 292//1
+f 291//1 243//1 242//1
+f 38//1 187//1 186//1
+f 290//1 243//1 291//1
+f 37//1 187//1 38//1
+f 9//1 87//1 86//1
+f 290//1 244//1 243//1
+f 37//1 188//1 187//1
+f 36//1 188//1 37//1
+f 289//1 244//1 290//1
+f 289//1 245//1 244//1
+f 9//1 88//1 87//1
+f 35//1 188//1 36//1
+f 35//1 189//1 188//1
+f 288//1 245//1 289//1
+f 288//1 246//1 245//1
+f 34//1 189//1 35//1
+f 9//1 89//1 88//1
+f 287//1 246//1 288//1
+f 287//1 247//1 246//1
+f 34//1 190//1 189//1
+f 33//1 190//1 34//1
+f 286//1 247//1 287//1
+f 286//1 248//1 247//1
+f 9//1 90//1 89//1
+f 33//1 191//1 190//1
+f 32//1 191//1 33//1
+f 285//1 248//1 286//1
+f 285//1 249//1 248//1
+f 31//1 191//1 32//1
+f 31//1 192//1 191//1
+f 9//1 91//1 90//1
+f 284//1 249//1 285//1
+f 284//1 250//1 249//1
+f 30//1 192//1 31//1
+f 30//1 193//1 192//1
+f 283//1 250//1 284//1
+f 283//1 251//1 250//1
+f 9//1 92//1 91//1
+f 29//1 193//1 30//1
+f 29//1 194//1 193//1
+f 172//1 3//1 173//1
+f 282//1 251//1 283//1
+f 282//1 252//1 251//1
+f 29//1 195//1 194//1
+f 171//1 3//1 172//1
+f 29//1 196//1 195//1
+f 28//1 196//1 29//1
+f 9//1 93//1 92//1
+f 170//1 3//1 171//1
+f 281//1 252//1 282//1
+f 281//1 253//1 252//1
+f 27//1 196//1 28//1
+f 169//1 3//1 170//1
+f 27//1 197//1 196//1
+f 280//1 253//1 281//1
+f 280//1 254//1 253//1
+f 168//1 137//1 169//1
+f 137//1 3//1 169//1
+f 9//1 94//1 93//1
+f 26//1 197//1 27//1
+f 167//1 137//1 168//1
+f 279//1 254//1 280//1
+f 279//1 255//1 254//1
+f 26//1 198//1 197//1
+f 166//1 137//1 167//1
+f 25//1 198//1 26//1
+f 278//1 255//1 279//1
+f 278//1 256//1 255//1
+f 165//1 137//1 166//1
+f 9//1 95//1 94//1
+f 25//1 199//1 198//1
+f 164//1 137//1 165//1
+f 277//1 256//1 278//1
+f 277//1 257//1 256//1
+f 24//1 199//1 25//1
+f 163//1 137//1 164//1
+f 276//1 257//1 277//1
+f 276//1 258//1 257//1
+f 162//1 137//1 163//1
+f 24//1 200//1 199//1
+f 161//1 137//1 162//1
+f 23//1 200//1 24//1
+f 9//1 96//1 95//1
+f 275//1 258//1 276//1
+f 275//1 259//1 258//1
+f 160//1 137//1 161//1
+f 159//1 137//1 160//1
+f 274//1 259//1 275//1
+f 158//1 137//1 159//1
+f 274//1 260//1 259//1
+f 22//1 200//1 23//1
+f 157//1 137//1 158//1
+f 22//1 201//1 200//1
+f 156//1 137//1 157//1
+f 273//1 260//1 274//1
+f 273//1 261//1 260//1
+f 155//1 137//1 156//1
+f 9//1 97//1 96//1
+f 154//1 137//1 155//1
+f 153//1 137//1 154//1
+f 153//1 138//1 137//1
+f 231//1 3//1 137//1
+f 153//1 139//1 138//1
+f 153//1 140//1 139//1
+f 272//1 261//1 273//1
+f 153//1 141//1 140//1
+f 152//1 141//1 153//1
+f 272//1 262//1 261//1
+f 152//1 142//1 141//1
+f 152//1 143//1 142//1
+f 21//1 201//1 22//1
+f 151//1 143//1 152//1
+f 151//1 144//1 143//1
+f 151//1 145//1 144//1
+f 151//1 146//1 145//1
+f 150//1 146//1 151//1
+f 150//1 147//1 146//1
+f 150//1 148//1 147//1
+f 149//1 148//1 150//1
+f 21//1 202//1 201//1
+f 271//1 262//1 272//1
+f 271//1 263//1 262//1
+f 270//1 263//1 271//1
+f 270//1 264//1 263//1
+f 269//1 264//1 270//1
+f 269//1 265//1 264//1
+f 20//1 202//1 21//1
+f 9//1 98//1 97//1
+f 268//1 265//1 269//1
+f 268//1 266//1 265//1
+f 267//1 266//1 268//1
+f 20//1 203//1 202//1
+f 19//1 203//1 20//1
+f 19//1 204//1 203//1
+f 9//1 99//1 98//1
+f 18//1 204//1 19//1
+f 18//1 205//1 204//1
+f 17//1 205//1 18//1
+f 9//1 100//1 99//1
+f 17//1 206//1 205//1
+f 16//1 206//1 17//1
+f 9//1 101//1 100//1
+f 16//1 207//1 206//1
+f 15//1 207//1 16//1
+f 15//1 208//1 207//1
+f 136//1 208//1 15//1
+f 9//1 102//1 101//1
+f 136//1 209//1 208//1
+f 135//1 209//1 136//1
+f 134//1 209//1 135//1
+f 134//1 210//1 209//1
+f 9//1 103//1 102//1
+f 133//1 210//1 134//1
+f 133//1 211//1 210//1
+f 133//1 212//1 211//1
+f 9//1 104//1 103//1
+f 132//1 212//1 133//1
+f 132//1 213//1 212//1
+f 230//1 3//1 231//1
+f 229//1 3//1 230//1
+f 132//1 214//1 213//1
+f 228//1 3//1 229//1
+f 9//1 105//1 104//1
+f 227//1 3//1 228//1
+f 132//1 215//1 214//1
+f 226//1 3//1 227//1
+f 131//1 215//1 132//1
+f 225//1 3//1 226//1
+f 131//1 216//1 215//1
+f 224//1 3//1 225//1
+f 131//1 217//1 216//1
+f 223//1 3//1 224//1
+f 9//1 106//1 105//1
+f 222//1 3//1 223//1
+f 131//1 218//1 217//1
+f 221//1 3//1 222//1
+f 220//1 3//1 221//1
+f 131//1 219//1 218//1
+f 219//1 3//1 220//1
+f 131//1 3//1 219//1
+f 9//1 107//1 106//1
+f 130//1 3//1 131//1
+f 121//1 123//1 122//1
+f 9//1 108//1 107//1
+f 120//1 123//1 121//1
+f 119//1 123//1 120//1
+f 118//1 123//1 119//1
+f 117//1 123//1 118//1
+f 9//1 109//1 108//1
+f 116//1 123//1 117//1
+f 115//1 123//1 116//1
+f 114//1 123//1 115//1
+f 113//1 123//1 114//1
+f 9//1 110//1 109//1
+f 112//1 123//1 113//1
+f 111//1 123//1 112//1
+f 110//1 123//1 111//1
+f 9//1 123//1 110//1
+f 129//1 3//1 130//1
+f 128//1 3//1 129//1
+f 128//1 4//1 3//1
+f 127//1 4//1 128//1
+f 8//1 123//1 9//1
+f 126//1 4//1 127//1
+f 125//1 4//1 126//1
+f 124//1 4//1 125//1
+f 123//1 4//1 124//1
+f 7//1 123//1 8//1
+f 7//1 4//1 123//1
+f 6//2 4//2 7//2
+f 5//3 4//3 6//3
+f 339//4 337//4 338//4
+f 340//4 337//4 339//4
+f 341//4 337//4 340//4
+f 328//4 337//4 341//4
+f 390//4 337//4 328//4
+f 389//4 390//4 328//4
+f 329//4 389//4 328//4
+f 329//4 388//4 389//4
+f 329//4 387//4 388//4
+f 391//4 337//4 390//4
+f 329//4 386//4 387//4
+f 392//4 337//4 391//4
+f 329//4 385//4 386//4
+f 393//4 337//4 392//4
+f 505//4 385//4 329//4
+f 503//4 505//4 329//4
+f 330//4 503//4 329//4
+f 505//4 384//4 385//4
+f 394//4 337//4 393//4
+f 505//4 383//4 384//4
+f 395//4 337//4 394//4
+f 402//4 336//4 337//4
+f 401//4 402//4 337//4
+f 400//4 401//4 337//4
+f 399//4 400//4 337//4
+f 398//4 399//4 337//4
+f 397//4 398//4 337//4
+f 396//4 397//4 337//4
+f 395//4 396//4 337//4
+f 505//4 382//4 383//4
+f 506//4 381//4 382//4
+f 505//4 506//4 382//4
+f 507//4 381//4 506//4
+f 503//4 504//4 505//4
+f 507//4 380//4 381//4
+f 507//4 379//4 380//4
+f 507//4 378//4 379//4
+f 507//4 377//4 378//4
+f 507//4 376//4 377//4
+f 643//4 641//4 642//4
+f 643//4 640//4 641//4
+f 644//4 640//4 643//4
+f 645//4 640//4 644//4
+f 645//4 639//4 640//4
+f 646//4 639//4 645//4
+f 646//4 638//4 639//4
+f 507//4 375//4 376//4
+f 403//4 336//4 402//4
+f 647//4 638//4 646//4
+f 647//4 637//4 638//4
+f 648//4 637//4 647//4
+f 648//4 636//4 637//4
+f 649//4 636//4 648//4
+f 649//4 635//4 636//4
+f 650//4 635//4 649//4
+f 650//4 634//4 635//4
+f 507//4 374//4 375//4
+f 404//4 336//4 403//4
+f 651//4 634//4 650//4
+f 651//4 633//4 634//4
+f 652//4 633//4 651//4
+f 652//4 632//4 633//4
+f 507//4 373//4 374//4
+f 405//4 336//4 404//4
+f 653//4 632//4 652//4
+f 653//4 631//4 632//4
+f 654//4 631//4 653//4
+f 654//4 630//4 631//4
+f 507//4 372//4 373//4
+f 406//4 336//4 405//4
+f 654//4 629//4 630//4
+f 559//4 629//4 654//4
+f 559//4 628//4 629//4
+f 560//4 628//4 559//4
+f 508//4 371//4 372//4
+f 507//4 508//4 372//4
+f 407//4 336//4 406//4
+f 560//4 627//4 628//4
+f 561//4 627//4 560//4
+f 509//4 371//4 508//4
+f 330//4 502//4 503//4
+f 561//4 626//4 627//4
+f 562//4 626//4 561//4
+f 509//4 370//4 371//4
+f 408//4 336//4 407//4
+f 562//4 625//4 626//4
+f 563//4 625//4 562//4
+f 509//4 369//4 370//4
+f 409//4 336//4 408//4
+f 563//4 624//4 625//4
+f 564//4 624//4 563//4
+f 564//4 623//4 624//4
+f 565//4 623//4 564//4
+f 509//4 368//4 369//4
+f 410//4 336//4 409//4
+f 565//4 622//4 623//4
+f 566//4 622//4 565//4
+f 509//4 367//4 368//4
+f 411//4 336//4 410//4
+f 566//4 621//4 622//4
+f 567//4 621//4 566//4
+f 510//4 367//4 509//4
+f 511//4 367//4 510//4
+f 502//4 500//4 501//4
+f 330//4 500//4 502//4
+f 567//4 620//4 621//4
+f 568//4 620//4 567//4
+f 512//4 367//4 511//4
+f 512//4 366//4 367//4
+f 412//4 336//4 411//4
+f 568//4 619//4 620//4
+f 569//4 619//4 568//4
+f 513//4 366//4 512//4
+f 513//4 365//4 366//4
+f 413//4 336//4 412//4
+f 569//4 618//4 619//4
+f 570//4 618//4 569//4
+f 514//4 365//4 513//4
+f 570//4 617//4 618//4
+f 514//4 364//4 365//4
+f 414//4 336//4 413//4
+f 571//4 617//4 570//4
+f 515//4 364//4 514//4
+f 515//4 363//4 364//4
+f 571//4 616//4 617//4
+f 572//4 616//4 571//4
+f 415//4 336//4 414//4
+f 515//4 362//4 363//4
+f 516//4 362//4 515//4
+f 572//4 615//4 616//4
+f 573//4 615//4 572//4
+f 516//4 361//4 362//4
+f 416//4 336//4 415//4
+f 573//4 614//4 615//4
+f 574//4 614//4 573//4
+f 517//4 361//4 516//4
+f 517//4 360//4 361//4
+f 574//4 613//4 614//4
+f 575//4 613//4 574//4
+f 417//4 336//4 416//4
+f 518//4 360//4 517//4
+f 518//4 359//4 360//4
+f 575//4 612//4 613//4
+f 576//4 612//4 575//4
+f 518//4 358//4 359//4
+f 519//4 358//4 518//4
+f 418//4 336//4 417//4
+f 576//4 611//4 612//4
+f 577//4 611//4 576//4
+f 519//4 357//4 358//4
+f 520//4 357//4 519//4
+f 577//4 610//4 611//4
+f 578//4 610//4 577//4
+f 419//4 336//4 418//4
+f 520//4 356//4 357//4
+f 521//4 356//4 520//4
+f 330//4 499//4 500//4
+f 578//4 609//4 610//4
+f 579//4 609//4 578//4
+f 522//4 356//4 521//4
+f 330//4 498//4 499//4
+f 523//4 356//4 522//4
+f 523//4 355//4 356//4
+f 420//4 336//4 419//4
+f 330//4 497//4 498//4
+f 579//4 608//4 609//4
+f 580//4 608//4 579//4
+f 523//4 354//4 355//4
+f 330//4 496//4 497//4
+f 524//4 354//4 523//4
+f 580//4 607//4 608//4
+f 581//4 607//4 580//4
+f 464//4 495//4 496//4
+f 330//4 464//4 496//4
+f 421//4 336//4 420//4
+f 524//4 353//4 354//4
+f 464//4 494//4 495//4
+f 581//4 606//4 607//4
+f 582//4 606//4 581//4
+f 525//4 353//4 524//4
+f 464//4 493//4 494//4
+f 525//4 352//4 353//4
+f 582//4 605//4 606//4
+f 583//4 605//4 582//4
+f 464//4 492//4 493//4
+f 422//4 336//4 421//4
+f 526//4 352//4 525//4
+f 464//4 491//4 492//4
+f 583//4 604//4 605//4
+f 584//4 604//4 583//4
+f 526//4 351//4 352//4
+f 464//4 490//4 491//4
+f 584//4 603//4 604//4
+f 585//4 603//4 584//4
+f 464//4 489//4 490//4
+f 527//4 351//4 526//4
+f 464//4 488//4 489//4
+f 527//4 350//4 351//4
+f 423//4 336//4 422//4
+f 585//4 602//4 603//4
+f 586//4 602//4 585//4
+f 464//4 487//4 488//4
+f 464//4 486//4 487//4
+f 586//4 601//4 602//4
+f 464//4 485//4 486//4
+f 587//4 601//4 586//4
+f 527//4 349//4 350//4
+f 464//4 484//4 485//4
+f 528//4 349//4 527//4
+f 464//4 483//4 484//4
+f 587//4 600//4 601//4
+f 588//4 600//4 587//4
+f 464//4 482//4 483//4
+f 424//4 336//4 423//4
+f 464//4 481//4 482//4
+f 464//4 480//4 481//4
+f 465//4 480//4 464//4
+f 330//4 558//4 464//4
+f 466//4 480//4 465//4
+f 467//4 480//4 466//4
+f 588//4 599//4 600//4
+f 468//4 480//4 467//4
+f 468//4 479//4 480//4
+f 589//4 599//4 588//4
+f 469//4 479//4 468//4
+f 470//4 479//4 469//4
+f 528//4 348//4 349//4
+f 470//4 478//4 479//4
+f 471//4 478//4 470//4
+f 472//4 478//4 471//4
+f 473//4 478//4 472//4
+f 473//4 477//4 478//4
+f 474//4 477//4 473//4
+f 475//5 477//5 474//5
+f 475//6 476//6 477//6
+f 529//4 348//4 528//4
+f 589//4 598//4 599//4
+f 590//4 598//4 589//4
+f 590//4 597//4 598//4
+f 591//4 597//4 590//4
+f 591//4 596//4 597//4
+f 592//4 596//4 591//4
+f 529//4 347//4 348//4
+f 425//4 336//4 424//4
+f 592//4 595//4 596//4
+f 593//4 595//4 592//4
+f 593//4 594//4 595//4
+f 530//4 347//4 529//4
+f 530//4 346//4 347//4
+f 531//4 346//4 530//4
+f 426//4 336//4 425//4
+f 531//4 345//4 346//4
+f 532//4 345//4 531//4
+f 532//4 344//4 345//4
+f 427//4 336//4 426//4
+f 533//4 344//4 532//4
+f 533//4 343//4 344//4
+f 428//4 336//4 427//4
+f 534//4 343//4 533//4
+f 534//4 342//4 343//4
+f 535//4 342//4 534//4
+f 535//4 463//4 342//4
+f 429//4 336//4 428//4
+f 536//4 463//4 535//4
+f 536//4 462//4 463//4
+f 536//4 461//4 462//4
+f 537//4 461//4 536//4
+f 430//4 336//4 429//4
+f 537//4 460//4 461//4
+f 538//4 460//4 537//4
+f 539//4 460//4 538//4
+f 431//4 336//4 430//4
+f 539//4 459//4 460//4
+f 540//4 459//4 539//4
+f 330//4 557//4 558//4
+f 330//4 556//4 557//4
+f 541//4 459//4 540//4
+f 330//4 555//4 556//4
+f 432//4 336//4 431//4
+f 330//4 554//4 555//4
+f 542//4 459//4 541//4
+f 330//4 553//4 554//4
+f 542//4 458//4 459//4
+f 330//4 552//4 553//4
+f 543//4 458//4 542//4
+f 330//4 551//4 552//4
+f 544//4 458//4 543//4
+f 330//4 550//4 551//4
+f 433//4 336//4 432//4
+f 330//4 549//4 550//4
+f 545//4 458//4 544//4
+f 330//4 548//4 549//4
+f 330//4 547//4 548//4
+f 546//4 458//4 545//4
+f 330//4 546//4 547//4
+f 330//4 458//4 546//4
+f 434//4 336//4 433//4
+f 330//4 457//4 458//4
+f 450//4 448//4 449//4
+f 435//4 336//4 434//4
+f 450//4 447//4 448//4
+f 450//4 446//4 447//4
+f 450//4 445//4 446//4
+f 450//4 444//4 445//4
+f 436//4 336//4 435//4
+f 450//4 443//4 444//4
+f 450//4 442//4 443//4
+f 450//4 441//4 442//4
+f 450//4 440//4 441//4
+f 437//4 336//4 436//4
+f 450//4 439//4 440//4
+f 450//4 438//4 439//4
+f 450//4 437//4 438//4
+f 450//4 336//4 437//4
+f 330//4 456//4 457//4
+f 330//4 455//4 456//4
+f 331//4 455//4 330//4
+f 331//4 454//4 455//4
+f 450//4 335//4 336//4
+f 331//4 453//4 454//4
+f 331//4 452//4 453//4
+f 331//4 451//4 452//4
+f 331//4 450//4 451//4
+f 450//4 334//4 335//4
+f 331//4 334//4 450//4
+f 331//2 333//2 334//2
+f 331//3 332//3 333//3
+s 1
+f 658//7 655//7 656//7
+f 660//8 657//7 658//7
+f 662//9 659//8 660//8
+f 664//2 661//9 662//9
+f 666//2 663//2 664//2
+f 668//10 665//2 666//2
+f 670//11 667//10 668//10
+f 672//11 669//11 670//11
+f 674//12 671//11 672//11
+f 676//13 673//12 674//12
+f 678//3 675//13 676//13
+f 680//3 677//3 678//3
+f 682//14 679//3 680//3
+f 656//7 681//14 682//14
+f 686//15 683//16 684//16
+f 688//17 685//15 686//15
+f 690//18 687//17 688//17
+f 692//19 689//18 690//18
+f 694//20 691//19 692//19
+f 696//21 693//20 694//20
+f 698//22 695//23 696//21
+f 700//24 697//22 698//22
+f 702//25 699//24 700//24
+f 704//26 701//25 702//25
+f 706//27 703//26 704//26
+f 708//28 705//27 706//27
+f 710//29 707//28 708//28
+f 712//30 709//29 710//29
+f 714//31 711//30 712//30
+f 716//32 713//31 714//31
+f 718//33 715//32 716//32
+f 720//34 717//33 718//33
+f 722//35 719//34 720//34
+f 724//36 721//35 722//35
+f 726//37 723//36 724//36
+f 728//38 725//37 726//37
+f 730//39 727//38 728//38
+f 732//40 729//39 730//39
+f 734//41 731//40 732//40
+f 736//42 733//41 734//41
+f 738//43 735//42 736//42
+f 740//44 737//43 738//43
+f 742//45 739//44 740//44
+f 744//46 741//45 742//45
+f 746//47 743//46 744//46
+f 748//48 745//47 746//47
+f 750//49 747//48 748//48
+f 752//50 749//49 750//49
+f 754//51 751//50 752//50
+f 756//52 753//51 754//51
+f 758//53 755//52 756//52
+f 760//54 757//53 758//53
+f 762//55 759//54 760//54
+f 764//56 761//55 762//55
+f 766//57 763//56 764//56
+f 768//58 765//57 766//57
+f 770//59 767//58 768//58
+f 772//60 769//59 770//59
+f 774//61 771//60 772//60
+f 776//62 773//61 774//61
+f 778//63 775//62 776//62
+f 780//64 777//63 778//63
+f 782//65 779//64 780//64
+f 784//66 781//65 782//65
+f 786//67 783//66 784//66
+f 788//68 785//67 786//67
+f 790//69 787//68 788//68
+f 792//70 789//69 790//69
+f 794//71 791//70 792//70
+f 796//72 793//71 794//71
+f 798//73 795//72 796//72
+f 800//74 797//73 798//73
+f 802//75 799//74 800//74
+f 804//76 801//75 802//75
+f 806//77 803//76 804//76
+f 808//78 805//77 806//77
+f 810//79 807//78 808//78
+f 812//80 809//79 810//79
+f 814//81 811//80 812//80
+f 816//82 813//81 814//81
+f 818//83 815//82 816//82
+f 820//84 817//83 818//83
+f 822//85 819//84 820//84
+f 824//86 821//85 822//85
+f 826//87 823//86 824//86
+f 828//88 825//87 826//87
+f 830//89 827//88 828//88
+f 832//90 829//89 830//89
+f 834//91 831//90 832//90
+f 836//92 833//91 834//91
+f 838//93 835//92 836//92
+f 840//94 837//93 838//93
+f 842//95 839//94 840//94
+f 844//96 841//95 842//95
+f 846//97 843//96 844//96
+f 848//98 845//97 846//97
+f 850//99 847//98 848//98
+f 852//100 849//99 850//99
+f 854//101 851//100 852//100
+f 856//102 853//101 854//101
+f 858//103 855//102 856//102
+f 860//104 857//103 858//103
+f 862//105 859//104 860//104
+f 864//106 861//105 862//105
+f 866//107 863//106 864//106
+f 868//108 865//107 866//107
+f 870//109 867//108 868//108
+f 872//110 869//109 870//109
+f 874//111 871//110 872//110
+f 876//112 873//111 874//111
+f 878//113 875//112 876//112
+f 880//114 877//113 878//113
+f 882//115 879//114 880//114
+f 884//116 881//115 882//115
+f 886//117 883//116 884//116
+f 888//118 885//117 886//117
+f 890//119 887//118 888//118
+f 892//120 889//119 890//119
+f 894//121 891//122 892//120
+f 896//123 893//121 894//121
+f 898//124 895//123 896//123
+f 900//125 897//124 898//124
+f 902//126 899//125 900//125
+f 904//127 901//126 902//126
+f 906//127 903//127 904//127
+f 908//127 905//127 906//127
+f 910//127 907//127 908//127
+f 912//127 909//127 910//127
+f 914//127 911//127 912//127
+f 916//127 913//127 914//127
+f 918//127 915//127 916//127
+f 920//127 917//127 918//127
+f 922//127 919//127 920//127
+f 924//127 921//127 922//127
+f 926//128 923//127 924//127
+f 684//16 925//128 926//128
+f 930//129 927//130 928//130
+f 932//129 929//129 930//129
+f 934//129 931//129 932//129
+f 936//129 933//129 934//129
+f 938//129 935//129 936//129
+f 940//129 937//129 938//129
+f 942//129 939//129 940//129
+f 944//129 941//129 942//129
+f 946//129 943//129 944//129
+f 948//129 945//129 946//129
+f 950//131 947//129 948//129
+f 952//132 949//129 950//131
+f 954//133 951//134 952//132
+f 956//135 953//133 954//133
+f 958//136 955//135 956//135
+f 960//137 957//136 958//136
+f 962//138 959//137 960//137
+f 964//139 961//138 962//138
+f 966//140 963//139 964//139
+f 968//141 965//140 966//140
+f 970//142 967//141 968//141
+f 972//143 969//142 970//142
+f 974//144 971//143 972//143
+f 976//145 973//144 974//144
+f 978//146 975//145 976//145
+f 980//147 977//146 978//146
+f 982//148 979//147 980//147
+f 984//149 981//148 982//148
+f 986//150 983//149 984//149
+f 988//151 985//150 986//150
+f 990//152 987//151 988//151
+f 992//153 989//152 990//152
+f 994//154 991//153 992//153
+f 996//155 993//154 994//154
+f 998//156 995//155 996//155
+f 1000//157 997//156 998//156
+f 1002//158 999//157 1000//157
+f 1004//158 1001//158 1002//158
+f 1006//10 1003//158 1004//158
+f 1008//10 1005//10 1006//10
+f 1010//10 1007//10 1008//10
+f 1012//159 1009//10 1010//10
+f 1014//159 1011//159 1012//159
+f 1016//159 1013//159 1014//159
+f 1018//14 1015//159 1016//159
+f 1020//14 1017//14 1018//14
+f 1022//7 1019//14 1020//14
+f 1024//7 1021//7 1022//7
+f 1026//7 1023//7 1024//7
+f 1028//7 1025//7 1026//7
+f 1030//7 1027//7 1028//7
+f 1032//7 1029//7 1030//7
+f 1034//7 1031//7 1032//7
+f 1036//7 1033//7 1034//7
+f 1038//7 1035//7 1036//7
+f 1040//7 1037//7 1038//7
+f 1042//7 1039//7 1040//7
+f 1044//160 1041//7 1042//7
+f 1046//161 1043//160 1044//160
+f 1048//162 1045//161 1046//161
+f 1050//163 1047//162 1048//162
+f 1052//164 1049//163 1050//163
+f 1054//165 1051//164 1052//164
+f 1056//166 1053//165 1054//165
+f 1058//167 1055//166 1056//166
+f 1060//168 1057//167 1058//167
+f 1062//96 1059//168 1060//168
+f 1064//169 1061//96 1062//96
+f 1066//170 1063//169 1064//169
+f 1068//171 1065//170 1066//170
+f 1070//172 1067//171 1068//171
+f 1072//173 1069//172 1070//172
+f 1074//174 1071//173 1072//173
+f 1076//175 1073//174 1074//174
+f 1078//176 1075//175 1076//175
+f 1080//177 1077//176 1078//176
+f 1082//178 1079//179 1080//177
+f 1084//180 1081//178 1082//178
+f 1086//181 1083//180 1084//180
+f 1088//182 1085//181 1086//181
+f 1090//183 1087//182 1088//182
+f 1092//184 1089//183 1090//183
+f 1094//185 1091//184 1092//184
+f 1096//186 1093//185 1094//185
+f 1098//187 1095//186 1096//186
+f 1100//188 1097//187 1098//187
+f 1102//189 1099//188 1100//188
+f 1104//190 1101//189 1102//189
+f 1106//191 1103//190 1104//190
+f 1108//192 1105//191 1106//191
+f 1110//193 1107//192 1108//192
+f 1112//194 1109//193 1110//193
+f 1114//195 1111//194 1112//194
+f 1116//196 1113//195 1114//195
+f 928//130 1115//196 1116//196
+f 1120//197 1117//198 1118//198
+f 1122//199 1119//197 1120//197
+f 1124//200 1121//199 1122//199
+f 1126//201 1123//200 1124//200
+f 1128//202 1125//201 1126//201
+f 1130//203 1127//202 1128//202
+f 1132//204 1129//203 1130//203
+f 1134//205 1131//204 1132//204
+f 1136//206 1133//205 1134//205
+f 1138//207 1135//206 1136//206
+f 1140//7 1137//207 1138//207
+f 1142//208 1139//7 1140//7
+f 1144//209 1141//208 1142//208
+f 1146//210 1143//209 1144//209
+f 1148//211 1145//210 1146//210
+f 1150//212 1147//211 1148//211
+f 1152//213 1149//212 1150//212
+f 1154//214 1151//213 1152//213
+f 1156//215 1153//214 1154//214
+f 1158//216 1155//215 1156//215
+f 1160//217 1157//216 1158//216
+f 1162//218 1159//217 1160//217
+f 1164//219 1161//218 1162//218
+f 1166//220 1163//219 1164//219
+f 1168//221 1165//220 1166//220
+f 1170//222 1167//221 1168//221
+f 1172//223 1169//222 1170//222
+f 1174//224 1171//223 1172//223
+f 1176//225 1173//224 1174//224
+f 1178//226 1175//225 1176//225
+f 1180//227 1177//226 1178//226
+f 1182//228 1179//227 1180//227
+f 1184//229 1181//228 1182//228
+f 1186//230 1183//229 1184//229
+f 1188//231 1185//230 1186//230
+f 1190//232 1187//231 1188//231
+f 1192//233 1189//232 1190//232
+f 1194//234 1191//233 1192//233
+f 1196//235 1193//236 1194//234
+f 1198//237 1195//235 1196//235
+f 1200//238 1197//237 1198//237
+f 1202//239 1199//238 1200//238
+f 1204//240 1201//239 1202//239
+f 1206//241 1203//240 1204//240
+f 1208//242 1205//241 1206//241
+f 1210//243 1207//242 1208//242
+f 1212//244 1209//243 1210//243
+f 1214//245 1211//244 1212//244
+f 1216//246 1213//245 1214//245
+f 1218//247 1215//246 1216//246
+f 1220//248 1217//247 1218//247
+f 1222//249 1219//248 1220//248
+f 1224//250 1221//249 1222//249
+f 1226//251 1223//250 1224//250
+f 1228//252 1225//251 1226//251
+f 1230//253 1227//252 1228//252
+f 1232//254 1229//253 1230//253
+f 1234//255 1231//254 1232//254
+f 1236//256 1233//255 1234//255
+f 1238//257 1235//256 1236//256
+f 1240//258 1237//257 1238//257
+f 1242//259 1239//258 1240//258
+f 1244//260 1241//259 1242//259
+f 1246//261 1243//260 1244//260
+f 1248//262 1245//261 1246//261
+f 1250//263 1247//262 1248//262
+f 1252//264 1249//263 1250//263
+f 1254//265 1251//264 1252//264
+f 1256//266 1253//265 1254//265
+f 1258//267 1255//266 1256//266
+f 1260//268 1257//267 1258//267
+f 1262//269 1259//268 1260//268
+f 1264//270 1261//269 1262//269
+f 1266//271 1263//270 1264//270
+f 1268//272 1265//271 1266//271
+f 1270//273 1267//272 1268//272
+f 1272//274 1269//273 1270//273
+f 1274//275 1271//274 1272//274
+f 1276//276 1273//275 1274//275
+f 1278//277 1275//276 1276//276
+f 1280//278 1277//277 1278//277
+f 1282//279 1279//278 1280//278
+f 1284//3 1281//279 1282//279
+f 1286//280 1283//3 1284//3
+f 1288//281 1285//280 1286//280
+f 1290//282 1287//281 1288//281
+f 1292//283 1289//282 1290//282
+f 1294//284 1291//283 1292//283
+f 1296//285 1293//284 1294//284
+f 1298//286 1295//285 1296//285
+f 1300//287 1297//286 1298//286
+f 1302//288 1299//287 1300//287
+f 1304//289 1301//288 1302//288
+f 1306//290 1303//289 1304//289
+f 1308//291 1305//290 1306//290
+f 1118//198 1307//291 1308//291
+f 658//7 657//7 655//7
+f 660//8 659//8 657//7
+f 662//9 661//9 659//8
+f 664//2 663//2 661//9
+f 666//2 665//2 663//2
+f 668//10 667//10 665//2
+f 670//11 669//11 667//10
+f 672//11 671//11 669//11
+f 674//12 673//12 671//11
+f 676//13 675//13 673//12
+f 678//3 677//3 675//13
+f 680//3 679//3 677//3
+f 682//14 681//14 679//3
+f 656//7 655//7 681//14
+f 686//15 685//15 683//16
+f 688//17 687//17 685//15
+f 690//18 689//18 687//17
+f 692//19 691//19 689//18
+f 694//20 693//20 691//19
+f 696//21 695//23 693//20
+f 698//22 697//22 695//23
+f 700//24 699//24 697//22
+f 702//25 701//25 699//24
+f 704//26 703//26 701//25
+f 706//27 705//27 703//26
+f 708//28 707//28 705//27
+f 710//29 709//29 707//28
+f 712//30 711//30 709//29
+f 714//31 713//31 711//30
+f 716//32 715//32 713//31
+f 718//33 717//33 715//32
+f 720//34 719//34 717//33
+f 722//35 721//35 719//34
+f 724//36 723//36 721//35
+f 726//37 725//37 723//36
+f 728//38 727//38 725//37
+f 730//39 729//39 727//38
+f 732//40 731//40 729//39
+f 734//41 733//41 731//40
+f 736//42 735//42 733//41
+f 738//43 737//43 735//42
+f 740//44 739//44 737//43
+f 742//45 741//45 739//44
+f 744//46 743//46 741//45
+f 746//47 745//47 743//46
+f 748//48 747//48 745//47
+f 750//49 749//49 747//48
+f 752//50 751//50 749//49
+f 754//51 753//51 751//50
+f 756//52 755//52 753//51
+f 758//53 757//53 755//52
+f 760//54 759//54 757//53
+f 762//55 761//55 759//54
+f 764//56 763//56 761//55
+f 766//57 765//57 763//56
+f 768//58 767//58 765//57
+f 770//59 769//59 767//58
+f 772//60 771//60 769//59
+f 774//61 773//61 771//60
+f 776//62 775//62 773//61
+f 778//63 777//63 775//62
+f 780//64 779//64 777//63
+f 782//65 781//65 779//64
+f 784//66 783//66 781//65
+f 786//67 785//67 783//66
+f 788//68 787//68 785//67
+f 790//69 789//69 787//68
+f 792//70 791//70 789//69
+f 794//71 793//71 791//70
+f 796//72 795//72 793//71
+f 798//73 797//73 795//72
+f 800//74 799//74 797//73
+f 802//75 801//75 799//74
+f 804//76 803//76 801//75
+f 806//77 805//77 803//76
+f 808//78 807//78 805//77
+f 810//79 809//79 807//78
+f 812//80 811//80 809//79
+f 814//81 813//81 811//80
+f 816//82 815//82 813//81
+f 818//83 817//83 815//82
+f 820//84 819//84 817//83
+f 822//85 821//85 819//84
+f 824//86 823//86 821//85
+f 826//87 825//87 823//86
+f 828//88 827//88 825//87
+f 830//89 829//89 827//88
+f 832//90 831//90 829//89
+f 834//91 833//91 831//90
+f 836//92 835//92 833//91
+f 838//93 837//93 835//92
+f 840//94 839//94 837//93
+f 842//95 841//95 839//94
+f 844//96 843//96 841//95
+f 846//97 845//97 843//96
+f 848//98 847//98 845//97
+f 850//99 849//99 847//98
+f 852//100 851//100 849//99
+f 854//101 853//101 851//100
+f 856//102 855//102 853//101
+f 858//103 857//103 855//102
+f 860//104 859//104 857//103
+f 862//105 861//105 859//104
+f 864//106 863//106 861//105
+f 866//107 865//107 863//106
+f 868//108 867//108 865//107
+f 870//109 869//109 867//108
+f 872//110 871//110 869//109
+f 874//111 873//111 871//110
+f 876//112 875//112 873//111
+f 878//113 877//113 875//112
+f 880//114 879//114 877//113
+f 882//115 881//115 879//114
+f 884//116 883//116 881//115
+f 886//117 885//117 883//116
+f 888//118 887//118 885//117
+f 890//119 889//119 887//118
+f 892//120 891//122 889//119
+f 894//121 893//121 891//122
+f 896//123 895//123 893//121
+f 898//124 897//124 895//123
+f 900//125 899//125 897//124
+f 902//126 901//126 899//125
+f 904//127 903//127 901//126
+f 906//127 905//127 903//127
+f 908//127 907//127 905//127
+f 910//127 909//127 907//127
+f 912//127 911//127 909//127
+f 914//127 913//127 911//127
+f 916//127 915//127 913//127
+f 918//127 917//127 915//127
+f 920//127 919//127 917//127
+f 922//127 921//127 919//127
+f 924//127 923//127 921//127
+f 926//128 925//128 923//127
+f 684//16 683//16 925//128
+f 930//129 929//129 927//130
+f 932//129 931//129 929//129
+f 934//129 933//129 931//129
+f 936//129 935//129 933//129
+f 938//129 937//129 935//129
+f 940//129 939//129 937//129
+f 942//129 941//129 939//129
+f 944//129 943//129 941//129
+f 946//129 945//129 943//129
+f 948//129 947//129 945//129
+f 950//131 949//129 947//129
+f 952//132 951//134 949//129
+f 954//133 953//133 951//134
+f 956//135 955//135 953//133
+f 958//136 957//136 955//135
+f 960//137 959//137 957//136
+f 962//138 961//138 959//137
+f 964//139 963//139 961//138
+f 966//140 965//140 963//139
+f 968//141 967//141 965//140
+f 970//142 969//142 967//141
+f 972//143 971//143 969//142
+f 974//144 973//144 971//143
+f 976//145 975//145 973//144
+f 978//146 977//146 975//145
+f 980//147 979//147 977//146
+f 982//148 981//148 979//147
+f 984//149 983//149 981//148
+f 986//150 985//150 983//149
+f 988//151 987//151 985//150
+f 990//152 989//152 987//151
+f 992//153 991//153 989//152
+f 994//154 993//154 991//153
+f 996//155 995//155 993//154
+f 998//156 997//156 995//155
+f 1000//157 999//157 997//156
+f 1002//158 1001//158 999//157
+f 1004//158 1003//158 1001//158
+f 1006//10 1005//10 1003//158
+f 1008//10 1007//10 1005//10
+f 1010//10 1009//10 1007//10
+f 1012//159 1011//159 1009//10
+f 1014//159 1013//159 1011//159
+f 1016//159 1015//159 1013//159
+f 1018//14 1017//14 1015//159
+f 1020//14 1019//14 1017//14
+f 1022//7 1021//7 1019//14
+f 1024//7 1023//7 1021//7
+f 1026//7 1025//7 1023//7
+f 1028//7 1027//7 1025//7
+f 1030//7 1029//7 1027//7
+f 1032//7 1031//7 1029//7
+f 1034//7 1033//7 1031//7
+f 1036//7 1035//7 1033//7
+f 1038//7 1037//7 1035//7
+f 1040//7 1039//7 1037//7
+f 1042//7 1041//7 1039//7
+f 1044//160 1043//160 1041//7
+f 1046//161 1045//161 1043//160
+f 1048//162 1047//162 1045//161
+f 1050//163 1049//163 1047//162
+f 1052//164 1051//164 1049//163
+f 1054//165 1053//165 1051//164
+f 1056//166 1055//166 1053//165
+f 1058//167 1057//167 1055//166
+f 1060//168 1059//168 1057//167
+f 1062//96 1061//96 1059//168
+f 1064//169 1063//169 1061//96
+f 1066//170 1065//170 1063//169
+f 1068//171 1067//171 1065//170
+f 1070//172 1069//172 1067//171
+f 1072//173 1071//173 1069//172
+f 1074//174 1073//174 1071//173
+f 1076//175 1075//175 1073//174
+f 1078//176 1077//176 1075//175
+f 1080//177 1079//179 1077//176
+f 1082//178 1081//178 1079//179
+f 1084//180 1083//180 1081//178
+f 1086//181 1085//181 1083//180
+f 1088//182 1087//182 1085//181
+f 1090//183 1089//183 1087//182
+f 1092//184 1091//184 1089//183
+f 1094//185 1093//185 1091//184
+f 1096//186 1095//186 1093//185
+f 1098//187 1097//187 1095//186
+f 1100//188 1099//188 1097//187
+f 1102//189 1101//189 1099//188
+f 1104//190 1103//190 1101//189
+f 1106//191 1105//191 1103//190
+f 1108//192 1107//192 1105//191
+f 1110//193 1109//193 1107//192
+f 1112//194 1111//194 1109//193
+f 1114//195 1113//195 1111//194
+f 1116//196 1115//196 1113//195
+f 928//130 927//130 1115//196
+f 1120//197 1119//197 1117//198
+f 1122//199 1121//199 1119//197
+f 1124//200 1123//200 1121//199
+f 1126//201 1125//201 1123//200
+f 1128//202 1127//202 1125//201
+f 1130//203 1129//203 1127//202
+f 1132//204 1131//204 1129//203
+f 1134//205 1133//205 1131//204
+f 1136//206 1135//206 1133//205
+f 1138//207 1137//207 1135//206
+f 1140//7 1139//7 1137//207
+f 1142//208 1141//208 1139//7
+f 1144//209 1143//209 1141//208
+f 1146//210 1145//210 1143//209
+f 1148//211 1147//211 1145//210
+f 1150//212 1149//212 1147//211
+f 1152//213 1151//213 1149//212
+f 1154//214 1153//214 1151//213
+f 1156//215 1155//215 1153//214
+f 1158//216 1157//216 1155//215
+f 1160//217 1159//217 1157//216
+f 1162//218 1161//218 1159//217
+f 1164//219 1163//219 1161//218
+f 1166//220 1165//220 1163//219
+f 1168//221 1167//221 1165//220
+f 1170//222 1169//222 1167//221
+f 1172//223 1171//223 1169//222
+f 1174//224 1173//224 1171//223
+f 1176//225 1175//225 1173//224
+f 1178//226 1177//226 1175//225
+f 1180//227 1179//227 1177//226
+f 1182//228 1181//228 1179//227
+f 1184//229 1183//229 1181//228
+f 1186//230 1185//230 1183//229
+f 1188//231 1187//231 1185//230
+f 1190//232 1189//232 1187//231
+f 1192//233 1191//233 1189//232
+f 1194//234 1193//236 1191//233
+f 1196//235 1195//235 1193//236
+f 1198//237 1197//237 1195//235
+f 1200//238 1199//238 1197//237
+f 1202//239 1201//239 1199//238
+f 1204//240 1203//240 1201//239
+f 1206//241 1205//241 1203//240
+f 1208//242 1207//242 1205//241
+f 1210//243 1209//243 1207//242
+f 1212//244 1211//244 1209//243
+f 1214//245 1213//245 1211//244
+f 1216//246 1215//246 1213//245
+f 1218//247 1217//247 1215//246
+f 1220//248 1219//248 1217//247
+f 1222//249 1221//249 1219//248
+f 1224//250 1223//250 1221//249
+f 1226//251 1225//251 1223//250
+f 1228//252 1227//252 1225//251
+f 1230//253 1229//253 1227//252
+f 1232//254 1231//254 1229//253
+f 1234//255 1233//255 1231//254
+f 1236//256 1235//256 1233//255
+f 1238//257 1237//257 1235//256
+f 1240//258 1239//258 1237//257
+f 1242//259 1241//259 1239//258
+f 1244//260 1243//260 1241//259
+f 1246//261 1245//261 1243//260
+f 1248//262 1247//262 1245//261
+f 1250//263 1249//263 1247//262
+f 1252//264 1251//264 1249//263
+f 1254//265 1253//265 1251//264
+f 1256//266 1255//266 1253//265
+f 1258//267 1257//267 1255//266
+f 1260//268 1259//268 1257//267
+f 1262//269 1261//269 1259//268
+f 1264//270 1263//270 1261//269
+f 1266//271 1265//271 1263//270
+f 1268//272 1267//272 1265//271
+f 1270//273 1269//273 1267//272
+f 1272//274 1271//274 1269//273
+f 1274//275 1273//275 1271//274
+f 1276//276 1275//276 1273//275
+f 1278//277 1277//277 1275//276
+f 1280//278 1279//278 1277//277
+f 1282//279 1281//279 1279//278
+f 1284//3 1283//3 1281//279
+f 1286//280 1285//280 1283//3
+f 1288//281 1287//281 1285//280
+f 1290//282 1289//282 1287//281
+f 1292//283 1291//283 1289//282
+f 1294//284 1293//284 1291//283
+f 1296//285 1295//285 1293//284
+f 1298//286 1297//286 1295//285
+f 1300//287 1299//287 1297//286
+f 1302//288 1301//288 1299//287
+f 1304//289 1303//289 1301//288
+f 1306//290 1305//290 1303//289
+f 1308//291 1307//291 1305//290
+f 1118//198 1117//198 1307//291
diff --git a/examples/vulkan/vulkan.pro b/examples/vulkan/vulkan.pro
index ef5496bcd4..920762cb9e 100644
--- a/examples/vulkan/vulkan.pro
+++ b/examples/vulkan/vulkan.pro
@@ -4,4 +4,7 @@ SUBDIRS = hellovulkanwindow \
hellovulkantriangle \
hellovulkantexture
-qtHaveModule(widgets): SUBDIRS += hellovulkanwidget
+qtHaveModule(widgets) {
+ SUBDIRS += hellovulkanwidget
+ qtHaveModule(concurrent): SUBDIRS += hellovulkancubes
+}