KiCad PCB EDA Suite
Loading...
Searching...
No Matches
triangle_3d.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2015-2016 Mario Luzeiro <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21
25
26
27#include "triangle_3d.h"
28
29
31{
32 const SFVEC3F& A = m_vertex[0];
33 const SFVEC3F& B = m_vertex[1];
34 const SFVEC3F& C = m_vertex[2];
35 const SFVEC3F c = B - A;
36 const SFVEC3F b = C - A;
37
38 m_bbox.Reset();
39 m_bbox.Set( A );
40 m_bbox.Union( B );
41 m_bbox.Union( C );
42 m_bbox.ScaleNextUp();
43 m_centroid = m_bbox.GetCenter();
44
45 m_n = glm::cross( b, c );
46
47 if( glm::abs( m_n.x ) > glm::abs( m_n.y ) )
48 {
49 if( glm::abs( m_n.x ) > glm::abs( m_n.z ) )
50 m_k = 0;
51 else
52 m_k = 2;
53 }
54 else
55 {
56 if( glm::abs( m_n.y ) > glm::abs( m_n.z ) )
57 m_k = 1;
58 else
59 m_k = 2;
60 }
61
62 int u = ( m_k + 1 ) % 3;
63 int v = ( m_k + 2 ) % 3;
64
65 // precomp
66 float krec = 1.0f / m_n[m_k];
67
68 m_nu = m_n[u] * krec;
69 m_nv = m_n[v] * krec;
70 m_nd = glm::dot( m_n, A ) * krec;
71
72 // first line equation
73 float reci = 1.0f / ( b[u] * c[v] - b[v] * c[u] );
74
75 m_bnu = b[u] * reci;
76 m_bnv = -b[v] * reci;
77
78 // second line equation
79 m_cnu = c[v] * reci;
80 m_cnv = -c[u] * reci;
81
82 // finalize normal
83 m_n = glm::normalize( m_n );
84
85 m_normal[0] = m_n;
86 m_normal[1] = m_n;
87 m_normal[2] = m_n;
88}
89
90
91TRIANGLE::TRIANGLE( const SFVEC3F& aV1, const SFVEC3F& aV2, const SFVEC3F& aV3 )
93{
94 m_vertex[0] = aV1;
95 m_vertex[1] = aV2;
96 m_vertex[2] = aV3;
97
98 m_vertexColorRGBA[0] = 0xFFFFFFFF;
99 m_vertexColorRGBA[1] = 0xFFFFFFFF;
100 m_vertexColorRGBA[2] = 0xFFFFFFFF;
101
103}
104
105
106TRIANGLE::TRIANGLE( const SFVEC3F& aV1, const SFVEC3F& aV2, const SFVEC3F& aV3,
107 const SFVEC3F& aFaceNormal )
109{
110 m_vertex[0] = aV1;
111 m_vertex[1] = aV2;
112 m_vertex[2] = aV3;
113
114 m_vertexColorRGBA[0] = 0xFFFFFFFF;
115 m_vertexColorRGBA[1] = 0xFFFFFFFF;
116 m_vertexColorRGBA[2] = 0xFFFFFFFF;
117
119
120 m_normal[0] = aFaceNormal;
121 m_normal[1] = aFaceNormal;
122 m_normal[2] = aFaceNormal;
123}
124
125
126TRIANGLE::TRIANGLE( const SFVEC3F& aV1, const SFVEC3F& aV2, const SFVEC3F& aV3,
127 const SFVEC3F& aN1, const SFVEC3F& aN2, const SFVEC3F& aN3 )
129{
130 m_vertex[0] = aV1;
131 m_vertex[1] = aV2;
132 m_vertex[2] = aV3;
133
134 m_vertexColorRGBA[0] = 0xFFFFFFFF;
135 m_vertexColorRGBA[1] = 0xFFFFFFFF;
136 m_vertexColorRGBA[2] = 0xFFFFFFFF;
137
139
140 m_normal[0] = aN1;
141 m_normal[1] = aN2;
142 m_normal[2] = aN3;
143}
144
145
146void TRIANGLE::SetColor( const SFVEC3F& aColor )
147{
148 m_vertexColorRGBA[0] = ( (unsigned int) ( aColor.r * 255 ) << 24 )
149 | ( (unsigned int) ( aColor.g * 255 ) << 16 )
150 | ( (unsigned int) ( aColor.b * 255 ) << 8 ) | 0xFF;
153}
154
155
156void TRIANGLE::SetColor( const SFVEC3F& aVC0, const SFVEC3F& aVC1, const SFVEC3F& aVC2 )
157{
158 m_vertexColorRGBA[0] = ( (unsigned int) ( aVC0.r * 255 ) << 24 )
159 | ( (unsigned int) ( aVC0.g * 255 ) << 16 )
160 | ( (unsigned int) ( aVC0.b * 255 ) << 8 ) | 0xFF;
161 m_vertexColorRGBA[1] = ( (unsigned int) ( aVC1.r * 255 ) << 24 )
162 | ( (unsigned int) ( aVC1.g * 255 ) << 16 )
163 | ( (unsigned int) ( aVC1.b * 255 ) << 8 ) | 0xFF;
164 m_vertexColorRGBA[2] = ( (unsigned int) ( aVC2.r * 255 ) << 24 )
165 | ( (unsigned int) ( aVC2.g * 255 ) << 16 )
166 | ( (unsigned int) ( aVC2.b * 255 ) << 8 ) | 0xFF;
167}
168
169
170void TRIANGLE::SetColor( unsigned int aFaceColorRGBA )
171{
172 m_vertexColorRGBA[0] = aFaceColorRGBA;
173 m_vertexColorRGBA[1] = aFaceColorRGBA;
174 m_vertexColorRGBA[2] = aFaceColorRGBA;
175}
176
177
178void TRIANGLE::SetColor( unsigned int aVertex1ColorRGBA, unsigned int aVertex2ColorRGBA,
179 unsigned int aVertex3ColorRGBA )
180{
181 m_vertexColorRGBA[0] = aVertex1ColorRGBA;
182 m_vertexColorRGBA[1] = aVertex2ColorRGBA;
183 m_vertexColorRGBA[2] = aVertex3ColorRGBA;
184}
185
186
187void TRIANGLE::SetUV( const SFVEC2F& aUV1, const SFVEC2F& aUV2, const SFVEC2F& aUV3 )
188{
189 m_uv[0] = aUV1;
190 m_uv[1] = aUV2;
191 m_uv[2] = aUV3;
192}
193
194
195static const unsigned int s_modulo[] = { 0, 1, 2, 0, 1 };
196
197
198bool TRIANGLE::Intersect( const RAY& aRay, HITINFO& aHitInfo ) const
199{
201#define ku s_modulo[m_k + 1]
202#define kv s_modulo[m_k + 2]
203
204 const SFVEC3F& O = aRay.m_Origin;
205 const SFVEC3F& D = aRay.m_Dir;
206 const SFVEC3F& A = m_vertex[0];
207
208 const float lnd = 1.0f / ( D[m_k] + m_nu * D[ku] + m_nv * D[kv] );
209 const float t = ( m_nd - O[m_k] - m_nu * O[ku] - m_nv * O[kv] ) * lnd;
210
211 if( !( ( aHitInfo.m_tHit > t ) && ( t > 0.0f ) ) )
212 return false;
213
214 const float hu = O[ku] + t * D[ku] - A[ku];
215 const float hv = O[kv] + t * D[kv] - A[kv];
216 const float beta = hv * m_bnu + hu * m_bnv;
217
218 if( beta < 0.0f )
219 return false;
220
221 const float gamma = hu * m_cnu + hv * m_cnv;
222
223 if( gamma < 0 )
224 return false;
225
226 const float v = gamma;
227 const float u = beta;
228
229 if( ( u + v ) > 1.0f )
230 return false;
231
232 if( glm::dot( D, m_n ) > 0.0f )
233 return false;
234
235 aHitInfo.m_tHit = t;
236 aHitInfo.m_HitPoint = aRay.at( t );
237
238 // interpolate vertex normals with UVW using Gouraud's shading
239 aHitInfo.m_HitNormal =
240 glm::normalize( ( 1.0f - u - v ) * m_normal[0] + u * m_normal[1] + v * m_normal[2] );
241
242 m_material->Generate( aHitInfo.m_HitNormal, aRay, aHitInfo );
243
244 aHitInfo.pHitObject = this;
245
246 return true;
247#undef ku
248#undef kv
249}
250
251
252bool TRIANGLE::IntersectP( const RAY& aRay, float aMaxDistance ) const
253{
255#define ku s_modulo[m_k + 1]
256#define kv s_modulo[m_k + 2]
257
258 const SFVEC3F O = aRay.m_Origin;
259 const SFVEC3F D = aRay.m_Dir;
260 const SFVEC3F A = m_vertex[0];
261
262 const float lnd = 1.0f / ( D[m_k] + m_nu * D[ku] + m_nv * D[kv] );
263 const float t = ( m_nd - O[m_k] - m_nu * O[ku] - m_nv * O[kv] ) * lnd;
264
265 if( !( ( aMaxDistance > t ) && ( t > 0.0f ) ) )
266 return false;
267
268 const float hu = O[ku] + t * D[ku] - A[ku];
269 const float hv = O[kv] + t * D[kv] - A[kv];
270 const float beta = hv * m_bnu + hu * m_bnv;
271
272 if( beta < 0.0f )
273 return false;
274
275 const float gamma = hu * m_cnu + hv * m_cnv;
276
277 if( gamma < 0.0f )
278 return false;
279
280 const float v = gamma;
281 const float u = beta;
282
283 if( ( u + v ) > 1.0f )
284 return false;
285
286 if( glm::dot( D, m_n ) > 0.0f )
287 return false;
288
289 return true;
290#undef ku
291#undef kv
292}
293
294
295bool TRIANGLE::Intersects( const BBOX_3D& aBBox ) const
296{
298 return m_bbox.Intersects( aBBox );
299}
300
301
303{
304 const unsigned int rgbC1 = m_vertexColorRGBA[0];
305 const unsigned int rgbC2 = m_vertexColorRGBA[1];
306 const unsigned int rgbC3 = m_vertexColorRGBA[2];
307
308 const SFVEC3F c1 = SFVEC3F( (float) ( ( rgbC1 >> 24 ) & 0xFF ) / 255.0f,
309 (float) ( ( rgbC1 >> 16 ) & 0xFF ) / 255.0f,
310 (float) ( ( rgbC1 >> 8 ) & 0xFF ) / 255.0f );
311 const SFVEC3F c2 = SFVEC3F( (float) ( ( rgbC2 >> 24 ) & 0xFF ) / 255.0f,
312 (float) ( ( rgbC2 >> 16 ) & 0xFF ) / 255.0f,
313 (float) ( ( rgbC2 >> 8 ) & 0xFF ) / 255.0f );
314 const SFVEC3F c3 = SFVEC3F( (float) ( ( rgbC3 >> 24 ) & 0xFF ) / 255.0f,
315 (float) ( ( rgbC3 >> 16 ) & 0xFF ) / 255.0f,
316 (float) ( ( rgbC3 >> 8 ) & 0xFF ) / 255.0f );
317
318 const float u = aHitInfo.m_UV.x;
319 const float v = aHitInfo.m_UV.y;
320 const float w = 1.0f - u - v;
321
322 return w * c1 + u * c2 + v * c3;
323}
BBOX_3D m_bbox
Definition object_3d.h:93
SFVEC3F m_centroid
Definition object_3d.h:94
OBJECT_3D(OBJECT_3D_TYPE aObjType)
Definition object_3d.cpp:36
const MATERIAL * m_material
Definition object_3d.h:96
void SetUV(const SFVEC2F &aUV1, const SFVEC2F &aUV2, const SFVEC2F &aUV3)
float m_cnv
Definition triangle_3d.h:76
float m_nu
Definition triangle_3d.h:73
float m_cnu
Definition triangle_3d.h:76
SFVEC2F m_uv[3]
Definition triangle_3d.h:71
float m_bnv
Definition triangle_3d.h:75
float m_nd
Definition triangle_3d.h:73
TRIANGLE(const SFVEC3F &aV1, const SFVEC3F &aV2, const SFVEC3F &aV3)
float m_nv
Definition triangle_3d.h:73
SFVEC3F GetDiffuseColor(const HITINFO &aHitInfo) const override
bool IntersectP(const RAY &aRay, float aMaxDistance) const override
bool Intersects(const BBOX_3D &aBBox) const override
SFVEC3F m_normal[3]
Definition triangle_3d.h:68
unsigned int m_vertexColorRGBA[3]
Definition triangle_3d.h:72
void SetColor(const SFVEC3F &aColor)
SFVEC3F m_vertex[3]
Definition triangle_3d.h:69
SFVEC3F m_n
Definition triangle_3d.h:70
bool Intersect(const RAY &aRay, HITINFO &aHitInfo) const override
void pre_calc_const()
float m_bnu
Definition triangle_3d.h:75
unsigned int m_k
Definition triangle_3d.h:74
OBJECT_3D_TYPE
Definition object_3d.h:35
#define D(x)
Definition ptree.cpp:37
Manage a bounding box defined by two SFVEC3F min max points.
Definition bbox_3d.h:39
Stores the hit information of a ray with a point on the surface of a object.
Definition hitinfo.h:32
float m_tHit
( 4) distance
Definition hitinfo.h:34
const OBJECT_3D * pHitObject
( 4) Object that was hitted
Definition hitinfo.h:36
SFVEC2F m_UV
( 8) 2-D texture coordinates
Definition hitinfo.h:37
SFVEC3F m_HitNormal
(12) normal at the hit point
Definition hitinfo.h:33
SFVEC3F m_HitPoint
(12) hit position
Definition hitinfo.h:40
Definition ray.h:59
SFVEC3F m_Dir
Definition ray.h:63
SFVEC3F m_Origin
Definition ray.h:60
SFVEC3F at(float t) const
Definition ray.h:80
static const unsigned int s_modulo[]
#define ku
#define kv
Implement a triangle ray intersection based on article http://www.flipcode.com/archives/Raytracing_To...
glm::vec2 SFVEC2F
Definition xv3d_types.h:38
glm::vec3 SFVEC3F
Definition xv3d_types.h:40