线段与三角形求交

最近需要用到这个求交计算,开始看了《计算机图形学几何工具算法详解》,里面的讲解很详细,但是给出的代码有点问题,而且用到的类/结构体的定义并没有给出,所以只能自己猜测,后来发现有的时候求出的结果有误,所以又在网上搜了一下,自己再整理如下,大家可以直接拷贝粘贴过去使用。

该算法主要思想是先求出线段与三角形所在平面的交点,然后判断该交点是否位于三角形内部。

利用三角形(顶点为V0, V1, V2)内任意一点Q可以用重心坐标表示为 Q = w*V0 + u*V1 + v*V2; 其中w+u+v=1,三元组(w, u, v)称为Q的重心坐标。设线段方程为 L: p + t*d; p为一个端点,d 为两个端点的差,即方向。

由 p + t*d = (1-u-v)*V0 + u*V1 + v*V2; 可以求出t, u, v的值。当 0=<u, v<=1 并且 0=<u+v<=1时,交点位于三角形内。

 

struct tri3d
{
     float v0[3];
     float v1[3];
     float v2[3];
};

 

float vector_dot(float v0[3], float3 v1[3])
{
     return v0[0] * v1[0] + v0[1] * v1[1] + v0[2] * v1[2];
}

 

void vector_minus(float a[3], float b[3], float res[3])
{
     res[0] = a[0]-b[0];
     res[1] = a[1]-b[1];
     res[2] = a[2]-b[2];
}

 

void vector_cross(float a[3], float b[3], float res[3])
{
     res[0] = a[1]*b[2]-a[2]*b[1];
     res[1] = a[2]*b[0]-a[0]*b[2];
     res[2] = a[0]*b[1]-a[1]*b[0];
}

 

bool LineTriangleIntersect(float start[3], float end[3], tri3d tri, float intersection[3])
{
     const float epsilon = 0.000001f;
     float e1[3], e2[3], p[3], s[3], q[3];
     float t, u, v, tmp;
     float direction[3]; 
     vector_minus(end, start, direction);
     vector_minus(tri.v1, tri.v0, e1);
     vector_minus(tri.v2, tri.v0, e2);
     vector_cross(direction, e2, p);
     tmp = vector_dot(p, e1);
     if (tmp > -epsilon && tmp < epsilon)
          return false;
     tmp = 1.0f / tmp;
     vector_minus(start, tri.v0, s);
     u = tmp * vector_dot(s, p);
     if (u < 0.0 || u > 1.0)
          return false;
     vector_cross(s, e1, q);
     v = tmp * vector_dot(direction, q);
     if (v < 0.0 || v > 1.0)
          return false;
     if (u + v > 1.0)
          return false;
     t = tmp * vector_dot(e2, q);
     if (t < 0.0 || t > 1.0)
          return false;
     intersection[0] = start[0] + t * direction[0];
     intersection[1] = start[1] + t * direction[1];
     intersection[2] = start[2] + t * direction[2];
     return true;
}

 

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值