GetBoundingBox() public method

Gets the bounding box of the shape given a transform.
public GetBoundingBox ( RigidTransform &shapeTransform, BoundingBox &boundingBox ) : void
shapeTransform BEPUutilities.RigidTransform Transform to use.
boundingBox BoundingBox Bounding box of the transformed shape.
return void
Beispiel #1
0
        ///<summary>
        /// Gets the point contributions within a convex shape.
        ///</summary>
        ///<param name="shape">Shape to compute the point contributions of.</param>
        ///<param name="volume">Volume of the shape.</param>
        ///<param name="outputPointContributions">Point contributions of the shape.</param>
        public static void GetPoints(ConvexShape shape, out float volume, RawList<Vector3> outputPointContributions)
        {
            RigidTransform transform = RigidTransform.Identity;
            BoundingBox boundingBox;
            shape.GetBoundingBox(ref transform, out boundingBox);

            //Find the direction which maximizes the possible hits.  Generally, this is the smallest area axis.
            //Possible options are:
            //YZ -> use X
            //XZ -> use Y
            //XY -> use Z
            Ray ray;
            float width = boundingBox.Max.X - boundingBox.Min.X;
            float height = boundingBox.Max.Y - boundingBox.Min.Y;
            float length = boundingBox.Max.Z - boundingBox.Min.Z;
            float yzArea = height * length;
            float xzArea = width * length;
            float xyArea = width * height;
            Vector3 increment1, increment2;
            float incrementMultiplier = 1f / NumberOfSamplesPerDimension;
            float maxLength;
            float rayIncrement;
            if (yzArea > xzArea && yzArea > xyArea)
            {
                //use the x axis as the direction.
                ray.Direction = Vector3.Right;
                ray.Position = new Vector3(boundingBox.Min.X, boundingBox.Min.Y + .5f * incrementMultiplier * height, boundingBox.Min.Z + .5f * incrementMultiplier * length);
                increment1 = new Vector3(0, incrementMultiplier * height, 0);
                increment2 = new Vector3(0, 0, incrementMultiplier * length);
                rayIncrement = incrementMultiplier * width;
                maxLength = width;
            }
            else if (xzArea > xyArea) //yz is not the max, given by the previous if.  Is xz or xy the max?
            {
                //use the y axis as the direction.
                ray.Direction = Vector3.Up;
                ray.Position = new Vector3(boundingBox.Min.X + .5f * incrementMultiplier * width, boundingBox.Min.Y, boundingBox.Min.Z + .5f * incrementMultiplier * length);
                increment1 = new Vector3(incrementMultiplier * width, 0, 0);
                increment2 = new Vector3(0, 0, incrementMultiplier * height);
                rayIncrement = incrementMultiplier * height;
                maxLength = height;
            }
            else
            {
                //use the z axis as the direction.
                ray.Direction = Vector3.Backward;
                ray.Position = new Vector3(boundingBox.Min.X + .5f * incrementMultiplier * width, boundingBox.Min.Y + .5f * incrementMultiplier * height, boundingBox.Min.Z);
                increment1 = new Vector3(incrementMultiplier * width, 0, 0);
                increment2 = new Vector3(0, incrementMultiplier * height, 0);
                rayIncrement = incrementMultiplier * length;
                maxLength = length;
            }


            Ray oppositeRay;
            volume = 0;
            for (int i = 0; i < NumberOfSamplesPerDimension; i++)
            {
                for (int j = 0; j < NumberOfSamplesPerDimension; j++)
                {
                    //Ray cast from one direction.  If it succeeds, try the other way.  This forms an interval in which inertia tensor contributions are contained.
                    RayHit hit;
                    if (shape.RayTest(ref ray, ref transform, maxLength, out hit))
                    {
                        Vector3.Multiply(ref ray.Direction, maxLength, out oppositeRay.Position);
                        Vector3.Add(ref oppositeRay.Position, ref ray.Position, out oppositeRay.Position);
                        Vector3.Negate(ref ray.Direction, out oppositeRay.Direction);
                        RayHit oppositeHit;
                        if (shape.RayTest(ref oppositeRay, ref transform, maxLength, out oppositeHit))
                        {
                            //It should always get here if one direction casts, but there may be numerical issues.
                            float scanVolume;
                            ScanObject(rayIncrement, maxLength, ref increment1, ref increment2, ref ray, ref hit, ref oppositeHit, outputPointContributions, out scanVolume);
                            volume += scanVolume;
                        }
                    }
                    Vector3.Add(ref ray.Position, ref increment2, out ray.Position);
                }
                Vector3.Add(ref ray.Position, ref increment1, out ray.Position);
                //Move the ray back to the starting position along the other axis.
                Vector3 subtract;
                Vector3.Multiply(ref increment2, NumberOfSamplesPerDimension, out subtract);
                Vector3.Subtract(ref ray.Position, ref subtract, out ray.Position);
            }


        }
