1/****************************************************************************
2**
3** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt3D module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "triangleboundingvolume_p.h"
41#include <Qt3DRender/private/qray3d_p.h>
42
43QT_BEGIN_NAMESPACE
44
45namespace Qt3DRender {
46
47namespace Render {
48
49// Note: a, b, c in clockwise order
50// RealTime Collision Detection page 192
51bool intersectsSegmentTriangle(const RayCasting::QRay3D &ray,
52 const Vector3D &a,
53 const Vector3D &b,
54 const Vector3D &c,
55 Vector3D &uvw,
56 float &t)
57{
58 const Vector3D ab = b - a;
59 const Vector3D ac = c - a;
60 const Vector3D qp = (ray.origin() - ray.point(t: ray.distance()));
61
62 const Vector3D n = Vector3D::crossProduct(a: ab, b: ac);
63 const float d = Vector3D::dotProduct(a: qp, b: n);
64
65 if (d <= 0.0f)
66 return false;
67
68 const Vector3D ap = ray.origin() - a;
69 t = Vector3D::dotProduct(a: ap, b: n);
70
71 if (t < 0.0f || t > d)
72 return false;
73
74 const Vector3D e = Vector3D::crossProduct(a: qp, b: ap);
75 uvw.setY(Vector3D::dotProduct(a: ac, b: e));
76
77 if (uvw.y() < 0.0f || uvw.y() > d)
78 return false;
79
80 uvw.setZ(-Vector3D::dotProduct(a: ab, b: e));
81
82 if (uvw.z() < 0.0f || uvw.y() + uvw.z() > d)
83 return false;
84
85 const float ood = 1.0f / d;
86 t *= ood;
87 uvw.setY(uvw.y() * ood);
88 uvw.setZ(uvw.z() * ood);
89 uvw.setX(1.0f - uvw.y() - uvw.z());
90
91 return true;
92}
93
94TriangleBoundingVolume::TriangleBoundingVolume()
95 : QBoundingVolume()
96{
97}
98
99/*
100 The vertices a, b, c are assumed to be in counter clockwise order.
101 */
102TriangleBoundingVolume::TriangleBoundingVolume(Qt3DCore::QNodeId id, const Vector3D &a, const Vector3D &b, const Vector3D &c)
103 : QBoundingVolume()
104 , m_id(id)
105 , m_a(a)
106 , m_b(b)
107 , m_c(c)
108{}
109
110Qt3DCore::QNodeId TriangleBoundingVolume::id() const
111{
112 return m_id;
113}
114
115bool TriangleBoundingVolume::intersects(const RayCasting::QRay3D &ray, Vector3D *q, Vector3D *uvw) const
116{
117 float t = 0.0f;
118 Vector3D uvwr;
119 const float intersected = intersectsSegmentTriangle(ray, a: m_c, b: m_b, c: m_a, uvw&: uvwr, t);
120
121 if (intersected) {
122 if (q != nullptr)
123 *q = ray.point(t);
124 if (uvw != nullptr)
125 *uvw = uvwr;
126 }
127 return intersected;
128}
129
130TriangleBoundingVolume::Type TriangleBoundingVolume::type() const
131{
132 return RayCasting::QBoundingVolume::Triangle;
133}
134
135Vector3D TriangleBoundingVolume::a() const
136{
137 return m_a;
138}
139
140Vector3D TriangleBoundingVolume::b() const
141{
142 return m_b;
143}
144
145Vector3D TriangleBoundingVolume::c() const
146{
147 return m_c;
148}
149
150void TriangleBoundingVolume::setA(const Vector3D &a)
151{
152 m_a = a;
153}
154
155void TriangleBoundingVolume::setB(const Vector3D &b)
156{
157 m_b = b;
158}
159
160void TriangleBoundingVolume::setC(const Vector3D &c)
161{
162 m_c = c;
163}
164
165TriangleBoundingVolume TriangleBoundingVolume::transformed(const Matrix4x4 &mat) const
166{
167 const Vector3D tA = mat * m_a;
168 const Vector3D tB = mat * m_b;
169 const Vector3D tC = mat * m_c;
170 return TriangleBoundingVolume(id(), tA, tB, tC);
171}
172
173} // namespace Render
174
175} // namespace Qt3DRender
176
177QT_END_NAMESPACE
178

source code of qt3d/src/render/backend/triangleboundingvolume.cpp