QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
PaperPlaneGeometry.cc
Go to the documentation of this file.
1/****************************************************************************
2 *
3 * (c) 2009-2024 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
4 *
5 * QGroundControl is licensed according to the terms in the file
6 * COPYING.md in the root of the source code directory.
7 *
8 ****************************************************************************/
9
10#include "PaperPlaneGeometry.h"
11
12#include <QtCore/QByteArray>
13#include <QtCore/QList>
14#include <QtCore/QtGlobal>
15#include <QtGui/QVector3D>
16#include <QtGui/QVector4D>
17
18#include <cmath>
19
20namespace {
21
22// Silhouette from vehicleArrowOpaque.svg (72x72 viewBox scaled to length 100):
23// nose top-center, wingtips at the rear corners, tail notch on the spine.
24// Wingtips raised and keel dropped for the folded-paper dihedral.
25constexpr QVector3D kNose(0.0f, 50.0f, 0.0f);
26constexpr QVector3D kTailNotch(0.0f, -25.0f, 0.0f);
27constexpr QVector3D kLeftTip(-36.0f, -50.0f, 14.0f);
28constexpr QVector3D kRightTip(36.0f, -50.0f, 14.0f);
29constexpr QVector3D kKeelBottom(0.0f, -48.0f, -16.0f);
30
31// Vertex colors multiply in linear space (linear tonemap re-encodes to sRGB)
32QVector4D linearColor(float r, float g, float b)
33{
34 const auto toLinear = [](float c) {
35 return (c <= 0.04045f) ? (c / 12.92f) : std::pow((c + 0.055f) / 1.055f, 2.4f);
36 };
37 return QVector4D(toLinear(r), toLinear(g), toLinear(b), 1.0f);
38}
39
40} // namespace
41
42PaperPlaneGeometry::PaperPlaneGeometry(QQuick3DObject* parent) : QQuick3DGeometry(parent)
43{
44 // Wing reds from vehicleArrowOpaque.svg; paper-white keel fin as the
45 // fuselage, visible in tilted 3D views
46 const QVector4D leftWingColor = linearColor(0xc7 / 255.0f, 0x2b / 255.0f, 0x27 / 255.0f);
47 const QVector4D rightWingColor = linearColor(0xee / 255.0f, 0x34 / 255.0f, 0x24 / 255.0f);
48 const QVector4D fuselageColor = linearColor(0xf5 / 255.0f, 0xf5 / 255.0f, 0xf5 / 255.0f);
49
50 struct Triangle
51 {
52 QVector3D a, b, c;
53 QVector4D color;
54 };
55
56 // CCW seen from the normal side: wings face up(ish), keel faces +x
57 const Triangle triangles[kTriangleCount] = {
58 {kNose, kLeftTip, kTailNotch, leftWingColor},
59 {kNose, kTailNotch, kRightTip, rightWingColor},
60 {kNose, kTailNotch, kKeelBottom, fuselageColor},
61 };
62
63 QList<float> floats;
64 floats.reserve(kTriangleCount * 3 * kFloatsPerVertex);
65 QVector3D minBounds = kNose;
66 QVector3D maxBounds = kNose;
67 for (const Triangle& triangle : triangles) {
68 const QVector3D normal = QVector3D::crossProduct(triangle.b - triangle.a, triangle.c - triangle.a).normalized();
69 for (const QVector3D& position : {triangle.a, triangle.b, triangle.c}) {
70 floats << position.x() << position.y() << position.z();
71 floats << normal.x() << normal.y() << normal.z();
72 floats << triangle.color.x() << triangle.color.y() << triangle.color.z() << triangle.color.w();
73 minBounds = QVector3D(qMin(minBounds.x(), position.x()), qMin(minBounds.y(), position.y()),
74 qMin(minBounds.z(), position.z()));
75 maxBounds = QVector3D(qMax(maxBounds.x(), position.x()), qMax(maxBounds.y(), position.y()),
76 qMax(maxBounds.z(), position.z()));
77 }
78 }
79
80 setStride(kFloatsPerVertex * sizeof(float));
81 setVertexData(QByteArray(reinterpret_cast<const char*>(floats.constData()),
82 static_cast<qsizetype>(floats.size() * sizeof(float))));
83 setPrimitiveType(QQuick3DGeometry::PrimitiveType::Triangles);
84 addAttribute(QQuick3DGeometry::Attribute::PositionSemantic, 0, QQuick3DGeometry::Attribute::F32Type);
85 addAttribute(QQuick3DGeometry::Attribute::NormalSemantic, 3 * sizeof(float), QQuick3DGeometry::Attribute::F32Type);
86 addAttribute(QQuick3DGeometry::Attribute::ColorSemantic, 6 * sizeof(float), QQuick3DGeometry::Attribute::F32Type);
87 setBounds(minBounds, maxBounds);
88}
static constexpr int kTriangleCount
static constexpr int kFloatsPerVertex
position 3, normal 3, color 4
PaperPlaneGeometry(QQuick3DObject *parent=nullptr)