// box intersect face and return intersection distance, point and normal
        public override bool BoxIntersect(CollisionBox ray_box, Vector3 ray_origin, Vector3 ray_direction, Vector3[] vert_pos,
            out float intersect_distance, out Vector3 intersect_position, out Vector3 intersect_normal)
        {
            intersect_distance = float.MaxValue;
            intersect_position = ray_origin;
            intersect_normal = Vector3.Zero;

            bool intersected = false;
            Vector3 p1, p2, p3, p4;
            uint i, j;

            CollisionBox world_box = new CollisionBox(ray_box.min + ray_origin, ray_box.max + ray_origin);

            Vector3[] box_verts = world_box.GetVertices();
            Vector3[] box_edges = world_box.GetEdges();

            // intersect box edges to face edges
            for (i = 0; i < 12; i++)
            {
                // cull edges with normal more than 135 degree from moving direction
                if (Vector3.Dot(CollisionBox.edge_normals[i], ray_direction) < -0.70710678)
                    continue;

                p1 = box_edges[i * 2];
                p2 = box_edges[i * 2 + 1];
                p4 = vert_pos[vertices[0]];
                for (j = 0; j < vertices.Length; j++)
                {
                    p3 = p4;
                    p4 = vert_pos[vertices[(j + 1) % vertices.Length]];

                    float distance;
                    Vector3 position;
                    if (CollisionFace.EdgeIntersect(p1, p2, ray_direction, p3, p4, out distance, out position))
                    {
                        if (distance < intersect_distance)
                        {
                            intersect_distance = distance;
                            intersect_position = position;
                            intersect_normal = Vector3.Normalize(Vector3.Cross(p2-p1,p3-p4));
                            if (Vector3.Dot(ray_direction, intersect_normal) > 0)
                                intersect_normal = Vector3.Negate(intersect_normal);
                            intersected = true;
                        }
                    }
                }
            }

            // intersect from face vertices to box
            for (i = 0; i < 3; i++)
            {
                float tnear, tfar;
                p1 = vert_pos[vertices[i]];
                int box_face_id = world_box.RayIntersect(p1, -ray_direction, out tnear, out tfar);
                if (box_face_id > -1)
                {
                    if (tnear < intersect_distance)
                    {
                        intersect_distance = tnear;
                        intersect_position = p1;
                        intersect_normal = -CollisionBox.face_normals[box_face_id];
                        intersected = true;
                    }
                }
            }

            // intersect from box vertices to face polygon
            Vector3 v1 = vert_pos[vertices[0]];
            Vector3 v2 = vert_pos[vertices[1]];
            Vector3 v3 = vert_pos[vertices[2]];
            for (i = 0; i < 8; i++)
            {
                // cull vertices with normal more than 135 degree from moving direction
                if (Vector3.Dot(CollisionBox.vertex_normals[i], ray_direction) < -0.70710678)
                    continue;

                Vector3 uvt;
                if (CollisionFace.RayTriangleIntersect(box_verts[i], ray_direction, v1, v2, v3, out uvt.Z, out uvt.X, out uvt.Y))
                {
                    if (uvt.Z < intersect_distance)
                    {
                        intersect_distance = uvt.Z;
                        intersect_position = (1.0f - uvt.X - uvt.Y) * v1 + uvt.X * v2 + uvt.Y * v3;
                        intersect_normal = Vector3.Normalize(Vector3.Cross(v3 - v1, v2 - v1));
                        intersected = true;
                    }
                }
            }

            return intersected;
        }
Example #2
0
        // box intersect face and return intersection distance, point and normal
        public override bool BoxIntersect(
            CollisionBox rayBox,
            Vector3 rayOrigin,
            Vector3 rayDirection,
            Vector3[] vertices,
            out float intersectDistance,
            out Vector3 intersectPosition,
            out Vector3 intersectNormal)
        {
            intersectDistance = float.MaxValue;
            intersectPosition = rayOrigin;
            intersectNormal   = Vector3.Zero;

            bool    intersected = false;
            Vector3 p1, p2, p3, p4;
            uint    i, j;

            CollisionBox worldBox = new CollisionBox(rayBox.min + rayOrigin,
                                                     rayBox.max + rayOrigin);

            Vector3[] boxVerts = worldBox.GetVertices();
            Vector3[] boxEdges = worldBox.GetEdges();

            float   distance;
            Vector3 position;

            // intersect box edges to face edges
            for (i = 0; i < 12; i++)
            {
                // cull edges with normal more than 135 degree from moving direction
                float dot = Vector3.Dot(CollisionBox.edgeNormals[i], rayDirection);
                if (dot < -0.70710678)
                {
                    continue;
                }

                p1 = boxEdges[i * 2];
                p2 = boxEdges[i * 2 + 1];
                p4 = vertices[indices[0]];
                for (j = 0; j < indices.Length; j++)
                {
                    p3 = p4;
                    p4 = vertices[indices[(j + 1) % indices.Length]];

                    if (CollisionFace.EdgeIntersect(p1, p2, rayDirection,
                                                    p3, p4, out distance, out position))
                    {
                        if (distance < intersectDistance)
                        {
                            intersectDistance = distance;
                            intersectPosition = position;
                            intersectNormal   = Vector3.Cross(p2 - p1, p3 - p4);
                            intersectNormal   = Vector3.Normalize(intersectNormal);
                            if (Vector3.Dot(rayDirection, intersectNormal) > 0)
                            {
                                intersectNormal = Vector3.Negate(intersectNormal);
                            }
                            intersected = true;
                        }
                    }
                }
            }

            // intersect from face vertices to box
            for (i = 0; i < 3; i++)
            {
                float tnear, tfar;
                p1 = vertices[indices[i]];
                int box_face_id = worldBox.RayIntersect(p1, -rayDirection,
                                                        out tnear, out tfar);
                if (box_face_id > -1)
                {
                    if (tnear < intersectDistance)
                    {
                        intersectDistance = tnear;
                        intersectPosition = p1;
                        intersectNormal   = -CollisionBox.faceNormals[box_face_id];
                        intersected       = true;
                    }
                }
            }

            // intersect from box vertices to face polygon
            Vector3 v1 = vertices[indices[0]];
            Vector3 v2 = vertices[indices[1]];
            Vector3 v3 = vertices[indices[2]];
            Vector3 uvt;

            for (i = 0; i < 8; i++)
            {
                // cull vertices with normal more than 135 degree from moving direction
                float dot = Vector3.Dot(CollisionBox.vertexNormals[i], rayDirection);
                if (dot < -0.70710678)
                {
                    continue;
                }

                if (CollisionFace.RayTriangleIntersect(boxVerts[i], rayDirection,
                                                       v1, v2, v3, out uvt.Z, out uvt.X, out uvt.Y))
                {
                    if (uvt.Z < intersectDistance)
                    {
                        intersectDistance = uvt.Z;
                        intersectPosition = (1.0f - uvt.X - uvt.Y) *
                                            v1 + uvt.X * v2 + uvt.Y * v3;
                        intersectNormal = Vector3.Cross(v3 - v1, v2 - v1);
                        intersectNormal = Vector3.Normalize(intersectNormal);
                        intersected     = true;
                    }
                }
            }

            return(intersected);
        }