예제 #1
0
        public bool Raycast(FRay ray, out float hitDistance, bool returnFirstHit = false)
        {
            // Raycast against the bounding box of the entire mesh first to see if we can save ourself a bunch of time.
            bool hitsAABB = WMath.RayIntersectsAABB(ray, BoundingBox.Min, BoundingBox.Max, out hitDistance);

            if (!hitsAABB)
            {
                return(false);
            }

            // Okay, they've intersected with our big bounding box, so now we'll trace against individual mesh bounding box.
            // However, if they've applied skinning data to the meshes then these bounding boxes are no longer valid, so this
            // optimization step only counts if they're not applying any skinning.
            bool canSkipShapeTriangles = m_currentBoneAnimation == null;
            bool rayDidHit             = false;

            foreach (var shape in SHP1Tag.Shapes)
            {
                if (canSkipShapeTriangles)
                {
                    hitsAABB = WMath.RayIntersectsAABB(ray, shape.BoundingBox.Min, shape.BoundingBox.Max, out hitDistance);

                    // If we didn't intersect with this shape, just go onto the next one.
                    if (!hitsAABB)
                    {
                        continue;
                    }
                }

                // We either intersected with this shape's AABB or they have skinning data applied (and thus we can't skip it),
                // thus, we're going to test against every (skinned!) triangle in this shape.
                bool hitTriangle = false;
                var  vertexList  = shape.OverrideVertPos.Count > 0 ? shape.OverrideVertPos : shape.VertexData.Position;

                for (int i = 0; i < shape.Indexes.Count; i += 3)
                {
                    float triHitDist;
                    hitTriangle = WMath.RayIntersectsTriangle(ray, vertexList[shape.Indexes[i]], vertexList[shape.Indexes[i + 1]], vertexList[shape.Indexes[i + 2]], true, out triHitDist);

                    // If we hit this triangle and we're OK to just return the first hit on the model, then we can early out.
                    if (hitTriangle && returnFirstHit)
                    {
                        hitDistance = triHitDist;
                        return(true);
                    }

                    // Otherwise, we need to test to see if this hit is closer than the previous hit.
                    if (hitTriangle)
                    {
                        if (triHitDist < hitDistance)
                        {
                            hitDistance = triHitDist;
                        }
                        rayDidHit = true;
                    }
                }
            }

            return(rayDidHit);
        }
예제 #2
0
        public bool Raycast(FRay ray, out float hitDistance, bool returnFirstHit = false)
        {
            // Raycast against the bounding box of the entire mesh first to see if we can save ourself a bunch of time.
            bool hitsAABB = WMath.RayIntersectsAABB(ray, BoundingBox.Min, BoundingBox.Max, out hitDistance);

            if (!hitsAABB)
            {
                return(false);
            }

            // Okay, they've intersected with our big bounding box, so now we'll trace against individual mesh bounding box.
            // However, if they've applied skinning data to the meshes then these bounding boxes are no longer valid, so this
            // optimization step only counts if they're not applying any skinning.
            bool canSkipShapeTriangles = m_currentBoneAnimation == null;
            bool rayDidHit             = false;

            foreach (var shape in SHP1Tag.Shapes)
            {
                if (canSkipShapeTriangles)
                {
                    hitsAABB = WMath.RayIntersectsAABB(ray, shape.BoundingBox.Min, shape.BoundingBox.Max, out hitDistance);

                    // If we didn't intersect with this shape, just go onto the next one.
                    if (!hitsAABB)
                    {
                        continue;
                    }
                }

                // We either intersected with this shape's AABB or they have skinning data applied (and thus we can't skip it),
                // thus, we're going to test against every (skinned!) triangle in this shape.
                bool hitTriangle = false;

                /*foreach (SHP1.Packet pak in shape.MatrixGroups)
                 * {
                 *  List<Vector3> vertexList = new List<Vector3>();
                 *
                 *  for (int i = 0; i < pak.Indexes.Count; i++)
                 *  {
                 *      Matrix4 cur_mat = DRW1Tag.Matrices[pak.MatrixDataTable.MatrixTable[pak.VertexData.PositionMatrixIndexes[i]]];
                 *      vertexList.Add(Vector3.Transform(pak.VertexData.Position[i], cur_mat));
                 *  }
                 *
                 *  for (int i = 0; i < pak.Indexes.Count; i += 3)
                 *  {
                 *      float triHitDist;
                 *      hitTriangle = WMath.RayIntersectsTriangle(ray, vertexList[pak.Indexes[i]], vertexList[pak.Indexes[i + 1]], vertexList[pak.Indexes[i + 2]], true, out triHitDist);
                 *
                 *      // If we hit this triangle and we're OK to just return the first hit on the model, then we can early out.
                 *      if (hitTriangle && returnFirstHit)
                 *      {
                 *          hitDistance = triHitDist;
                 *          Console.WriteLine($"{Name}:{hitDistance}");
                 *          return true;
                 *      }
                 *
                 *      // Otherwise, we need to test to see if this hit is closer than the previous hit.
                 *      if (hitTriangle)
                 *      {
                 *          if (triHitDist < hitDistance)
                 *              hitDistance = triHitDist;
                 *          rayDidHit = true;
                 *      }
                 *  }
                 * }*/
            }

            return(rayDidHit);
        }