예제 #1
0
 public void LineCheck(KDopCollisionCheck check)
 {
     if (nodes == null || nodes.Count == 0)
     {
         return;
     }
     nodes[0].LineCheck(check, this);
 }
예제 #2
0
    private void LineCheckTriangles(KDopCollisionCheck check, KDopTree kDopTree)
    {
        for (int triIndex = data.startIndex; triIndex < data.startIndex + data.numTriangles; ++triIndex)
        {
            KDopTriangle tri   = kDopTree.triangles[triIndex];
            Vector3      trip0 = tri.v0;
            Vector3      trip1 = tri.v1;
            Vector3      trip2 = tri.v2;

            Vector3 linep0 = check.LocalStart;
            Vector3 linep1 = check.LocalEnd;

            // Line is on the same side of triangle-plane
            Vector3 triNormal = Vector3.Cross(trip1 - trip0, trip2 - trip0);
            triNormal.Normalize();
            float   triPlaneD = Vector3.Dot(trip0, triNormal);
            Vector4 triPlane  = new Vector4(triNormal.x, triNormal.y, triNormal.z, triPlaneD);
            float   line0D    = Vector3.Dot(linep0, triNormal) - triPlaneD;
            float   line1D    = Vector3.Dot(linep1, triNormal) - triPlaneD;
            if (line0D * line1D > 0)
            {
                continue;
            }

            // Figure out the hit point(intersection)
            float   hitTime = line0D / (line0D - line1D);
            Vector3 lineDir = linep1 - linep0;
            Vector3 hitP    = linep0 + lineDir * hitTime;

            // Check if the point point is inside the triangle
            s_trianglePoints[0] = trip0;
            s_trianglePoints[1] = trip1;
            s_trianglePoints[2] = trip2;
            for (int sideIndex = 0; sideIndex < 3; ++sideIndex)
            {
                Vector3 edge    = s_trianglePoints[(sideIndex + 1) % 3] - s_trianglePoints[sideIndex];
                Vector3 sideDir = Vector3.Cross(triNormal, edge);
                Vector3 hitDir  = hitP - s_trianglePoints[sideIndex];
                float   side    = Vector3.Dot(hitDir, sideDir);
                if (side < 0)
                {
                    // Hit point is outside the triangle.
                    hitTime = float.MaxValue;
                    break;
                }
            }

            if (hitTime < check.HitResult.hitTime)
            {
                check.HitResult.hitTime     = hitTime;
                check.HitResult.isHit       = true;
                check.HitResult.hitTriangle = triIndex;
            }
        }
    }
예제 #3
0
 public void LineCheck(KDopCollisionCheck check, KDopTree kDopTree)
 {
     if (isLeaf)
     {
         if (LineCheckBounds(check, kDopTree))
         {
             LineCheckTriangles(check, kDopTree);
         }
     }
     else
     {
         if (LineCheckBounds(check, kDopTree))
         {
             kDopTree.nodes[data.leftNode].LineCheck(check, kDopTree);
             kDopTree.nodes[data.rightNode].LineCheck(check, kDopTree);
         }
     }
 }
예제 #4
0
    private bool LineCheckBounds(KDopCollisionCheck check, KDopTree kDopTree)
    {
        Vector3 min = boundingVolumes.min;
        Vector3 max = boundingVolumes.max;

        Vector3 startP = check.LocalStart;
        Vector3 endP   = check.LocalEnd;

        Vector3 dir        = check.LocalEnd - check.LocalStart;
        Vector3 oneOverDir = check.LocalOneOverDir;

        // Slabs
        float _minSlabX = (min.x - startP.x) * oneOverDir.x;
        float _minSlabY = (min.y - startP.y) * oneOverDir.y;
        float _minSlabZ = (min.z - startP.z) * oneOverDir.z;

        float _maxSlabX = (max.x - startP.x) * oneOverDir.x;
        float _maxSlabY = (max.y - startP.y) * oneOverDir.y;
        float _maxSlabZ = (max.z - startP.z) * oneOverDir.z;

        // Min/Max Slabs
        float minSlabX = Mathf.Min(_minSlabX, _maxSlabX);
        float minSlabY = Mathf.Min(_minSlabY, _maxSlabY);
        float minSlabZ = Mathf.Min(_minSlabZ, _maxSlabZ);

        float maxSlabX = Mathf.Max(_minSlabX, _maxSlabX);
        float maxSlabY = Mathf.Max(_minSlabY, _maxSlabY);
        float maxSlabZ = Mathf.Max(_minSlabZ, _maxSlabZ);

        float minSlab = Mathf.Max(Mathf.Max(minSlabX, minSlabY), minSlabZ);
        float maxSlab = Mathf.Min(Mathf.Min(maxSlabX, maxSlabY), maxSlabZ);

        bool bHit = maxSlab >= 0.0f && maxSlab >= minSlab && minSlab <= 1.0f;

        if (bHit)
        {
            int hitSurface = 0;
            if (minSlab >= 0 && minSlab <= 1)
            {
                // Draw first hit point
                ++hitSurface;
            }
            if (maxSlab >= 0 && maxSlab <= 1)
            {
                // Draw second hit point
                ++hitSurface;
            }
            if (hitSurface == 0)
            {
                // line segment inside bounds
                return(true);
            }
            else
            {
                // line segment hit surface
                return(true);
            }
        }
        else
        {
            // line segment hit nothing
            return(false);
        }
    }