コード例 #1
0
    bool MeshIntersects(const Ray& ray, float3* pos, uint32_t posCount, uint32_t* indices, uint32_t indicesCount,
                        bool backfaceCull, float* out_tmin, float3* out_pos, float3* out_nor, float3* nearestVertex)
    {        
        if(posCount == 0) 
            return false;

        uint32_t LastTri = indicesCount -3;
        bool hit = false;
        bool tri_hit = false;
        float dist = FLT_MAX;
        float hit_dist = FLT_MAX;
        float3 hit_pos;
        float3 hit_nor;
        Triangle tri;

        for( uint32_t i = 0; i <= LastTri; i+=3 )
        {
            assert(indices[i] < posCount);
            assert(indices[i+1] < posCount);
            assert(indices[i+2] < posCount);

            tri.A = pos[ indices[i]];
            tri.B = pos[ indices[i+1]];
            tri.C = pos[ indices[i+2]];
            
            tri_hit = IntersectionRayTriangle(ray, tri, backfaceCull, &hit_dist, &hit_pos, &hit_nor);            
            if(tri_hit)
            {                
                hit = true;
                if(hit_dist < dist)
                {
                    dist = hit_dist;
                    *out_tmin = hit_dist;
                    *out_pos = hit_pos;
                    *out_nor = hit_nor;

                    float distA = lengthsquared(hit_pos - tri.A);
                    float distB = lengthsquared(hit_pos - tri.B);
                    float distC = lengthsquared(hit_pos - tri.C);
                    
                    if(distA <= distB && distA <= distC)
                        *nearestVertex = tri.A;
                    else if( distB < distC)
                        *nearestVertex = tri.B;
                    else
                        *nearestVertex = tri.C;

                }
            }
           
        }  
        return hit;
    }
コード例 #2
0
 // find close point on line l that is closest to point p.
 // see arg l and p.
 float3 ClosestPointOnLineToPoint(const LineSeg &l, const float3 &p)
 {
     float3 ab = l.B - l.A;
     float t = dot((p-l.A), ab) / lengthsquared(ab);
     t = clamp(t,0.0f,1.0f);
     return l.A + t * ab;
 }
コード例 #3
0
ファイル: V3dMath.cpp プロジェクト: Averroes/LevelEditor
    Matrix Matrix::CreateBillboard(const float3& objectPos, const float3& camPos, const float3& camUp, const float3& camLook)
    {
         Matrix matrix;
         float3 look = camPos - objectPos;            
         float len = lengthsquared(look);

         if (len < 0.0001f)
         {
             look = -camLook;
         }
         else
         {
             look = normalize(look);
         }

         float3 right = normalize( cross(camUp, look) );
         float3 up = cross(look,right);

         matrix.M11 = right.x;
         matrix.M12 = right.y;
         matrix.M13 = right.z;
         matrix.M14 = 0.0f;
         matrix.M21 = up.x;
         matrix.M22 = up.y;
         matrix.M23 = up.z;
         matrix.M24 = 0.0f;
         matrix.M31 = look.x;
         matrix.M32 = look.y;
         matrix.M33 = look.z;
         matrix.M34 = 0.0f;
         matrix.M41 = objectPos.x;
         matrix.M42 = objectPos.y;
         matrix.M43 = objectPos.z;
         matrix.M44 = 1.0f;
         return matrix;
    }
コード例 #4
0
    //-----------------------------------------------------------------------------
    // Frustum Triangle intersection  using separating axis test.
    // note: the frustum and the triangle must be in the same space.
    //       optimization needed
    bool FrustumTriangleIntersect(const Frustum& fr, const Triangle& tri)
    {            
        bool allInside = true;        
        for(int i = 0; i < 6; ++i)
        {
            const Plane& plane = fr[i];
            float d1 = plane.Eval(tri.A);
            float d2 = plane.Eval(tri.B);
            float d3 = plane.Eval(tri.C); 

            // if all outside a single plane, then there is
            // no intersection.
            if( d1 < 0 && d2 < 0 && d3 < 0) 
                return false;
            allInside = allInside && ( d1 > 0 && d2 > 0 && d3 > 0);            
        }

        // the tri is completely inside the frustum.
        if( allInside ) 
            return true; 

        // separating axis test.
        // Triangle:  3 edges  1 face normal.
        // Frustum:   6 edges, 5 face normal.
        // for total of 24 separating axis.
        // note this test can be optimized.
                        
        // tri edges
        float3 triEdges[3];
        triEdges[0] = tri.B - tri.A;
        triEdges[1] = tri.C - tri.A;
        triEdges[2] = tri.C - tri.B;

        // frustum edges
        float3 FrEdges[6];
        FrEdges[0] = fr.Corner(Frustum::NearTopLeft) - fr.Corner(Frustum::NearTopRight);
        FrEdges[1] = fr.Corner(Frustum::NearBottomRight) - fr.Corner(Frustum::NearTopRight);
        FrEdges[2] = (fr.Corner(Frustum::FarBottonLeft) - fr.Corner(Frustum::NearBottonLeft));
        FrEdges[3] = (fr.Corner(Frustum::FarBottomRight) - fr.Corner(Frustum::NearBottomRight));
        FrEdges[4] = (fr.Corner(Frustum::FarTopRight) - fr.Corner(Frustum::NearTopRight));
        FrEdges[5] = (fr.Corner(Frustum::FarTopLeft) - fr.Corner(Frustum::NearTopLeft));

        int k = 0;        
        float3 Axis[24];                
        Axis[k++] = fr.TopPlane().normal;
        Axis[k++] = fr.BottomPlane().normal;
        Axis[k++] = fr.LeftPlane().normal;
        Axis[k++] = fr.RightPlane().normal;
        Axis[k++] = fr.NearPlane().normal;
        Axis[k++] = normalize(cross(triEdges[0], triEdges[1]));

        for(int te = 0;  te < 3; te++)
        {
            for(int fe = 0; fe < 6; fe++)
            {
                float3 axis = cross( triEdges[te], FrEdges[fe]); 
                Axis[k++] = normalize(axis);                
            }
        }
                
        for(int n = 0; n < 24; n++)
        {
            float3 axis = Axis[n];
            if( lengthsquared(axis) < Epsilon) 
                continue;
            float trid1 = dot(tri.A,axis);
            float trid2 = dot(tri.B,axis);
            float trid3 = dot(tri.C,axis);

            float trMin = std::min(trid1,trid2);
            trMin = std::min(trMin, trid3);
            float trMax = std::max(trid1,trid2);
            trMax = std::max(trMax,trid3);

            float frMin = dot(fr.Corner(0),axis);
            float frMax = frMin;
            for(int c = 1; c < 8; c++)
            {
                float fdist = dot(fr.Corner(c), axis);
                frMin = std::min(frMin,fdist);
                frMax = std::max(frMax,fdist);
            }
           
            if( (trMax < frMin) || (frMax < trMin))
            {               
                return false;                
            }
        }

        // must be intersecting.
        return true;
               
    }