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; } }