Mesh: [skip ci] update tri-tri-intersection

This commit is contained in:
wmayer
2021-10-19 15:14:36 +02:00
parent 0e2c402c20
commit 277c5ef9e9

View File

@@ -14,20 +14,38 @@
* Here is a version withouts divisions (a little faster)
* int NoDivTriTriIsect(float V0[3],float V1[3],float V2[3],
* float U0[3],float U1[3],float U2[3]);
*
*
* This version computes the line of intersection as well (if they are not coplanar):
* int tri_tri_intersect_with_isectline(float V0[3],float V1[3],float V2[3],
* int tri_tri_intersect_with_isectline(float V0[3],float V1[3],float V2[3],
* float U0[3],float U1[3],float U2[3],int *coplanar,
* float isectpt1[3],float isectpt2[3]);
* coplanar returns whether the tris are coplanar
* isectpt1, isectpt2 are the endpoints of the line of intersection
*/
/*
Copyright 2020 Tomas Akenine-Möller
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <math.h>
#define FABS(x) ((float)fabs(x)) /* implement as is fastest on your machine */
/* if USE_EPSILON_TEST is true then we do a check:
/* if USE_EPSILON_TEST is true then we do a check:
if |dv|<EPSILON then dv=0.0;
else no check is done (which is less robust)
*/
@@ -43,13 +61,13 @@
#define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2])
#define SUB(dest,v1,v2) dest[0]=v1[0]-v2[0]; dest[1]=v1[1]-v2[1]; dest[2]=v1[2]-v2[2];
#define SUB(dest,v1,v2) dest[0]=v1[0]-v2[0]; dest[1]=v1[1]-v2[1]; dest[2]=v1[2]-v2[2];
#define ADD(dest,v1,v2) dest[0]=v1[0]+v2[0]; dest[1]=v1[1]+v2[1]; dest[2]=v1[2]+v2[2];
#define ADD(dest,v1,v2) dest[0]=v1[0]+v2[0]; dest[1]=v1[1]+v2[1]; dest[2]=v1[2]+v2[2];
#define MULT(dest,v,factor) dest[0]=factor*v[0]; dest[1]=factor*v[1]; dest[2]=factor*v[2];
#define SET(dest,src) dest[0]=src[0]; dest[1]=src[1]; dest[2]=src[2];
#define SET(dest,src) dest[0]=src[0]; dest[1]=src[1]; dest[2]=src[2];
/* sort so that a<=b */
#define SORT(a,b) \
@@ -101,7 +119,7 @@
/* this edge to edge test is based on Franlin Antonio's gem:
"Faster Line Segment Intersection", in Graphics Gems III,
pp. 199-202 */
pp. 199-202 */
#define EDGE_EDGE_TEST(V0,U0,U1) \
Bx=U0[i0]-U1[i0]; \
By=U0[i1]-U1[i1]; \
@@ -120,7 +138,7 @@
{ \
if(e<=0 && e>=f) return 1; \
} \
}
}
#define EDGE_AGAINST_TRI_EDGES(V0,V1,U0,U1,U2) \
{ \
@@ -172,7 +190,7 @@ int coplanar_tri_tri(float N[3],float V0[3],float V1[3],float V2[3],
A[2]=fabs(N[2]);
if(A[0]>A[1])
{
if(A[0]>A[2])
if(A[0]>A[2])
{
i0=1; /* A[0] is greatest */
i1=2;
@@ -188,20 +206,20 @@ int coplanar_tri_tri(float N[3],float V0[3],float V1[3],float V2[3],
if(A[2]>A[1])
{
i0=0; /* A[2] is greatest */
i1=1;
i1=1;
}
else
{
i0=0; /* A[1] is greatest */
i1=2;
}
}
}
/* test all edges of triangle 1 against the edges of triangle 2 */
EDGE_AGAINST_TRI_EDGES(V0,V1,U0,U1,U2);
EDGE_AGAINST_TRI_EDGES(V1,V2,U0,U1,U2);
EDGE_AGAINST_TRI_EDGES(V2,V0,U0,U1,U2);
/* finally, test if tri1 is totally contained in tri2 or vice versa */
POINT_IN_TRI(V0,U0,U1,U2);
POINT_IN_TRI(U0,V0,V1,V2);
@@ -268,7 +286,7 @@ int tri_tri_intersect(float V0[3],float V1[3],float V2[3],
dv0dv1=dv0*dv1;
dv0dv2=dv0*dv2;
if(dv0dv1>0.0f && dv0dv2>0.0f) /* same sign on all of them + not equal 0 ? */
return 0; /* no intersection occurs */
@@ -287,7 +305,7 @@ int tri_tri_intersect(float V0[3],float V1[3],float V2[3],
vp0=V0[index];
vp1=V1[index];
vp2=V2[index];
up0=U0[index];
up1=U1[index];
up2=U2[index];
@@ -465,16 +483,16 @@ int NoDivTriTriIsect(float V0[3],float V1[3],float V2[3],
inline void isect2(float VTX0[3],float VTX1[3],float VTX2[3],float VV0,float VV1,float VV2,
float D0,float D1,float D2,float *isect0,float *isect1,float isectpoint0[3],float isectpoint1[3])
float D0,float D1,float D2,float *isect0,float *isect1,float isectpoint0[3],float isectpoint1[3])
{
float tmp=D0/(D0-D1);
float tmp=D0/(D0-D1);
float diff[3];
*isect0=VV0+(VV1-VV0)*tmp;
*isect0=VV0+(VV1-VV0)*tmp;
SUB(diff,VTX1,VTX0);
MULT(diff,diff,tmp);
ADD(isectpoint0,diff,VTX0);
tmp=D0/(D0-D2);
*isect1=VV0+(VV2-VV0)*tmp;
tmp=D0/(D0-D2);
*isect1=VV0+(VV2-VV0)*tmp;
SUB(diff,VTX2,VTX0);
MULT(diff,diff,tmp);
ADD(isectpoint1,VTX0,diff);
@@ -500,33 +518,33 @@ inline int compute_intervals_isectline(float VERT0[3],float VERT1[3],float VERT2
float D0D1,float D0D2,float *isect0,float *isect1,
float isectpoint0[3],float isectpoint1[3])
{
if(D0D1>0.0f)
{
/* here we know that D0D2<=0.0 */
if(D0D1>0.0f)
{
/* here we know that D0D2<=0.0 */
/* that is D0, D1 are on the same side, D2 on the other or on the plane */
isect2(VERT2,VERT0,VERT1,VV2,VV0,VV1,D2,D0,D1,isect0,isect1,isectpoint0,isectpoint1);
}
else if(D0D2>0.0f)
{
/* here we know that d0d1<=0.0 */
}
else if(D0D2>0.0f)
{
/* here we know that d0d1<=0.0 */
isect2(VERT1,VERT0,VERT2,VV1,VV0,VV2,D1,D0,D2,isect0,isect1,isectpoint0,isectpoint1);
}
else if(D1*D2>0.0f || D0!=0.0f)
{
}
else if(D1*D2>0.0f || D0!=0.0f)
{
/* here we know that d0d1<=0.0 or that D0!=0.0 */
isect2(VERT0,VERT1,VERT2,VV0,VV1,VV2,D0,D1,D2,isect0,isect1,isectpoint0,isectpoint1);
}
else if(D1!=0.0f)
{
isect2(VERT1,VERT0,VERT2,VV1,VV0,VV2,D1,D0,D2,isect0,isect1,isectpoint0,isectpoint1);
}
else if(D2!=0.0f)
{
isect2(VERT2,VERT0,VERT1,VV2,VV0,VV1,D2,D0,D1,isect0,isect1,isectpoint0,isectpoint1);
}
else
{
/* triangles are coplanar */
isect2(VERT0,VERT1,VERT2,VV0,VV1,VV2,D0,D1,D2,isect0,isect1,isectpoint0,isectpoint1);
}
else if(D1!=0.0f)
{
isect2(VERT1,VERT0,VERT2,VV1,VV0,VV2,D1,D0,D2,isect0,isect1,isectpoint0,isectpoint1);
}
else if(D2!=0.0f)
{
isect2(VERT2,VERT0,VERT1,VV2,VV0,VV1,D2,D0,D1,isect0,isect1,isectpoint0,isectpoint1);
}
else
{
/* triangles are coplanar */
return 1;
}
return 0;
@@ -538,7 +556,7 @@ inline int compute_intervals_isectline(float VERT0[3],float VERT1[3],float VERT2
/* here we know that D0D2<=0.0 */ \
/* that is D0, D1 are on the same side, D2 on the other or on the plane */ \
isect2(VERT2,VERT0,VERT1,VV2,VV0,VV1,D2,D0,D1,&isect0,&isect1,isectpoint0,isectpoint1); \
}
}
#if 0
else if(D0D2>0.0f) \
{ \
@@ -628,7 +646,7 @@ int tri_tri_intersect_with_isectline(float V0[3],float V1[3],float V2[3],
dv0dv1=dv0*dv1;
dv0dv2=dv0*dv2;
if(dv0dv1>0.0f && dv0dv2>0.0f) /* same sign on all of them + not equal 0 ? */
return 0; /* no intersection occurs */
@@ -647,7 +665,7 @@ int tri_tri_intersect_with_isectline(float V0[3],float V1[3],float V2[3],
vp0=V0[index];
vp1=V1[index];
vp2=V2[index];
up0=U0[index];
up1=U1[index];
up2=U2[index];
@@ -655,7 +673,7 @@ int tri_tri_intersect_with_isectline(float V0[3],float V1[3],float V2[3],
/* compute interval for triangle 1 */
*coplanar=compute_intervals_isectline(V0,V1,V2,vp0,vp1,vp2,dv0,dv1,dv2,
dv0dv1,dv0dv2,&isect1[0],&isect1[1],isectpointA1,isectpointA2);
if(*coplanar) return coplanar_tri_tri(N1,V0,V1,V2,U0,U1,U2);
if(*coplanar) return coplanar_tri_tri(N1,V0,V1,V2,U0,U1,U2);
/* compute interval for triangle 2 */
@@ -693,12 +711,12 @@ int tri_tri_intersect_with_isectline(float V0[3],float V1[3],float V2[3],
if(isect2[1]>isect1[1])
{
if(smallest1==0) { SET(isectpt2,isectpointA2); }
else { SET(isectpt2,isectpointA1); }
else { SET(isectpt2,isectpointA1); }
}
else
{
if(smallest2==0) { SET(isectpt2,isectpointB2); }
else { SET(isectpt2,isectpointB1); }
else { SET(isectpt2,isectpointB1); }
}
}
return 1;