Beispiel #2
0
        /// <summary>
        /// Computes a bounding box and expands it.
        /// </summary>
        /// <param name="shape">Shape to compute the bounding box of.</param>
        /// <param name="transform">Transform to use to position the shape.</param>
        /// <param name="sweep">Extra to add to the bounding box.</param>
        /// <param name="boundingBox">Expanded bounding box.</param>
        public static void GetExpandedBoundingBox(ref ConvexShape shape, ref RigidTransform transform, ref Vector3 sweep, out BoundingBox boundingBox)
        {
            shape.GetBoundingBox(ref transform, out boundingBox);
            ExpandBoundingBox(ref boundingBox, ref sweep);

        }
Beispiel #3
0
        ///<summary>
        /// Gets the point contributions within a convex shape.
        ///</summary>
        ///<param name="shape">Shape to compute the point contributions of.</param>
        ///<param name="volume">Volume of the shape.</param>
        ///<param name="outputPointContributions">Point contributions of the shape.</param>
        public static void GetPoints(ConvexShape shape, out float volume, RawList <Vector3> outputPointContributions)
        {
            RigidTransform transform = RigidTransform.Identity;
            BoundingBox    boundingBox;

            shape.GetBoundingBox(ref transform, out boundingBox);

            //Find the direction which maximizes the possible hits.  Generally, this is the smallest area axis.
            //Possible options are:
            //YZ -> use X
            //XZ -> use Y
            //XY -> use Z
            Ray     ray;
            float   width = boundingBox.Max.X - boundingBox.Min.X;
            float   height = boundingBox.Max.Y - boundingBox.Min.Y;
            float   length = boundingBox.Max.Z - boundingBox.Min.Z;
            float   yzArea = height * length;
            float   xzArea = width * length;
            float   xyArea = width * height;
            Vector3 increment1, increment2;
            float   incrementMultiplier = 1f / NumberOfSamplesPerDimension;
            float   maxLength;
            float   rayIncrement;

            if (yzArea > xzArea && yzArea > xyArea)
            {
                //use the x axis as the direction.
                ray.Direction = Vector3.Right;
                ray.Position  = new Vector3(boundingBox.Min.X, boundingBox.Min.Y + .5f * incrementMultiplier * height, boundingBox.Min.Z + .5f * incrementMultiplier * length);
                increment1    = new Vector3(0, incrementMultiplier * height, 0);
                increment2    = new Vector3(0, 0, incrementMultiplier * length);
                rayIncrement  = incrementMultiplier * width;
                maxLength     = width;
            }
            else if (xzArea > xyArea) //yz is not the max, given by the previous if.  Is xz or xy the max?
            {
                //use the y axis as the direction.
                ray.Direction = Vector3.Up;
                ray.Position  = new Vector3(boundingBox.Min.X + .5f * incrementMultiplier * width, boundingBox.Min.Y, boundingBox.Min.Z + .5f * incrementMultiplier * length);
                increment1    = new Vector3(incrementMultiplier * width, 0, 0);
                increment2    = new Vector3(0, 0, incrementMultiplier * height);
                rayIncrement  = incrementMultiplier * height;
                maxLength     = height;
            }
            else
            {
                //use the z axis as the direction.
                ray.Direction = Vector3.Backward;
                ray.Position  = new Vector3(boundingBox.Min.X + .5f * incrementMultiplier * width, boundingBox.Min.Y + .5f * incrementMultiplier * height, boundingBox.Min.Z);
                increment1    = new Vector3(incrementMultiplier * width, 0, 0);
                increment2    = new Vector3(0, incrementMultiplier * height, 0);
                rayIncrement  = incrementMultiplier * length;
                maxLength     = length;
            }


            Ray oppositeRay;

            volume = 0;
            for (int i = 0; i < NumberOfSamplesPerDimension; i++)
            {
                for (int j = 0; j < NumberOfSamplesPerDimension; j++)
                {
                    //Ray cast from one direction.  If it succeeds, try the other way.  This forms an interval in which inertia tensor contributions are contained.
                    RayHit hit;
                    if (shape.RayTest(ref ray, ref transform, maxLength, out hit))
                    {
                        Vector3.Multiply(ref ray.Direction, maxLength, out oppositeRay.Position);
                        Vector3.Add(ref oppositeRay.Position, ref ray.Position, out oppositeRay.Position);
                        Vector3.Negate(ref ray.Direction, out oppositeRay.Direction);
                        RayHit oppositeHit;
                        if (shape.RayTest(ref oppositeRay, ref transform, maxLength, out oppositeHit))
                        {
                            //It should always get here if one direction casts, but there may be numerical issues.
                            float scanVolume;
                            ScanObject(rayIncrement, maxLength, ref increment1, ref increment2, ref ray, ref hit, ref oppositeHit, outputPointContributions, out scanVolume);
                            volume += scanVolume;
                        }
                    }
                    Vector3.Add(ref ray.Position, ref increment2, out ray.Position);
                }
                Vector3.Add(ref ray.Position, ref increment1, out ray.Position);
                //Move the ray back to the starting position along the other axis.
                Vector3 subtract;
                Vector3.Multiply(ref increment2, NumberOfSamplesPerDimension, out subtract);
                Vector3.Subtract(ref ray.Position, ref subtract, out ray.Position);
            }
        }
