欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

三维空间三角形与线段相交判断

程序员文章站 2024-03-16 18:41:40
...

 很多几何对象的相交判断都可以转化为三角形与直线的相交判断

#include <iostream>
#include <numeric>
#include <math.h>
#include <stdio.h>

class vec3 {
public:
    float x, y, z;

    float dot(const vec3& b) {
        return vec3::x * b.x + vec3::y * b.y + vec3::z * b.z;
    }

    vec3 cross(const vec3& b) {
        return vec3::vec3(
            vec3::y * b.z - vec3::z * b.y,
            vec3::z * b.x - vec3::x * b.z,
            vec3::x * b.y - vec3::y * b.x
        );
    }

    vec3 normalize() {
        const float s = 1.0f / sqrtf(vec3::x * vec3::x + vec3::y * vec3::y + vec3::z * vec3::z);
        return vec3::vec3(vec3::x * s, vec3::y * s, vec3::z * s);
    }

    vec3 operator+(const vec3& b) {
        return vec3::vec3(
            vec3::x + b.x,
            vec3::y + b.y,
            vec3::z + b.z
        );
    }
    vec3 operator+=(const vec3& b) {
        *this = vec3::operator+(b);
        return *this;
    }

    vec3 operator-(const vec3& b) {
        return vec3::vec3(
            vec3::x - b.x,
            vec3::y - b.y,
            vec3::z - b.z
        );
    }
    vec3 operator-=(const vec3& b) {
        *this = vec3::operator-(b);
        return *this;
    }

    vec3 operator*(const vec3& b) {
        return vec3::vec3(
            vec3::x * b.x,
            vec3::y * b.y,
            vec3::z * b.z
        );
    }
    vec3 operator*=(const vec3& b) {
        *this = vec3::operator*(b);
        return *this;
    }
    vec3 operator*(float b) {
        return vec3::vec3(
            vec3::x * b,
            vec3::y * b,
            vec3::z * b
        );
    }
    vec3 operator*=(float b) {
        *this = vec3::operator*(b);
        return *this;
    }

    vec3 operator/(const vec3& b) {
        return vec3::vec3(
            vec3::x / b.x,
            vec3::y / b.y,
            vec3::z / b.z
        );
    }
    vec3 operator/=(const vec3& b) {
        *this = vec3::operator/(b);
        return *this;
    }
    vec3 operator/(float b) {
        return vec3::vec3(
            vec3::x * b,
            vec3::y * b,
            vec3::z * b
        );
    }
    vec3 operator/=(float b) {
        *this = vec3::operator/(b);
        return *this;
    }

    vec3(float x, float y, float z) {
        vec3::x = x;
        vec3::y = y;
        vec3::z = z;
    }
    vec3(float x) {
        vec3::x = x;
        vec3::y = x;
        vec3::z = x;
    }
    vec3() {
        //
    }
    ~vec3() {
        //
    }
};

//#define EPSILON 0.000001f
const float EPSILON = std::numeric_limits<float>::epsilon();
bool lineSegIntersectTri(
    vec3 line[2],
    vec3 tri[3],
    vec3& point
) {
    vec3 e0 = tri[1] - tri[0];
    vec3 e1 = tri[2] - tri[0];

    vec3 dir = line[1] - line[0];
    vec3 dir_norm = dir.normalize();

    vec3 h = dir_norm.cross(e1);
    const float a = e0.dot(h);

    if (a > -EPSILON && a < EPSILON) {
        return false;
    }

    vec3 s = line[0] - tri[0];
    const float f = 1.0f / a;
    const float u = f * s.dot(h);

    if (u < 0.0f || u > 1.0f) {
        return false;
    }

    vec3 q = s.cross(e0);
    const float v = f * dir_norm.dot(q);

    if (v < 0.0f || u + v > 1.0f) {
        return false;
    }

    const float t = f * e1.dot(q);

    if (t > EPSILON && t < sqrtf(dir.dot(dir))) { // segment intersection
        point = line[0] + dir_norm * t;
        return true;
    }

    return false;
}


const char* boolStr(bool b) {
    if (b) {
        return "true";
    }

    return "false";
}
int main()
{
    std::cout << "Hello World!\n";
    vec3 tri[3] = {
        { -1.0f, -1.0f, 0.0f },
        { 1.0f, -1.0f, 0.0f },
        { 1.0f, 1.0f, 0.0f },
    };

    vec3 line0[2] = { // should intersect
        { 0.0f, -0.0f, -1.0f },
        { 0.0f, -0.0f, 1.0f },
    };

    vec3 line1[2] = { // should not intersect
        { -0.5f, 0.5f, -1.0f },
        { -0.5f, 0.5f, 1.0f },
    };
    vec3 point0, point1;
    std::cout << boolStr(lineSegIntersectTri(line0, tri, point0)) << point0.x 
        << " " << point0.y << " " << point0.z << std::endl;
    std::cout << boolStr(lineSegIntersectTri(line1, tri, point1)) << point1.x
        << " " << point1.y << " " << point1.z << std::endl;
    
    return 0;
}

三维空间三角形与线段相交判断

上一篇: QT连接FireBird测试

下一篇: