Revision control

Copy as Markdown

// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\example custommorphing
\ingroup quick3d-examples
\title Qt Quick 3D - Custom Morphing Animation
\examplecategory {3D}
\brief Demonstrates writing C++ custom geometry with a morph target.
\image custommorphing.png
{Orange wavy object demonstrating custom morphing animation}
This example shows how to define a complex custom geometry in C++ that contains a base shape and a
morph target, with normal vectors for both.
\section1 Custom geometry
The main part of this example is creating a custom geometry with a morph target. We do this by
subclassing QQuick3DGeometry:
\snippet custommorphing/morphgeometry.h class definition
The constructor defines the layout of the mesh data:
\snippet custommorphing/morphgeometry.cpp constructor
The function \c updateData performs the actual uploading of the mesh geometry:
\snippet custommorphing/morphgeometry.cpp updateData
We call \c updateData from the constructor, and when a property has changed.
The function \c calculateGeometry contains all the tedious mathematics to calculate the shapes
and normal vectors. It is specific to this example, and the code will not be explained in
detail. In general: to implement smooth shading, it's necessary to calculate the normal vector
for each vertex. Mathematically, the normal vector can be calculated from the partial
derivatives of the function describing the plane:
\image partialderivatives.png
{Formula to calculate normal vector}
In this example, we make it simple by using a cosine wave for the base
shape, knowing that its derivative is a sine function.
In practice, normal vectors can often be determined by geometric reasoning. For the morph
target, we use the fact that any vector from the center of a sphere to the surface will be
normal to the sphere at that point. Note that normal vectors in QtQuick3D must have unit length,
which can be done by using \l QVector3D::normalized().
\section1 QML part
We define a morph target that corresponds to the one we created in the custom geometry, and do
an animation on the weight, so it will cycle between the two shapes:
\snippet custommorphing/main.qml target
Finally, we create a model using our custom geometry, and apply the morph target to it:
\snippet custommorphing/main.qml model
*/