Beispiel #4
0
 public bool ConvexCast(ConvexShape castShape, ref RigidTransform startingTransform, ref Vector3 sweepnorm, double slen, MaterialSolidity solidness, out RayHit hit)
 {
     BoundingBox bb;
     RigidTransform rot = new RigidTransform(Vector3.Zero, startingTransform.Orientation);
     castShape.GetBoundingBox(ref rot, out bb);
     double adv = 0.1f;
     double max = slen + adv;
     bool gotOne = false;
     RayHit BestRH = default(RayHit);
     Vector3 sweep = sweepnorm * slen;
     for (double f = 0; f < max; f += adv)
     {
         Vector3 c = startingTransform.Position + sweepnorm * f;
         int mx = (int)Math.Ceiling(c.X + bb.Max.X);
         for (int x = (int)Math.Floor(c.X + bb.Min.X); x <= mx; x++)
         {
             if (x < 0 || x >= ChunkSize.X)
             {
                 continue;
             }
             int my = (int)Math.Ceiling(c.Y + bb.Max.Y);
             for (int y = (int)Math.Floor(c.Y + bb.Min.Y); y <= my; y++)
             {
                 if (y < 0 || y >= ChunkSize.Y)
                 {
                     continue;
                 }
                 int mz = (int)Math.Ceiling(c.Z + bb.Max.Z);
                 for (int z = (int)Math.Floor(c.Z + bb.Min.Z); z <= mz; z++)
                 {
                     if (z < 0 || z >= ChunkSize.Z)
                     {
                         continue;
                     }
                     BlockInternal bi = Blocks[BlockIndex(x, y, z)];
                     if (solidness.HasFlag(((Material)bi.BlockMaterial).GetSolidity()))
                     {
                         Location offs;
                         EntityShape es = BlockShapeRegistry.BSD[bi.BlockData].GetShape(bi.Damage, out offs, false);
                         if (es == null)
                         {
                             continue;
                         }
                         Vector3 adj = new Vector3(x + (double)offs.X, y + (double)offs.Y, z + (double)offs.Z);
                         EntityCollidable coll = es.GetCollidableInstance();
                         //coll.LocalPosition = adj;
                         RigidTransform rt = new RigidTransform(Vector3.Zero, Quaternion.Identity);
                         coll.LocalPosition = Vector3.Zero;
                         coll.WorldTransform = rt;
                         coll.UpdateBoundingBoxForTransform(ref rt);
                         RayHit rhit;
                         RigidTransform adjusted = new RigidTransform(startingTransform.Position - adj, startingTransform.Orientation);
                         bool b = coll.ConvexCast(castShape, ref adjusted, ref sweep, out rhit);
                         if (b && (!gotOne || rhit.T * slen < BestRH.T) && rhit.T >= 0)
                         {
                             gotOne = true;
                             BestRH = rhit;
                             BestRH.Location += adj;
                             BestRH.T *= slen; // TODO: ???
                             BestRH.Normal = -BestRH.Normal; // TODO: WHY?!
                         }
                     }
                 }
             }
         }
         if (gotOne)
         {
             hit = BestRH;
             return true;
         }
     }
     hit = new RayHit() { Location = startingTransform.Position + sweep, Normal = new Vector3(0, 0, 0), T = slen };
     return false;
 }