KiCad PCB EDA Suite
Loading...
Searching...
No Matches
frustum_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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
31
32#include "3d_fastmath.h"
33#include "frustum_3d.h"
34#include <cmath>
35
36
37TRUNCATED_CONE::TRUNCATED_CONE( SFVEC2F aCenterPoint, float aZmin, float aZmax, float aRadiusMin,
38 float aRadiusMax )
39 : OBJECT_3D( OBJECT_3D_TYPE::CYLINDER ) // Reuse CYLINDER type for now
40{
41 m_center = aCenterPoint;
42 m_zMin = aZmin;
43 m_zMax = aZmax;
44 m_radiusMin = aRadiusMin;
45 m_radiusMax = aRadiusMax;
46 m_height = aZmax - aZmin;
47 m_slope = ( m_height > 0.0f ) ? ( aRadiusMax - aRadiusMin ) / m_height : 0.0f;
48
49 // Bounding box uses the larger radius
50 const float maxRadius = std::max( aRadiusMin, aRadiusMax );
51 m_bbox.Set( SFVEC3F( aCenterPoint.x - maxRadius, aCenterPoint.y - maxRadius, aZmin ),
52 SFVEC3F( aCenterPoint.x + maxRadius, aCenterPoint.y + maxRadius, aZmax ) );
53 m_bbox.ScaleNextUp();
54 m_centroid = m_bbox.GetCenter();
55}
56
57
58bool TRUNCATED_CONE::Intersect( const RAY& aRay, HITINFO& aHitInfo ) const
59{
60 // Ray-cone intersection for a vertical cone with apex on the Z axis.
61 // The cone surface is defined by: (x-cx)^2 + (y-cy)^2 = r(z)^2
62 // where r(z) = radiusMin + slope * (z - zMin)
63 //
64 // Substituting the ray equation P = O + t*D:
65 // (Ox + t*Dx - cx)^2 + (Oy + t*Dy - cy)^2 = (radiusMin + slope*(Oz + t*Dz - zMin))^2
66
67 const double OCx = aRay.m_Origin.x - m_center.x;
68 const double OCy = aRay.m_Origin.y - m_center.y;
69 const double OCz = aRay.m_Origin.z - m_zMin; // Z relative to cone base
70
71 const double Dx = aRay.m_Dir.x;
72 const double Dy = aRay.m_Dir.y;
73 const double Dz = aRay.m_Dir.z;
74
75 const double r0 = m_radiusMin;
76 const double k = m_slope; // dr/dz
77
78 // Expanding the equation gives us a quadratic: a*t^2 + 2*b*t + c = 0
79 // Note: we use 2*b to simplify the quadratic formula
80 const double a = Dx * Dx + Dy * Dy - k * k * Dz * Dz;
81 const double b = OCx * Dx + OCy * Dy - k * ( r0 + k * OCz ) * Dz;
82 const double c = OCx * OCx + OCy * OCy - ( r0 + k * OCz ) * ( r0 + k * OCz );
83
84 const double discriminant = b * b - a * c;
85
86 if( discriminant < 0.0 )
87 return false;
88
89 bool hitResult = false;
90 float tHit = aHitInfo.m_tHit;
91 SFVEC3F hitNormal;
92
93 const double sqrtDisc = std::sqrt( discriminant );
94
95 // Check both roots
96 for( int i = 0; i < 2; ++i )
97 {
98 double t;
99 if( std::abs( a ) < 1e-10 )
100 {
101 // Nearly linear case
102 if( std::abs( b ) < 1e-10 )
103 continue;
104 t = -c / ( 2.0 * b );
105 if( i == 1 )
106 continue; // Only one solution in linear case
107 }
108 else
109 {
110 t = ( -b + ( i == 0 ? -sqrtDisc : sqrtDisc ) ) / a;
111 }
112
113 if( t <= 0.0f || t >= tHit )
114 continue;
115
116 const float z = aRay.m_Origin.z + t * aRay.m_Dir.z;
117
118 if( z < m_zMin || z > m_zMax )
119 continue;
120
121 // Valid hit on cone surface
122 tHit = t;
123 hitResult = true;
124
125 const SFVEC3F hitPoint = aRay.at( t );
126 const float hitRadius = m_radiusMin + m_slope * ( z - m_zMin );
127
128 if( hitRadius > 1e-6f )
129 {
130 // Normal points outward from cone surface
131 // For a cone, the normal has both radial and vertical components
132 const float invR = 1.0f / hitRadius;
133 const float nx = -( hitPoint.x - m_center.x ) * invR;
134 const float ny = -( hitPoint.y - m_center.y ) * invR;
135 // The vertical component depends on the slope
136 const float nz = m_slope / std::sqrt( 1.0f + m_slope * m_slope );
137
138 hitNormal = glm::normalize( SFVEC3F( nx, ny, nz ) );
139 }
140 else
141 {
142 hitNormal = SFVEC3F( 0.0f, 0.0f, -1.0f );
143 }
144
145 break; // Take the first valid hit (closer one)
146 }
147
148 if( hitResult )
149 {
150 aHitInfo.m_tHit = tHit;
151 aHitInfo.m_HitPoint = aRay.at( tHit );
152 aHitInfo.m_HitNormal = hitNormal;
153
154 m_material->Generate( aHitInfo.m_HitNormal, aRay, aHitInfo );
155
156 aHitInfo.pHitObject = this;
157 }
158
159 return hitResult;
160}
161
162
163bool TRUNCATED_CONE::IntersectP( const RAY& aRay, float aMaxDistance ) const
164{
165 const double OCx = aRay.m_Origin.x - m_center.x;
166 const double OCy = aRay.m_Origin.y - m_center.y;
167 const double OCz = aRay.m_Origin.z - m_zMin;
168
169 const double Dx = aRay.m_Dir.x;
170 const double Dy = aRay.m_Dir.y;
171 const double Dz = aRay.m_Dir.z;
172
173 const double r0 = m_radiusMin;
174 const double k = m_slope;
175
176 const double a = Dx * Dx + Dy * Dy - k * k * Dz * Dz;
177 const double b = OCx * Dx + OCy * Dy - k * ( r0 + k * OCz ) * Dz;
178 const double c = OCx * OCx + OCy * OCy - ( r0 + k * OCz ) * ( r0 + k * OCz );
179
180 const double discriminant = b * b - a * c;
181
182 if( discriminant < 0.0 )
183 return false;
184
185 const double sqrtDisc = std::sqrt( discriminant );
186
187 for( int i = 0; i < 2; ++i )
188 {
189 double t;
190 if( std::abs( a ) < 1e-10 )
191 {
192 if( std::abs( b ) < 1e-10 )
193 continue;
194 t = -c / ( 2.0 * b );
195 if( i == 1 )
196 continue;
197 }
198 else
199 {
200 t = ( -b + ( i == 0 ? -sqrtDisc : sqrtDisc ) ) / a;
201 }
202
203 if( t <= 0.0f || t >= aMaxDistance )
204 continue;
205
206 const float z = aRay.m_Origin.z + t * aRay.m_Dir.z;
207
208 if( z >= m_zMin && z <= m_zMax )
209 return true;
210 }
211
212 return false;
213}
214
215
216bool TRUNCATED_CONE::Intersects( const BBOX_3D& aBBox ) const
217{
218 // Simple bounding box check
219 return m_bbox.Intersects( aBBox );
220}
221
222
223SFVEC3F TRUNCATED_CONE::GetDiffuseColor( const HITINFO& /* aHitInfo */ ) const
224{
225 return m_diffusecolor;
226}
Defines math related functions.
A vertical cylinder.
Definition cylinder_3d.h:38
BBOX_3D m_bbox
Definition object_3d.h:97
SFVEC3F m_centroid
Definition object_3d.h:98
OBJECT_3D(OBJECT_3D_TYPE aObjType)
Definition object_3d.cpp:40
const MATERIAL * m_material
Definition object_3d.h:100
bool Intersect(const RAY &aRay, HITINFO &aHitInfo) const override
bool IntersectP(const RAY &aRay, float aMaxDistance) const override
float m_radiusMax
Definition frustum_3d.h:61
SFVEC3F m_diffusecolor
Definition frustum_3d.h:66
SFVEC2F m_center
Definition frustum_3d.h:59
bool Intersects(const BBOX_3D &aBBox) const override
SFVEC3F GetDiffuseColor(const HITINFO &aHitInfo) const override
TRUNCATED_CONE(SFVEC2F aCenterPoint, float aZmin, float aZmax, float aRadiusMin, float aRadiusMax)
float m_radiusMin
Definition frustum_3d.h:60
A truncated cone for raytracing, used for countersink visualization.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:400
OBJECT_3D_TYPE
Definition object_3d.h:39
Manage a bounding box defined by two SFVEC3F min max points.
Definition bbox_3d.h:43
Stores the hit information of a ray with a point on the surface of a object.
Definition hitinfo.h:36
float m_tHit
( 4) distance
Definition hitinfo.h:38
const OBJECT_3D * pHitObject
( 4) Object that was hitted
Definition hitinfo.h:40
SFVEC3F m_HitNormal
(12) normal at the hit point
Definition hitinfo.h:37
SFVEC3F m_HitPoint
(12) hit position
Definition hitinfo.h:44
Definition ray.h:63
SFVEC3F m_Dir
Definition ray.h:67
SFVEC3F m_Origin
Definition ray.h:64
SFVEC3F at(float t) const
Definition ray.h:84
glm::vec2 SFVEC2F
Definition xv3d_types.h:42
glm::vec3 SFVEC3F
Definition xv3d_types.h:44