private void EnsureObjectAboveGround()
        {
            //check our bounding box. if it is below ground, provide a
            //z+ adjustment to our position to move it out

            //the height of ALL the terrain below our bounding box must be checked
            //to find the highest peak. quantize to the nearest meter since we don't
            //actually need to have the slope calculations performed
            int   yCoordMin      = (int)Math.Floor(_actor.WorldBounds.Center.Y - _actor.WorldBounds.Extents.Y);
            int   yCoordMax      = (int)Math.Ceiling(_actor.WorldBounds.Center.Y + _actor.WorldBounds.Extents.Y);
            int   xCoordMin      = (int)Math.Floor(_actor.WorldBounds.Center.X - _actor.WorldBounds.Extents.X);
            int   xCoordMax      = (int)Math.Ceiling(_actor.WorldBounds.Center.X + _actor.WorldBounds.Extents.X);
            float maxHeightFound = -100.0f;

            for (int x = xCoordMin; x <= xCoordMax; x++)
            {
                for (int y = yCoordMin; y <= yCoordMax; y++)
                {
                    maxHeightFound = Math.Max(maxHeightFound, (float)_scene.TerrainChannel[x, y]);
                }
            }

            if (_position.Z - _actor.WorldBounds.Extents.Z <= maxHeightFound)
            {
                _position.Z          = maxHeightFound + _actor.WorldBounds.Extents.Z + 0.1f;
                _dynActor.GlobalPose = PhysUtil.PositionToMatrix(_position, _rotation);
            }
        }
        private void RunDepenetrateCycle(ref float pushFactor, ref bool foundOverlap, ref bool foundCriticalOverlap)
        {
            const int MAX_ITERATIONS = 6;
            const int MAX_OVERLAPS   = 32;

            OpenMetaverse.Vector3 offset = OpenMetaverse.Vector3.Zero;

            int iterOverlaps = 0;

            for (int i = 0; i < MAX_ITERATIONS; i++)
            {
                iterOverlaps         = 0;
                foundOverlap         = false;
                foundCriticalOverlap = false;
                foreach (var shape in _shapeToPrimIndex.Keys)
                {
                    OpenMetaverse.Vector3 translatedPose = PhysUtil.DecomposeToPosition(shape.GlobalPose) + offset;
                    PhysX.Shape[]         overlapping    = _scene.SceneImpl.OverlapMultiple(shape.Geom, PhysUtil.PositionToMatrix(translatedPose, _rotation));

                    if (overlapping == null)
                    {
                        //the overlap is too deep, instant fail
                        foundOverlap         = true;
                        foundCriticalOverlap = true;
                        return;
                    }

                    foreach (var oshape in overlapping)
                    {
                        if (oshape != null && oshape.Actor.UserData != this)
                        {
                            iterOverlaps++;
                            foundOverlap = true;
                            if (iterOverlaps > MAX_OVERLAPS)
                            {
                                foundCriticalOverlap = true;
                                break;
                            }
                        }
                    }

                    if (iterOverlaps > MAX_OVERLAPS)
                    {
                        break;
                    }
                }

                if (iterOverlaps > 0 && i + 1 < MAX_ITERATIONS)
                {
                    offset     += new OpenMetaverse.Vector3(0f, 0f, pushFactor);
                    pushFactor *= 2.0f;
                }
                else
                {
                    break;
                }
            }

            if (iterOverlaps == 0 && offset != OpenMetaverse.Vector3.Zero)
            {
                _dynActor.GlobalPose = PhysUtil.PositionToMatrix(_position + offset, _rotation);
                _position            = _position + offset;
                foundOverlap         = false;
            }
            else if (iterOverlaps == 0 && offset == OpenMetaverse.Vector3.Zero)
            {
                foundOverlap = false;
            }
            else if (iterOverlaps < MAX_OVERLAPS)
            {
                foundOverlap         = true;
                foundCriticalOverlap = false;
            }
            else
            {
                foundOverlap         = true;
                foundCriticalOverlap = true;
            }
        }