21 #include <Qt3DRender/QCamera>
26 namespace QgsRayCastingUtils
34 : m_direction( 0.0f, 0.0f, 1.0f )
38 Ray3D::Ray3D( QVector3D origin, QVector3D direction,
float distance )
40 , m_direction( direction )
41 , m_distance( distance )
44 QVector3D Ray3D::origin()
const
49 void Ray3D::setOrigin( QVector3D value )
54 QVector3D Ray3D::direction()
const
59 void Ray3D::setDirection( QVector3D value )
67 float Ray3D::distance()
const
72 void Ray3D::setDistance(
float distance )
74 m_distance = distance;
77 QVector3D Ray3D::point(
float t )
const
79 return m_origin + t * m_direction;
82 Ray3D &Ray3D::transform(
const QMatrix4x4 &matrix )
84 m_origin = matrix * m_origin;
85 m_direction = matrix.mapVector( m_direction );
90 Ray3D Ray3D::transformed(
const QMatrix4x4 &matrix )
const
92 return Ray3D( matrix * m_origin, matrix.mapVector( m_direction ) );
97 return m_origin == other.origin() && m_direction == other.direction();
102 return !( *
this == other );
105 bool Ray3D::contains( QVector3D point )
const
107 const QVector3D ppVec( point - m_origin );
108 if ( ppVec.isNull() )
110 const float dot = QVector3D::dotProduct( ppVec, m_direction );
111 if ( qFuzzyIsNull( dot ) )
113 return qFuzzyCompare( dot * dot, ppVec.lengthSquared() * m_direction.lengthSquared() );
116 bool Ray3D::contains(
const Ray3D &ray )
const
118 const float dot = QVector3D::dotProduct( m_direction, ray.direction() );
119 if ( !qFuzzyCompare( dot * dot, m_direction.lengthSquared() * ray.direction().lengthSquared() ) )
121 return contains( ray.origin() );
124 float Ray3D::projectedDistance( QVector3D point )
const
126 Q_ASSERT( !m_direction.isNull() );
128 return QVector3D::dotProduct( point - m_origin, m_direction ) /
129 m_direction.lengthSquared();
132 QVector3D Ray3D::project( QVector3D vector )
const
134 const QVector3D norm = m_direction.normalized();
135 return QVector3D::dotProduct( vector, norm ) * norm;
139 float Ray3D::distance( QVector3D point )
const
141 const float t = projectedDistance( point );
142 return ( point - ( m_origin + t * m_direction ) ).length();
145 QDebug
operator<<( QDebug dbg,
const Ray3D &ray )
147 const QDebugStateSaver saver( dbg );
148 dbg.nospace() <<
"QRay3D(origin("
149 << ray.origin().x() <<
", " << ray.origin().y() <<
", "
150 << ray.origin().z() <<
") - direction("
151 << ray.direction().x() <<
", " << ray.direction().y() <<
", "
152 << ray.direction().z() <<
"))";
175 ray(
double xO,
double yO,
double zO,
double xD,
double yD,
double zD )
177 origin[0] = xO; origin[1] = yO; origin[2] = zO;
178 dir[0] = xD; dir[1] = yD; dir[2] = zD;
179 dir_inv[0] = 1 / dir[0]; dir_inv[1] = 1 / dir[1]; dir_inv[2] = 1 / dir[2];
181 ray(
const QgsRayCastingUtils::Ray3D &r )
184 origin[0] = r.origin().x(); origin[1] = r.origin().y(); origin[2] = r.origin().z();
185 dir[0] = r.direction().x(); dir[1] = r.direction().y(); dir[2] = r.direction().z();
186 dir_inv[0] = 1 / dir[0]; dir_inv[1] = 1 / dir[1]; dir_inv[2] = 1 / dir[2];
196 bool intersection(
const box &b,
const ray &r )
198 double t1 = ( b.min[0] - r.origin[0] ) * r.dir_inv[0];
199 double t2 = ( b.max[0] - r.origin[0] ) * r.dir_inv[0];
201 double tmin = std::min( t1, t2 );
202 double tmax = std::max( t1, t2 );
204 for (
int i = 1; i < 3; ++i )
206 t1 = ( b.min[i] - r.origin[i] ) * r.dir_inv[i];
207 t2 = ( b.max[i] - r.origin[i] ) * r.dir_inv[i];
209 tmin = std::max( tmin, std::min( std::min( t1, t2 ), tmax ) );
210 tmax = std::min( tmax, std::max( std::max( t1, t2 ), tmin ) );
213 return tmax > std::max( tmin, 0.0 );
217 namespace QgsRayCastingUtils
220 bool rayBoxIntersection(
const Ray3D &r,
const QgsAABB &aabb )
225 if ( b.min[0] == b.max[0] ) b.max[0] += 0.1;
226 if ( b.min[1] == b.max[1] ) b.max[1] += 0.1;
227 if ( b.min[2] == b.max[2] ) b.max[2] += 0.1;
229 return intersection( b, ray( r ) );
234 bool rayTriangleIntersection(
const Ray3D &ray,
244 const QVector3D ab = b - a;
245 const QVector3D ac =
c - a;
246 const QVector3D qp = ( ray.origin() - ray.point( ray.distance() ) );
248 const QVector3D n = QVector3D::crossProduct( ab, ac );
249 const float d = QVector3D::dotProduct( qp, n );
254 const QVector3D ap = ray.origin() - a;
255 t = QVector3D::dotProduct( ap, n );
257 if ( t < 0.0f || t > d )
260 const QVector3D e = QVector3D::crossProduct( qp, ap );
261 uvw.setY( QVector3D::dotProduct( ac, e ) );
263 if ( uvw.y() < 0.0f || uvw.y() > d )
266 uvw.setZ( -QVector3D::dotProduct( ab, e ) );
268 if ( uvw.z() < 0.0f || uvw.y() + uvw.z() > d )
271 const float ood = 1.0f / d;
273 uvw.setY( uvw.y() * ood );
274 uvw.setZ( uvw.z() * ood );
275 uvw.setX( 1.0f - uvw.y() - uvw.z() );