Ray-triangle intersection

后端 未结 4 1464
无人及你
无人及你 2021-01-31 05:07

I saw that Fast Minimum Storage Ray/Triangle Intersection by Moller and Trumbore is frequently recommended.

The thing is, I don\'t mind pre-computing and storing any amo

4条回答
  •  一个人的身影
    2021-01-31 05:19

    I have done a lot of benchmarks, and I can confidently say that the fastest (published) method is the one invented by Havel and Herout and presented in their paper Yet Faster Ray-Triangle Intersection (Using SSE4). Even without using SSE it is about twice as fast as Möller and Trumbore's algorithm.

    My C implementation of Havel-Herout:

        typedef struct {
            vec3 n0; float d0;
            vec3 n1; float d1;
            vec3 n2; float d2;
        } isect_hh_data;
    
        void
        isect_hh_pre(vec3 v0, vec3 v1, vec3 v2, isect_hh_data *D) {
            vec3 e1 = v3_sub(v1, v0);
            vec3 e2 = v3_sub(v2, v0);
            D->n0 = v3_cross(e1, e2);
            D->d0 = v3_dot(D->n0, v0);
    
            float inv_denom = 1 / v3_dot(D->n0, D->n0);
    
            D->n1 = v3_scale(v3_cross(e2, D->n0), inv_denom);
            D->d1 = -v3_dot(D->n1, v0);
    
            D->n2 = v3_scale(v3_cross(D->n0, e1), inv_denom);
            D->d2 = -v3_dot(D->n2, v0);
        }
    
        inline bool
        isect_hh(vec3 o, vec3 d, float *t, vec2 *uv, isect_hh_data *D) {
            float det = v3_dot(D->n0, d);
            float dett = D->d0 - v3_dot(o, D->n0);
            vec3 wr = v3_add(v3_scale(o, det), v3_scale(d, dett));
            uv->x = v3_dot(wr, D->n1) + det * D->d1;
            uv->y = v3_dot(wr, D->n2) + det * D->d2;
            float tmpdet0 = det - uv->x - uv->y;
            int pdet0 = ((int_or_float)tmpdet0).i;
            int pdetu = ((int_or_float)uv->x).i;
            int pdetv = ((int_or_float)uv->y).i;
            pdet0 = pdet0 ^ pdetu;
            pdet0 = pdet0 | (pdetu ^ pdetv);
            if (pdet0 & 0x80000000)
                return false;
            float rdet = 1 / det;
            uv->x *= rdet;
            uv->y *= rdet;
            *t = dett * rdet;
            return *t >= ISECT_NEAR && *t <= ISECT_FAR;
        }
    

提交回复
热议问题