3#include <Core/Geometry/TriangleMesh.hpp>
4#include <Core/RaCore.hpp>
20inline RA_CORE_API Scalar pointToLineSq(
const Vector3& q,
const Vector3& a,
const Vector3& dir );
24inline RA_CORE_API Scalar projectOnSegment(
const Vector3& q,
const Vector3& a,
const Vector3& ab );
28inline RA_CORE_API Scalar pointToSegmentSq(
const Vector3& q,
const Vector3& a,
const Vector3& ab );
37 enum Flags { HIT_FACE = 0, HIT_VERTEX = 1, HIT_EDGE = 2 };
40 meshPoint( { 0, 0, 0 } ),
72 Vector3 closestPoint[2];
77 Vector3 lineDirection,
78 const Vector3& segCenter,
80 const Scalar segExtent );
91 Scalar triangleParameter[3];
92 Vector3 closestPoint[2];
97 Vector3 lineDirection,
108 Scalar segmentParameter;
109 Scalar triangleParameter[3];
110 Vector3 closestPoint[2];
115 Vector3 segDirection,
116 const Scalar segExtent,
117 const Vector3 v[3] );
126 Scalar triangleParameter1[3];
127 Scalar triangleParameter2[3];
128 Vector3 closestPoint[2];
133 const Vector3 v2[3] );
137inline RA_CORE_API Scalar pointToLineSq(
const Vector3& q,
const Vector3& a,
const Vector3& dir ) {
139 return ( dir.cross( q - a ) ).squaredNorm() / dir.squaredNorm();
142inline RA_CORE_API Scalar projectOnSegment(
const Vector3& q,
144 const Vector3& ab ) {
146 if ( UNLIKELY( ab.squaredNorm() == 0 ) ) {
return 0; }
147 return std::clamp( ( q - a ).dot( ab ) / ( ab.squaredNorm() ), Scalar( 0 ), Scalar( 1 ) );
150inline RA_CORE_API Scalar pointToSegmentSq(
const Vector3& q,
152 const Vector3& ab ) {
153 const Scalar t = projectOnSegment( q, a, ab );
154 return ( q - ( a + t * ( ab ) ) ).squaredNorm();
159 HIT_FACE = PointToTriangleOutput::HIT_FACE,
161 HIT_A = 0x0 | PointToTriangleOutput::HIT_VERTEX,
162 HIT_B = 0x4 | PointToTriangleOutput::HIT_VERTEX,
163 HIT_C = 0x8 | PointToTriangleOutput::HIT_VERTEX,
165 HIT_AB = 0x0 | PointToTriangleOutput::HIT_EDGE,
166 HIT_BC = 0x4 | PointToTriangleOutput::HIT_EDGE,
167 HIT_CA = 0x8 | PointToTriangleOutput::HIT_EDGE,
170inline RA_CORE_API PointToTriangleOutput pointToTriSq(
const Vector3& q,
196 PointToTriangleOutput output;
198 const Vector3 ab = b - a;
199 const Vector3 ac = c - a;
200 const Vector3 aq = q - a;
202 CORE_ASSERT( ab.cross( ac ).squaredNorm() > 0,
"Triangle ABC is degenerate" );
204 const Scalar d1 = ab.dot( aq );
205 const Scalar d2 = ac.dot( aq );
208 const bool m1 = d1 <= 0 && d2 <= 0;
210 output.meshPoint = a;
211 output.distanceSquared = aq.squaredNorm();
212 output.flags = FlagsInternal::HIT_A;
216 const Vector3 bq = q - b;
217 const Scalar d3 = ab.dot( bq );
218 const Scalar d4 = ac.dot( bq );
221 const bool m2 = d3 >= 0 && d4 <= d3;
223 output.meshPoint = b;
224 output.distanceSquared = bq.squaredNorm();
225 output.flags = FlagsInternal::HIT_B;
229 const Vector3 cq = q - c;
230 const Scalar d5 = ab.dot( cq );
231 const Scalar d6 = ac.dot( cq );
234 const bool m3 = ( d6 >= 0 && d5 <= d6 );
236 output.meshPoint = c;
237 output.distanceSquared = cq.squaredNorm();
238 output.flags = FlagsInternal::HIT_C;
242 const Scalar vc = d1 * d4 - d3 * d2;
243 const Scalar v1 = d1 / ( d1 - d3 );
246 const bool m4 = vc <= 0 && d1 >= 0 && d3 <= 0;
248 output.meshPoint = a + v1 * ab;
249 output.distanceSquared = ( output.meshPoint - q ).squaredNorm();
250 output.flags = FlagsInternal::HIT_AB;
254 const Scalar vb = d5 * d2 - d1 * d6;
255 const Scalar w1 = d2 / ( d2 - d6 );
258 const bool m5 = vb <= 0 && d2 >= 0 && d6 <= 0;
260 output.meshPoint = a + w1 * ac;
261 output.distanceSquared = ( output.meshPoint - q ).squaredNorm();
262 output.flags = FlagsInternal::HIT_CA;
266 const Scalar va = d3 * d6 - d5 * d4;
267 const Scalar w2 = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) );
270 const bool m6 = va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0;
272 output.meshPoint = b + w2 * ( c - b );
273 output.distanceSquared = ( output.meshPoint - q ).squaredNorm();
274 output.flags = FlagsInternal::HIT_BC;
279 const Scalar d = Scalar( 1 ) / ( va + vb + vc );
280 const Scalar v2 = vb * d;
281 const Scalar w3 = vc * d;
283 output.meshPoint = a + v2 * ab + w3 * ac;
284 output.distanceSquared = ( output.meshPoint - q ).squaredNorm();
289inline RA_CORE_API LineToSegmentOutput lineToSegSq(
const Vector3& lineOrigin,
290 Vector3 lineDirection,
291 const Vector3& segCenter,
292 Vector3 segDirection,
293 const Scalar segExtent ) {
297 LineToSegmentOutput output;
299 segDirection.normalize();
300 lineDirection.normalize();
302 Vector3 diff = lineOrigin - segCenter;
303 Scalar a01 = -lineDirection.dot( segDirection );
304 Scalar b0 = diff.dot( lineDirection );
307 if ( std::abs( a01 ) < (Scalar)1 ) {
309 Scalar det = (Scalar)1 - a01 * a01;
310 Scalar extDet = segExtent * det;
311 Scalar b1 = -diff.dot( segDirection );
314 if ( s1 >= -extDet ) {
315 if ( s1 <= extDet ) {
317 s0 = ( a01 * b1 - b0 ) / det;
323 s0 = -( a01 * s1 + b0 );
329 s0 = -( a01 * s1 + b0 );
339 output.parameter[0] = s0;
340 output.parameter[1] = s1;
341 output.closestPoint[0] = lineOrigin + s0 * lineDirection;
342 output.closestPoint[1] = segCenter + s1 * segDirection;
343 diff = output.closestPoint[0] - output.closestPoint[1];
344 output.sqrDistance = diff.dot( diff );
345 output.distance =
std::sqrt( output.sqrDistance );
349inline RA_CORE_API LineToTriangleOutput lineToTriSq(
const Vector3& lineOrigin,
350 Vector3 lineDirection,
351 const Vector3 v[3] ) {
355 LineToTriangleOutput output;
357 lineDirection.normalize();
359 Vector3 edge0 = v[1] - v[0];
360 Vector3 edge1 = v[2] - v[0];
361 Vector3 normal = edge0.cross( edge1 );
363 Scalar nd = normal.dot( lineDirection );
364 if ( std::abs( nd ) > (Scalar)0 ) {
368 Vector3 diff = lineOrigin - v[0];
370 basis[0] = lineDirection;
371 if ( std::abs( basis[0][0] ) > std::abs( basis[0][1] ) ) {
372 basis[1] = { -basis[0][2], (Scalar)0, basis[0][0] };
374 else { basis[1] = { (Scalar)0, basis[0][2], -basis[0][1] }; }
375 basis[2] = basis[0].cross( basis[1] );
378 basis[0] /=
std::sqrt( basis[0].dot( basis[0] ) );
379 basis[1] -= basis[0] * ( basis[1].dot( basis[0] ) );
381 basis[1] /=
std::sqrt( basis[1].dot( basis[1] ) );
382 basis[2] -= basis[0] * ( basis[2].dot( basis[0] ) );
383 basis[2] -= basis[1] * ( basis[2].dot( basis[1] ) );
385 basis[2] /=
std::sqrt( basis[2].dot( basis[2] ) );
387 Scalar UdE0 = basis[1].dot( edge0 );
388 Scalar UdE1 = basis[1].dot( edge1 );
389 Scalar UdDiff = basis[1].dot( diff );
390 Scalar VdE0 = basis[2].dot( edge0 );
391 Scalar VdE1 = basis[2].dot( edge1 );
392 Scalar VdDiff = basis[2].dot( diff );
393 Scalar invDet = (Scalar)1 / ( UdE0 * VdE1 - UdE1 * VdE0 );
396 Scalar b1 = ( VdE1 * UdDiff - UdE1 * VdDiff ) * invDet;
397 Scalar b2 = ( UdE0 * VdDiff - VdE0 * UdDiff ) * invDet;
398 Scalar b0 = (Scalar)1 - b1 - b2;
400 if ( b0 >= (Scalar)0 && b1 >= (Scalar)0 && b2 >= (Scalar)0 ) {
403 Scalar DdE0 = lineDirection.dot( edge0 );
404 Scalar DdE1 = lineDirection.dot( edge1 );
405 Scalar DdDiff = lineDirection.dot( diff );
406 output.lineParameter = b1 * DdE0 + b2 * DdE1 - DdDiff;
409 output.triangleParameter[0] = b0;
410 output.triangleParameter[1] = b1;
411 output.triangleParameter[2] = b2;
414 output.closestPoint[0] = lineOrigin + output.lineParameter * lineDirection;
415 output.closestPoint[1] = v[0] + b1 * edge0 + b2 * edge1;
417 output.distance = (Scalar)0;
418 output.sqrDistance = (Scalar)0;
428 for (
int i0 = 2, i1 = 0; i1 < 3; i0 = i1++ ) {
429 Vector3 segCenter = ( (Scalar)0.5 ) * ( v[i0] + v[i1] );
430 Vector3 segDirection = v[i1] - v[i0];
431 Scalar segExtent = ( (Scalar)0.5 ) *
std::sqrt( segDirection.dot( segDirection ) );
434 LineToSegmentOutput lsOutput =
435 lineToSegSq( lineOrigin, lineDirection, segCenter, segDirection, segExtent );
436 if ( lsOutput.sqrDistance < output.sqrDistance ) {
437 output.sqrDistance = lsOutput.sqrDistance;
438 output.distance = lsOutput.distance;
439 output.lineParameter = lsOutput.parameter[0];
440 output.triangleParameter[i0] =
441 ( (Scalar)0.5 ) * ( (Scalar)1 - lsOutput.parameter[0] / segExtent );
442 output.triangleParameter[i1] = (Scalar)1 - output.triangleParameter[i0];
443 output.triangleParameter[3 - i0 - i1] = (Scalar)0;
444 output.closestPoint[0] = lsOutput.closestPoint[0];
445 output.closestPoint[1] = lsOutput.closestPoint[1];
451inline RA_CORE_API SegmentToTriangleOutput segmentToTriSq(
const Vector3& segCenter,
452 Vector3 segDirection,
454 const Vector3 v[3] ) {
458 SegmentToTriangleOutput output;
460 segDirection.normalize();
463 LineToTriangleOutput ltOutput = lineToTriSq( segCenter, segDirection, v );
465 if ( ltOutput.lineParameter >= -segExtent ) {
467 if ( ltOutput.lineParameter <= segExtent ) {
470 output.distance = ltOutput.distance;
471 output.sqrDistance = ltOutput.sqrDistance;
472 output.segmentParameter = ltOutput.lineParameter;
473 output.triangleParameter[0] = ltOutput.triangleParameter[0];
474 output.triangleParameter[1] = ltOutput.triangleParameter[1];
475 output.triangleParameter[2] = ltOutput.triangleParameter[2];
476 output.closestPoint[0] = ltOutput.closestPoint[0];
477 output.closestPoint[1] = ltOutput.closestPoint[1];
482 Vector3 point = segCenter + segExtent * segDirection;
483 PointToTriangleOutput ptOutput = pointToTriSq( point, v[0], v[1], v[2] );
484 output.sqrDistance = ptOutput.distanceSquared;
485 output.distance =
std::sqrt( output.sqrDistance );
486 output.segmentParameter = segExtent;
487 output.closestPoint[0] = point;
488 output.closestPoint[1] = ptOutput.meshPoint;
494 Vector3 point = segCenter - segExtent * segDirection;
495 PointToTriangleOutput ptOutput = pointToTriSq( point, v[0], v[1], v[2] );
496 output.sqrDistance = ptOutput.distanceSquared;
497 output.distance =
std::sqrt( output.sqrDistance );
498 output.segmentParameter = segExtent;
499 output.closestPoint[0] = point;
500 output.closestPoint[1] = ptOutput.meshPoint;
505inline RA_CORE_API TriangleToTriangleOutput triangleToTriSq(
const Vector3 v1[3],
506 const Vector3 v2[3] ) {
507 TriangleToTriangleOutput output;
509 SegmentToTriangleOutput stOutput;
513 for (
int i0 = 2, i1 = 0; i1 < 3; i0 = i1++ ) {
514 Vector3 segCenter = ( (Scalar)0.5 ) * ( v1[i0] + v1[i1] );
515 Vector3 segDirection = v1[i1] - v1[i0];
516 Scalar segExtent = ( (Scalar)0.5 ) *
std::sqrt( segDirection.dot( segDirection ) );
518 stOutput = segmentToTriSq( segCenter, segDirection, segExtent, v2 );
519 if ( stOutput.sqrDistance < output.sqrDistance ) {
520 output.sqrDistance = stOutput.sqrDistance;
521 output.distance = stOutput.distance;
522 output.triangleParameter1[i0] =
523 ( (Scalar)0.5 ) * ( (Scalar)1 - stOutput.segmentParameter / segExtent );
524 output.triangleParameter1[i1] = (Scalar)1 - output.triangleParameter1[i0];
525 output.triangleParameter1[3 - i0 - i1] = (Scalar)0;
526 output.triangleParameter2[0] = stOutput.triangleParameter[0];
527 output.triangleParameter2[1] = stOutput.triangleParameter[1];
528 output.triangleParameter2[2] = stOutput.triangleParameter[2];
529 output.closestPoint[0] = stOutput.closestPoint[0];
530 output.closestPoint[1] = stOutput.closestPoint[1];
535 for (
int i0 = 2, i1 = 0; i1 < 3; i0 = i1++ ) {
536 Vector3 segCenter = ( (Scalar)0.5 ) * ( v2[i0] + v2[i1] );
537 Vector3 segDirection = v2[i1] - v2[i0];
538 Scalar segExtent = ( (Scalar)0.5 ) *
std::sqrt( segDirection.dot( segDirection ) );
540 stOutput = segmentToTriSq( segCenter, segDirection, segExtent, v1 );
541 if ( stOutput.sqrDistance < output.sqrDistance ) {
542 output.sqrDistance = stOutput.sqrDistance;
543 output.distance = stOutput.distance;
544 output.triangleParameter1[0] = stOutput.triangleParameter[0];
545 output.triangleParameter1[1] = stOutput.triangleParameter[1];
546 output.triangleParameter1[2] = stOutput.triangleParameter[2];
547 output.triangleParameter2[i0] =
548 ( (Scalar)0.5 ) * ( (Scalar)1 - stOutput.segmentParameter / segExtent );
549 output.triangleParameter2[i1] = (Scalar)1 - output.triangleParameter2[i0];
550 output.triangleParameter2[3 - i0 - i1] = (Scalar)0;
551 output.closestPoint[0] = stOutput.closestPoint[0];
552 output.closestPoint[1] = stOutput.closestPoint[1];
@ Geometry
"Geometry" render objects are those loaded using Radium::IO and generated by GeometrySystem
hepler function to manage enum as underlying types in VariableSet
Structure holding the result of a line-to-segment distance query.
Structure holding the result of a line-to-triangle distance query.
Structure holding the result of a point-to triangle distance query.
Scalar distanceSquared
the point hit on the mesh
Flags
Flags denoting the primitive where the closest point is.
uchar flags
distance squared to the point
Flags getHitPrimitive() const
Return if the hit is a face, a vertex or an edge.
Structure holding the result of a segment-to-triangle distance query.
Structure holding the result of a triangle-to-triangle distance query.