Exemple #1
0
        /// <summary>
        /// Performs a raycast against the mesh triangles and returns info
        /// about the closest hit or null if no triangle was hit by the ray.
        /// </summary>
        /// <param name="meshTransform">
        /// The mesh transform which brings the mesh in the same space as the
        /// ray.
        /// </param>
        /// <remarks>
        /// This method will build the tree if it hasn't already been built.
        /// </remarks>
        public MeshRayHit RaycastClosest(Ray ray, Matrix4x4 meshTransform)
        {
            // Build the tree if it hasn't already been built
            if (!_isBuilt)
            {
                Build();
            }

            // Work in mesh local space by transforming the ray by the inverse of
            // the mesh transform. It is faster to perform this transformation here
            // instead of transforming every possibly hit triangle by 'meshTransform'.
            Ray modelSpaceRay = ray.InverseTransform(meshTransform);

            // Get the list of tree nodes which are hit by the ray
            if (!_tree.RaycastAll(modelSpaceRay, _nodeHitBuffer))
            {
                return(null);
            }

            // Store data in preparation for closest hit identification
            float        t;
            float        minT            = float.MaxValue;
            MeshTriangle closestTriangle = null;
            bool         foundTriangle   = false;

            // Loop through each node hit
            foreach (var nodeHit in _nodeHitBuffer)
            {
                // Get the associated mesh triangle and check if the ray intersects it
                MeshTriangle meshTriangle = nodeHit.HitNode.Data;
                if (TriangleMath.Raycast(modelSpaceRay, out t, meshTriangle.Vertex0, meshTriangle.Vertex1, meshTriangle.Vertex2))
                {
                    if (Vector3.Dot(modelSpaceRay.direction, meshTriangle.Normal) < 0.0f)
                    {
                        // If the intersection offset is smaller than what we have so far,
                        // it means we have a new closest hit.
                        if (t < minT)
                        {
                            minT            = t;
                            closestTriangle = meshTriangle;
                            foundTriangle   = true;
                        }
                    }
                }
            }

            // If we found a triangle, we can return the mesh ray hit information
            if (foundTriangle)
            {
                // Convert the t value in world space. Do the same for the normal.
                Vector3 worldHit = meshTransform.MultiplyPoint(modelSpaceRay.GetPoint(minT));
                minT = (ray.origin - worldHit).magnitude / ray.direction.magnitude;
                Vector3 transformedNormal = meshTransform.inverse.transpose.MultiplyVector(closestTriangle.Normal).normalized;

                // Return the hit instance
                return(new MeshRayHit(ray, closestTriangle.TriangleIndex, minT, transformedNormal));
            }

            return(null);
        }
        public override bool Raycast(Ray ray, out float t)
        {
            var trianglePoints = GetPoints();

            if (_raycastMode == Shape3DRaycastMode.Solid)
            {
                return(TriangleMath.Raycast(ray, out t, trianglePoints[0], trianglePoints[1], trianglePoints[2], _epsilon));
            }
            else
            {
                return(TriangleMath.RaycastWire(ray, out t, trianglePoints[0], trianglePoints[1], trianglePoints[2], _epsilon));
            }
        }
Exemple #3
0
 public override bool Raycast(Ray ray, out float t)
 {
     return(TriangleMath.Raycast(ray, out t, GetPoint(EqTrianglePoint.Left), GetPoint(EqTrianglePoint.Top), GetPoint(EqTrianglePoint.Right), _epsilon));
 }
Exemple #4
0
        public static bool RaycastTriangular(Ray ray, out float t, Vector3 baseCenter,
                                             float baseWidth, float baseDepth, float topWidth, float topDepth, float height, Quaternion prismRotation)
        {
            t = 0.0f;
            if (baseWidth == 0.0f || baseDepth == 0.0f ||
                topWidth == 0.0f || topDepth == 0.0f || height == 0.0f)
            {
                return(false);
            }

            baseWidth = Mathf.Abs(baseWidth);
            baseDepth = Mathf.Abs(baseDepth);
            topWidth  = Mathf.Abs(topWidth);
            topDepth  = Mathf.Abs(topDepth);

            ray = ray.InverseTransform(Matrix4x4.TRS(baseCenter, prismRotation, Vector3.one));

            // Since the raycast calculations can be quite expensive for a prism, we will
            // first check if the ray intersects its AABB to quickly return false if no
            // intersection is found. If the ray does not intersect the AABB it can not
            // possibly intersect the prism.
            Vector3 aabbSize = Vector3.Max(new Vector3(baseWidth, height, baseDepth), new Vector3(topWidth, height, topDepth));

            if (!BoxMath.Raycast(ray, Vector3.up * height * 0.5f, aabbSize, Quaternion.identity))
            {
                return(false);
            }

            List <Vector3> cornerPoints  = CalcTriangPrismCornerPoints(Vector3.zero, baseWidth, baseDepth, topWidth, topDepth, height, Quaternion.identity);
            Vector3        baseLeftPt    = cornerPoints[(int)TriangularPrismCorner.BaseLeft];
            Vector3        baseRightPt   = cornerPoints[(int)TriangularPrismCorner.BaseRight];
            Vector3        baseForwardPt = cornerPoints[(int)TriangularPrismCorner.BaseForward];

            Vector3 topLeftPt    = cornerPoints[(int)TriangularPrismCorner.TopLeft];
            Vector3 topRightPt   = cornerPoints[(int)TriangularPrismCorner.TopRight];
            Vector3 topForwardPt = cornerPoints[(int)TriangularPrismCorner.TopForward];

            List <float> tValues = new List <float>(5);

            // Base triangle
            float rayEnter;

            if (TriangleMath.Raycast(ray, out rayEnter, baseLeftPt, baseRightPt, baseForwardPt))
            {
                tValues.Add(rayEnter);
            }

            // Top triangle
            if (TriangleMath.Raycast(ray, out rayEnter, topLeftPt, topForwardPt, topRightPt))
            {
                tValues.Add(rayEnter);
            }

            // Back face
            List <Vector3> facePoints = new List <Vector3>(4)
            {
                baseLeftPt, topLeftPt, topRightPt, baseRightPt
            };
            Vector3 faceNormal = Vector3.Cross((facePoints[1] - facePoints[0]), facePoints[3] - facePoints[0]).normalized;

            if (PolygonMath.Raycast(ray, out rayEnter, facePoints, false, faceNormal))
            {
                tValues.Add(rayEnter);
            }

            // Left face
            // facePoints[0] = baseLeftPt;
            facePoints[1] = baseForwardPt;
            facePoints[2] = topForwardPt;
            facePoints[3] = topLeftPt;
            faceNormal    = Vector3.Cross((facePoints[1] - facePoints[0]), facePoints[3] - facePoints[0]).normalized;
            if (PolygonMath.Raycast(ray, out rayEnter, facePoints, false, faceNormal))
            {
                tValues.Add(rayEnter);
            }

            // Right face
            facePoints[0] = baseRightPt;
            facePoints[1] = topRightPt;
            // facePoints[2] = topForwardPt;
            facePoints[3] = baseForwardPt;
            faceNormal    = Vector3.Cross((facePoints[1] - facePoints[0]), facePoints[3] - facePoints[0]).normalized;
            if (PolygonMath.Raycast(ray, out rayEnter, facePoints, false, faceNormal))
            {
                tValues.Add(rayEnter);
            }

            if (tValues.Count == 0)
            {
                return(false);
            }

            tValues.Sort(delegate(float t0, float t1) { return(t0.CompareTo(t1)); });
            t = tValues[0];

            return(true);
        }