diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 7d886048fc..d206fc1278 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -1866,6 +1866,12 @@ namespace OpenSim.Framework /// Prints the call stack at any given point. Useful for debugging. /// public static void PrintCallStack() + { + PrintCallStack(m_log.DebugFormat); + } + + public delegate void DebugPrinter(string msg, params Object[] parm); + public static void PrintCallStack(DebugPrinter printer) { StackTrace stackTrace = new StackTrace(true); // get call stack StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames) @@ -1874,7 +1880,7 @@ namespace OpenSim.Framework foreach (StackFrame stackFrame in stackFrames) { MethodBase mb = stackFrame.GetMethod(); - m_log.DebugFormat("{0}.{1}:{2}", mb.DeclaringType, mb.Name, stackFrame.GetFileLineNumber()); // write method name + printer("{0}.{1}:{2}", mb.DeclaringType, mb.Name, stackFrame.GetFileLineNumber()); // write method name } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index b9f9c86cd1..bc62d51e0e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -505,11 +505,19 @@ namespace OpenSim.Region.Framework.Scenes if (Scene != null) { - // if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W) - // || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S)) - // && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) - if ((Scene.TestBorderCross(val, Cardinals.E) || Scene.TestBorderCross(val, Cardinals.W) - || Scene.TestBorderCross(val, Cardinals.N) || Scene.TestBorderCross(val, Cardinals.S)) + if ( + // (Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) + // || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W) + // || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) + // || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S)) + // Experimental change for better border crossings. + // The commented out original lines above would, it seems, trigger + // a border crossing a little early or late depending on which + // direction the object was moving. + (Scene.TestBorderCross(val, Cardinals.E) + || Scene.TestBorderCross(val, Cardinals.W) + || Scene.TestBorderCross(val, Cardinals.N) + || Scene.TestBorderCross(val, Cardinals.S)) && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) { IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface(); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 0defb24f76..4dd6264339 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -311,6 +311,15 @@ public sealed class BSCharacter : BSPhysObject { bool ret = false; + // TODO: check for out of bounds + if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(_position)) + { + // The character is out of the known/simulated area. + // Upper levels of code will handle the transition to other areas so, for + // the time, we just ignore the position. + return ret; + } + // If below the ground, move the avatar up float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); if (Position.Z < terrainHeight) @@ -329,7 +338,6 @@ public sealed class BSCharacter : BSPhysObject } } - // TODO: check for out of bounds return ret; } @@ -700,7 +708,7 @@ public sealed class BSCharacter : BSPhysObject } // Tell the linkset about value changes - Linkset.UpdateProperties(this); + Linkset.UpdateProperties(this, true); // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. // base.RequestPhysicsterseUpdate(); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 82e829e700..ef68471a29 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -871,8 +871,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin if (VehiclePosition.Z < GetTerrainHeight(VehiclePosition)) { // TODO: correct position by applying force rather than forcing position. - VehiclePosition += new Vector3(0f, 0f, GetTerrainHeight(VehiclePosition) + 2f); - VDetailLog("{0}, MoveLinear,terrainHeight,terrainHeight={1},pos={2}", Prim.LocalID, GetTerrainHeight(VehiclePosition), VehiclePosition); + Vector3 newPosition = VehiclePosition; + newPosition.Z = GetTerrainHeight(VehiclePosition) + 1f; + VehiclePosition = newPosition; + VDetailLog("{0}, MoveLinear,terrainHeight,terrainHeight={1},pos={2}", + Prim.LocalID, GetTerrainHeight(VehiclePosition), VehiclePosition); } return ret; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index ce0fbe6c91..2017fa5656 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -38,6 +38,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Each type of linkset will define the information needed for its type. public abstract class BSLinksetInfo { + public virtual void Clear() { } } public abstract class BSLinkset @@ -95,13 +96,6 @@ public abstract class BSLinkset return BSPhysicsShapeType.SHAPE_UNKNOWN; } - // Linksets move around the children so the linkset might need to compute the child position - public virtual OMV.Vector3 Position(BSPhysObject member) - { return member.RawPosition; } - public virtual OMV.Quaternion Orientation(BSPhysObject member) - { return member.RawOrientation; } - // TODO: does this need to be done for Velocity and RotationalVelocityy? - // We keep the prim's mass in the linkset structure since it could be dependent on other prims protected float m_mass; public float LinksetMass @@ -258,8 +252,9 @@ public abstract class BSLinkset // Called when a parameter update comes from the physics engine for any object // of the linkset is received. + // Passed flag is update came from physics engine (true) or the user (false). // Called at taint-time!! - public abstract void UpdateProperties(BSPhysObject physObject); + public abstract void UpdateProperties(BSPhysObject physObject, bool physicalUpdate); // Routine used when rebuilding the body of the root of the linkset // Destroy all the constraints have have been made to root. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index 2189468e17..4d4f7123bc 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -28,6 +28,8 @@ using System; using System.Collections.Generic; using System.Text; +using OpenSim.Framework; + using OMV = OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin @@ -45,6 +47,11 @@ sealed class BSLinksetCompoundInfo : BSLinksetInfo OffsetPos = p; OffsetRot = r; } + public override void Clear() + { + OffsetPos = OMV.Vector3.Zero; + OffsetRot = OMV.Quaternion.Identity; + } public override string ToString() { StringBuilder buff = new StringBuilder(); @@ -82,22 +89,22 @@ public sealed class BSLinksetCompound : BSLinkset // its internal properties. public override void Refresh(BSPhysObject requestor) { - // External request for Refresh (from BSPrim) doesn't need to do anything - // InternalRefresh(requestor); + // Something changed so do the rebuilding thing + // ScheduleRebuild(); } // Schedule a refresh to happen after all the other taint processing. - private void InternalRefresh(BSPhysObject requestor) + private void ScheduleRebuild() { - DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1},rebuilding={2}", - LinksetRoot.LocalID, requestor.LocalID, Rebuilding); + DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,rebuilding={1}", + LinksetRoot.LocalID, Rebuilding); // When rebuilding, it is possible to set properties that would normally require a rebuild. // If already rebuilding, don't request another rebuild. if (!Rebuilding) { - PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate() + PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", LinksetRoot.LocalID, delegate() { - if (IsRoot(requestor) && HasAnyChildren) + if (HasAnyChildren) RecomputeLinksetCompound(); }); } @@ -117,8 +124,7 @@ public sealed class BSLinksetCompound : BSLinkset { // The root is going dynamic. Make sure mass is properly set. m_mass = ComputeLinksetMass(); - if (HasAnyChildren) - InternalRefresh(LinksetRoot); + ScheduleRebuild(); } else { @@ -147,8 +153,7 @@ public sealed class BSLinksetCompound : BSLinkset DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child)); if (IsRoot(child)) { - if (HasAnyChildren) - InternalRefresh(LinksetRoot); + ScheduleRebuild(); } else { @@ -164,22 +169,21 @@ public sealed class BSLinksetCompound : BSLinkset return ret; } - // Called at taint-time!! - public override void UpdateProperties(BSPhysObject updated) + public override void UpdateProperties(BSPhysObject updated, bool physicalUpdate) { - // Nothing to do for compound linksets on property updates - } - - // The children move around in relationship to the root. - // Just grab the current values of wherever it is right now. - public override OMV.Vector3 Position(BSPhysObject member) - { - return BulletSimAPI.GetPosition2(member.PhysBody.ptr); - } - - public override OMV.Quaternion Orientation(BSPhysObject member) - { - return BulletSimAPI.GetOrientation2(member.PhysBody.ptr); + // The user moving a child around requires the rebuilding of the linkset compound shape + // One problem is this happens when a border is crossed -- the simulator implementation + // is to store the position into the group which causes the move of the object + // but it also means all the child positions get updated. + // What would cause an unnecessary rebuild so we make sure the linkset is in a + // region before bothering to do a rebuild. + if (!IsRoot(updated) + && !physicalUpdate + && PhysicsScene.TerrainManager.IsWithinKnownTerrain(LinksetRoot.RawPosition)) + { + updated.LinksetInfo = null; + ScheduleRebuild(); + } } // Routine called when rebuilding the body of some member of the linkset. @@ -261,8 +265,8 @@ public sealed class BSLinksetCompound : BSLinkset DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); - // Cause constraints and assorted properties to be recomputed before the next simulation step. - InternalRefresh(LinksetRoot); + // Rebuild the compound shape with the new child shape included + ScheduleRebuild(); } return; } @@ -289,8 +293,8 @@ public sealed class BSLinksetCompound : BSLinkset } else { - // Schedule a rebuild of the linkset before the next simulation tick. - InternalRefresh(LinksetRoot); + // Rebuild the compound shape with the child removed + ScheduleRebuild(); } } return; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index 732c0848b7..8c36c3153a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -78,23 +78,11 @@ public sealed class BSLinksetConstraints : BSLinkset } // Called at taint-time!! - public override void UpdateProperties(BSPhysObject updated) + public override void UpdateProperties(BSPhysObject updated, bool inTaintTime) { // Nothing to do for constraints on property updates } - // The children of the linkset are moved around by the constraints. - // Just grab the current values of wherever it is right now. - public override OMV.Vector3 Position(BSPhysObject member) - { - return BulletSimAPI.GetPosition2(member.PhysBody.ptr); - } - - public override OMV.Quaternion Orientation(BSPhysObject member) - { - return BulletSimAPI.GetOrientation2(member.PhysBody.ptr); - } - // Routine called when rebuilding the body of some member of the linkset. // Destroy all the constraints have have been made to root and set // up to rebuild the constraints before the next simulation step. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 6539b43156..92a5f2f054 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -214,7 +214,7 @@ public abstract class BSPhysObject : PhysicsActor { bool ret = true; // If the 'no collision' call, force it to happen right now so quick collision_end - bool force = CollisionCollection.Count == 0; + bool force = (CollisionCollection.Count == 0); // throttle the collisions to the number of milliseconds specified in the subscription if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime)) @@ -232,8 +232,10 @@ public abstract class BSPhysObject : PhysicsActor // DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count); base.SendCollisionUpdate(CollisionCollection); - // The collisionCollection structure is passed around in the simulator. + // The CollisionCollection instance is passed around in the simulator. // Make sure we don't have a handle to that one and that a new one is used for next time. + // This fixes an interesting 'gotcha'. If we call CollisionCollection.Clear() here, + // a race condition is created for the other users of this instance. CollisionCollection = new CollisionEventUpdate(); } return ret; @@ -251,7 +253,8 @@ public abstract class BSPhysObject : PhysicsActor PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate() { - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + if (PhysBody.HasPhysicalBody) + CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); }); } else diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index c9c9c2cc10..758d92bd0f 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -279,9 +279,12 @@ public sealed class BSPrim : BSPhysObject } public override OMV.Vector3 Position { get { + /* NOTE: this refetch is not necessary. The simulator knows about linkset children + * and does not fetch this position info for children. Thus this is commented out. // child prims move around based on their parent. Need to get the latest location if (!Linkset.IsRoot(this)) - _position = Linkset.Position(this); + _position = Linkset.PositionGet(this); + */ // don't do the GetObjectPosition for root elements because this function is called a zillion times. // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); @@ -289,21 +292,22 @@ public sealed class BSPrim : BSPhysObject } set { // If the position must be forced into the physics engine, use ForcePosition. + // All positions are given in world positions. if (_position == value) { + DetailLog("{0},BSPrim.setPosition,taint,positionNotChanging,pos={1},orient={2}", LocalID, _position, _orientation); return; } _position = value; - // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? PositionSanityCheck(false); + + // A linkset might need to know if a component information changed. + Linkset.UpdateProperties(this, false); + PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() { - // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); - if (PhysBody.HasPhysicalBody) - { - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - ActivateIfPhysical(false); - } + DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); + ForcePosition = _position; }); } } @@ -314,9 +318,11 @@ public sealed class BSPrim : BSPhysObject } set { _position = value; - // PositionSanityCheck(); // Don't do this! Causes a loop and caller should know better. - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - ActivateIfPhysical(false); + if (PhysBody.HasPhysicalBody) + { + BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); + ActivateIfPhysical(false); + } } } @@ -327,6 +333,14 @@ public sealed class BSPrim : BSPhysObject { bool ret = false; + if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(_position)) + { + // The physical object is out of the known/simulated area. + // Upper levels of code will handle the transition to other areas so, for + // the time, we just ignore the position. + return ret; + } + float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); OMV.Vector3 upForce = OMV.Vector3.Zero; if (RawPosition.Z < terrainHeight) @@ -350,8 +364,6 @@ public sealed class BSPrim : BSPhysObject } } - // TODO: check for out of bounds - // The above code computes a force to apply to correct any out-of-bounds problems. Apply same. // TODO: This should be intergrated with a geneal physics action mechanism. // TODO: This should be moderated with PID'ness. @@ -551,18 +563,24 @@ public sealed class BSPrim : BSPhysObject } public override OMV.Quaternion Orientation { get { + /* NOTE: this refetch is not necessary. The simulator knows about linkset children + * and does not fetch this position info for children. Thus this is commented out. // Children move around because tied to parent. Get a fresh value. if (!Linkset.IsRoot(this)) { - _orientation = Linkset.Orientation(this); + _orientation = Linkset.OrientationGet(this); } + */ return _orientation; } set { if (_orientation == value) return; _orientation = value; - // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? + + // A linkset might need to know if a component information changed. + Linkset.UpdateProperties(this, false); + PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() { if (PhysBody.HasPhysicalBody) @@ -1427,14 +1445,14 @@ public sealed class BSPrim : BSPhysObject entprop.Velocity = _velocity; } - // remember the current and last set values - LastEntityProperties = CurrentEntityProperties; - CurrentEntityProperties = entprop; - OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; // DEBUG DEBUG DEBUG DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}", LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity); + // remember the current and last set values + LastEntityProperties = CurrentEntityProperties; + CurrentEntityProperties = entprop; + base.RequestPhysicsterseUpdate(); } /* @@ -1448,7 +1466,7 @@ public sealed class BSPrim : BSPhysObject */ // The linkset implimentation might want to know about this. - Linkset.UpdateProperties(this); + Linkset.UpdateProperties(this, true); } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index cf5bb57c17..7b44574c69 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -349,8 +349,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // make sure no stepping happens while we're deleting stuff m_initialized = false; - TerrainManager.ReleaseGroundPlaneAndTerrain(); - foreach (KeyValuePair kvp in PhysObjects) { kvp.Value.Destroy(); @@ -370,6 +368,13 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters Shapes = null; } + if (TerrainManager != null) + { + TerrainManager.ReleaseGroundPlaneAndTerrain(); + TerrainManager.Dispose(); + TerrainManager = null; + } + // Anything left in the unmanaged code should be cleaned out BulletSimAPI.Shutdown2(World.ptr); @@ -512,8 +517,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); - DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}", - DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount); + DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}, objWColl={7}", + DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, + updatedEntityCount, collidersCount, ObjectsWithCollisions.Count); if (VehiclePhysicalLoggingEnabled) DumpVehicles(); // DEBUG } catch (Exception e) @@ -568,6 +574,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // Objects that are done colliding are removed from the ObjectsWithCollisions list. // Not done above because it is inside an iteration of ObjectWithCollisions. + // This complex collision processing is required to create an empty collision + // event call after all collisions have happened on an object. This enables + // the simulator to generate the 'collision end' event. if (ObjectsWithNoMoreCollisions.Count > 0) { foreach (BSPhysObject po in ObjectsWithNoMoreCollisions) @@ -592,7 +601,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters ProcessPostStepTaints(); - // This causes the unmanaged code to output ALL the values found in ALL the objects in the world. + // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world. // Only enable this in a limited test world with few objects. // BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 5dbd8ce6cf..3428b9c0fa 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -67,7 +67,7 @@ public abstract class BSTerrainPhys : IDisposable } // ========================================================================================== -public sealed class BSTerrainManager +public sealed class BSTerrainManager : IDisposable { static string LogHeader = "[BULLETSIM TERRAIN MANAGER]"; @@ -122,6 +122,11 @@ public sealed class BSTerrainManager MegaRegionParentPhysicsScene = null; } + public void Dispose() + { + ReleaseGroundPlaneAndTerrain(); + } + // Create the initial instance of terrain and the underlying ground plane. // This is called from the initialization routine so we presume it is // safe to call Bullet in real time. We hope no one is moving prims around yet. @@ -327,6 +332,13 @@ public sealed class BSTerrainManager return newTerrainPhys; } + // Return 'true' of this position is somewhere in known physical terrain space + public bool IsWithinKnownTerrain(Vector3 pos) + { + Vector3 terrainBaseXYZ; + BSTerrainPhys physTerrain; + return GetTerrainPhysicalAtXYZ(pos, out physTerrain, out terrainBaseXYZ); + } // Given an X and Y, find the height of the terrain. // Since we could be handling multiple terrains for a mega-region, @@ -337,13 +349,13 @@ public sealed class BSTerrainManager private float lastHeightTX = 999999f; private float lastHeightTY = 999999f; private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT; - public float GetTerrainHeightAtXYZ(Vector3 loc) + public float GetTerrainHeightAtXYZ(Vector3 pos) { - float tX = loc.X; - float tY = loc.Y; + float tX = pos.X; + float tY = pos.Y; // You'd be surprized at the number of times this routine is called // with the same parameters as last time. - if (!m_terrainModified && lastHeightTX == tX && lastHeightTY == tY) + if (!m_terrainModified && (lastHeightTX == tX) && (lastHeightTY == tY)) return lastHeight; m_terrainModified = false; @@ -351,23 +363,20 @@ public sealed class BSTerrainManager lastHeightTY = tY; float ret = HEIGHT_GETHEIGHT_RET; - int offsetX = ((int)(tX / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X; - int offsetY = ((int)(tY / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y; - Vector3 terrainBaseXYZ = new Vector3(offsetX, offsetY, 0f); - - lock (m_terrains) + Vector3 terrainBaseXYZ; + BSTerrainPhys physTerrain; + if (GetTerrainPhysicalAtXYZ(pos, out physTerrain, out terrainBaseXYZ)) { - BSTerrainPhys physTerrain; - if (m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain)) - { - ret = physTerrain.GetTerrainHeightAtXYZ(loc - terrainBaseXYZ); - } - else - { - PhysicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}", - LogHeader, PhysicsScene.RegionName, tX, tY); - } + ret = physTerrain.GetTerrainHeightAtXYZ(pos - terrainBaseXYZ); } + else + { + PhysicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}", + LogHeader, PhysicsScene.RegionName, tX, tY); + DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXYZ,terrainNotFound,pos={1},base={2}", + BSScene.DetailLogZero, pos, terrainBaseXYZ); + } + lastHeight = ret; return ret; } @@ -376,29 +385,38 @@ public sealed class BSTerrainManager { float ret = WATER_HEIGHT_GETHEIGHT_RET; - float tX = pos.X; - float tY = pos.Y; - - Vector3 terrainBaseXYZ = Vector3.Zero; - terrainBaseXYZ.X = ((int)(tX / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X; - terrainBaseXYZ.Y = ((int)(tY / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y; - - lock (m_terrains) + Vector3 terrainBaseXYZ; + BSTerrainPhys physTerrain; + if (GetTerrainPhysicalAtXYZ(pos, out physTerrain, out terrainBaseXYZ)) { - BSTerrainPhys physTerrain; - if (m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain)) - { - ret = physTerrain.GetWaterLevelAtXYZ(pos); - } - else - { - PhysicsScene.Logger.ErrorFormat("{0} GetWaterHeightAtXY: terrain not found: region={1}, x={2}, y={3}", - LogHeader, PhysicsScene.RegionName, tX, tY); - } + ret = physTerrain.GetWaterLevelAtXYZ(pos); + } + else + { + PhysicsScene.Logger.ErrorFormat("{0} GetWaterHeightAtXY: terrain not found: pos={1}, terrainBase={2}, height={3}", + LogHeader, PhysicsScene.RegionName, pos, terrainBaseXYZ, ret); } return ret; } + // Given an address, return 'true' of there is a description of that terrain and output + // the descriptor class and the 'base' fo the addresses therein. + private bool GetTerrainPhysicalAtXYZ(Vector3 pos, out BSTerrainPhys outPhysTerrain, out Vector3 outTerrainBase) + { + int offsetX = ((int)(pos.X / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X; + int offsetY = ((int)(pos.Y / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y; + Vector3 terrainBaseXYZ = new Vector3(offsetX, offsetY, 0f); + + BSTerrainPhys physTerrain = null; + lock (m_terrains) + { + m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain); + } + outTerrainBase = terrainBaseXYZ; + outPhysTerrain = physTerrain; + return (physTerrain != null); + } + // Although no one seems to check this, I do support combining. public bool SupportsCombining() { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt index 7d6ace8b08..31dd790ff3 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt @@ -1,3 +1,16 @@ +CURRENT PRIORITIES +================================================= +Eliminate all crashes (DONEish) + Editing/deleting physical linkset (DONE) + Border crossing of physical linkset (DONE) +Enable vehicle border crossings (at least as poorly as ODE) + Avatar created in previous region and not new region when crossing border + Vehicle recreated in new sim at small Z value (offset from root value?) +Calibrate turning radius +limitMotorUp calibration (more down?) +study PID motors (include 'efficiency' implementation + Add to avatar movement + CRASHES ================================================= 20121129.1411: editting/moving phys object across region boundries causes crash @@ -11,16 +24,18 @@ CRASHES VEHICLES TODO LIST: ================================================= +Border crossing with linked vehicle causes crash Neb vehicle taking > 25ms of physics time!! Vehicles (Move smoothly) Add vehicle collisions so IsColliding is properly reported. Needed for banking, limitMotorUp, movementLimiting, ... Some vehicles should not be able to turn if no speed or off ground. +Cannot edit/move a vehicle being ridden: it jumps back to the origional position. Neb car jiggling left and right Happens on terrain and any other mesh object. Flat cubes are much smoother. This has been reduced but not eliminated. Light cycle falling over when driving -For limitMotorUp, use raycast down to find if vehicle is in the air. +Implement referenceFrame for all the motion routines. Angular motion around Z moves the vehicle in world Z and not vehicle Z in ODE. Verify that angular motion specified around Z moves in the vehicle coordinates. Verify llGetVel() is returning a smooth and good value for vehicle movement. @@ -31,12 +46,13 @@ Should vehicle angular/linear movement friction happen after all the components After getting off a vehicle, the root prim is phantom (can be walked through) Need to force a position update for the root prim after compound shape destruction Linkset explosion after three "rides" on Nebadon lite vehicle (LinksetConstraint) -Implement referenceFrame for all the motion routines. -Cannot edit/move a vehicle being ridden: it jumps back to the origional position. -Border crossing with linked vehicle causes crash +For limitMotorUp, use raycast down to find if vehicle is in the air. +Remove vehicle angular velocity zeroing in BSPrim.UpdateProperties(). + A kludge that isn't fixing the real problem of Bullet adding extra motion. BULLETSIM TODO LIST: ================================================= +Revisit CollisionMargin. Builders notice the 0.04 spacing between prims. Avatar height off after unsitting (floats off ground) Editting appearance then moving restores. Must not be initializing height when recreating capsule after unsit. @@ -64,11 +80,16 @@ Implement ShapeCollection.Dispose() Implement water as a plain so raycasting and collisions can happen with same. Add osGetPhysicsEngineName() so scripters can tell whether BulletSim or ODE Also osGetPhysicsEngineVerion() maybe. +Linkset.Position and Linkset.Orientation requre rewrite to properly return + child position. LinksetConstraint acts like it's at taint time!! LINKSETS ====================================================== Linksets should allow collisions to individual children Add LocalID to children shapes in LinksetCompound and create events for individuals +LinksetCompound: when one of the children changes orientation (like tires + turning on a vehicle, the whole compound object is rebuilt. Optimize this + so orientation/position of individual children can change without a rebuild. Verify/think through scripts in children of linksets. What do they reference and return when getting position, velocity, ... Confirm constraint linksets still work after making all the changes for compound linksets. @@ -140,6 +161,11 @@ Remove HeightmapInfo from terrain specification Since C++ code does not need terrain height, this structure et al are not needed. Add floating motor for BS_FLOATS_ON_WATER so prim and avatar will bob at the water level. BSPrim.PositionSanityCheck(). +Should taints check for existance or activeness of target? + When destroying linksets/etc, taints can be generated for objects that are + actually gone when the taint happens. Crashes don't happen because the taint closure + keeps the object from being freed, but that is just an accident. + Possibly have and 'active' flag that is checked by the taint processor? THREADING =================================================