From 128c72a23437423d87cc9b10815f96d7362bddd1 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 25 Mar 2013 21:24:21 +0000 Subject: Start recording inter-region teleport attempts, aborts, cancels and failures in statistics for monitoring/debugging purposes These are recorded as 'entitytransfer' stats as seen by the "show stats entitytransfer" console command. --- .../EntityTransfer/EntityTransferModule.cs | 119 +++++++++++++++++++-- 1 file changed, 109 insertions(+), 10 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 136caad..4cf7645 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -33,6 +33,7 @@ using System.Threading; using OpenSim.Framework; using OpenSim.Framework.Capabilities; using OpenSim.Framework.Client; +using OpenSim.Framework.Monitoring; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Physics.Manager; @@ -77,6 +78,31 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer /// public bool DisableInterRegionTeleportCancellation { get; set; } + /// + /// Number of times inter-region teleport was attempted. + /// + private Stat m_interRegionTeleportAttempts; + + /// + /// Number of times inter-region teleport was aborted (due to simultaneous client logout). + /// + private Stat m_interRegionTeleportAborts; + + /// + /// Number of times inter-region teleport was successfully cancelled by the client. + /// + private Stat m_interRegionTeleportCancels; + + /// + /// Number of times inter-region teleport failed due to server/client/network problems (e.g. viewer failed to + /// connect with destination region). + /// + /// + /// This is not necessarily a problem for this simulator - in open-grid/hg conditions, viewer connectivity to + /// destination simulator is unknown. + /// + private Stat m_interRegionTeleportFailures; + protected bool m_Enabled = false; public Scene Scene { get; private set; } @@ -156,6 +182,60 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer Scene = scene; + m_interRegionTeleportAttempts = + new Stat( + "InterRegionTeleportAttempts", + "Number of inter-region teleports attempted.", + "This does not count attempts which failed due to pre-conditions (e.g. target simulator refused access).\n" + + "You can get successfully teleports by subtracting aborts, cancels and teleport failures from this figure.", + "", + "entitytransfer", + Scene.Name, + StatType.Push, + null, + StatVerbosity.Debug); + + m_interRegionTeleportAborts = + new Stat( + "InterRegionTeleportAborts", + "Number of inter-region teleports aborted due to client actions.", + "The chief action is simultaneous logout whilst teleporting.", + "", + "entitytransfer", + Scene.Name, + StatType.Push, + null, + StatVerbosity.Debug); + + m_interRegionTeleportCancels = + new Stat( + "InterRegionTeleportCancels", + "Number of inter-region teleports cancelled by the client.", + null, + "", + "entitytransfer", + Scene.Name, + StatType.Push, + null, + StatVerbosity.Debug); + + m_interRegionTeleportFailures = + new Stat( + "InterRegionTeleportFailures", + "Number of inter-region teleports that failed due to server/client/network issues.", + "This number may not be very helpful in open-grid/hg situations as the network connectivity/quality of destinations is uncontrollable.", + "", + "entitytransfer", + Scene.Name, + StatType.Push, + null, + StatVerbosity.Debug); + + StatsManager.RegisterStat(m_interRegionTeleportAttempts); + StatsManager.RegisterStat(m_interRegionTeleportAborts); + StatsManager.RegisterStat(m_interRegionTeleportCancels); + StatsManager.RegisterStat(m_interRegionTeleportFailures); + scene.RegisterModuleInterface(this); scene.EventManager.OnNewClient += OnNewClient; } @@ -173,7 +253,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer public virtual void Close() {} - public virtual void RemoveRegion(Scene scene) {} + public virtual void RemoveRegion(Scene scene) + { + StatsManager.DeregisterStat(m_interRegionTeleportAttempts); + StatsManager.DeregisterStat(m_interRegionTeleportAborts); + StatsManager.DeregisterStat(m_interRegionTeleportCancels); + StatsManager.DeregisterStat(m_interRegionTeleportFailures); + } public virtual void RegionLoaded(Scene scene) { @@ -545,6 +631,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return; } + // Before this point, teleport 'failure' is due to checkable pre-conditions such as whether the target + // simulator can be found and is explicitly prepared to allow access. Therefore, we will not count these + // as server attempts. + m_interRegionTeleportAttempts.Value++; + m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version); // Fixing a bug where teleporting while sitting results in the avatar ending up removed from @@ -595,6 +686,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer bool logout = false; if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout)) { + m_interRegionTeleportFailures.Value++; + sp.ControllingClient.SendTeleportFailed(String.Format("Teleport refused: {0}", reason)); m_log.DebugFormat( @@ -606,6 +699,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling) { + m_interRegionTeleportCancels.Value++; + m_log.DebugFormat( "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request", sp.Name, finalDestination.RegionName, sp.Scene.Name); @@ -614,6 +709,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) { + m_interRegionTeleportAborts.Value++; + m_log.DebugFormat( "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.", sp.Name, finalDestination.RegionName, sp.Scene.Name); @@ -683,6 +780,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // establish th econnection to the destination which makes it return true. if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) { + m_interRegionTeleportAborts.Value++; + m_log.DebugFormat( "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} before UpdateAgent", sp.Name, finalDestination.RegionName, sp.Scene.Name); @@ -698,6 +797,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) { + m_interRegionTeleportAborts.Value++; + m_log.DebugFormat( "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.", sp.Name, finalDestination.RegionName, sp.Scene.Name); @@ -715,6 +816,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling) { + m_interRegionTeleportCancels.Value++; + m_log.DebugFormat( "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request", sp.Name, finalDestination.RegionName, sp.Scene.Name); @@ -750,6 +853,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) { + m_interRegionTeleportAborts.Value++; + m_log.DebugFormat( "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after WaitForAgentArrivedAtDestination due to previous client close.", sp.Name, finalDestination.RegionName, sp.Scene.Name); @@ -762,6 +867,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); Fail(sp, finalDestination, logout, "Destination region did not signal teleport completion."); + return; } @@ -803,15 +909,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // now we have a child agent in this region. sp.Reset(); } - - // Commented pending deletion since this method no longer appears to do anything at all -// // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! -// if (sp.Scene.NeedSceneCacheClear(sp.UUID)) -// { -// m_log.DebugFormat( -// "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed", -// sp.UUID); -// } } /// @@ -847,6 +944,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { CleanupFailedInterRegionTeleport(sp, finalDestination); + m_interRegionTeleportFailures.Value++; + sp.ControllingClient.SendTeleportFailed( string.Format( "Problems connecting to destination {0}, reason: {1}", finalDestination.RegionName, reason)); -- cgit v1.1 From f783b9169fbc0544ec6c634900cb34bf48c6b2a9 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 22 Mar 2013 16:50:56 -0700 Subject: BulletSim: parameterize C# HACD hull creation. Add feature of reducing max hull count for simple (non-cut prims) meshes. --- OpenSim/Region/Physics/BulletSPlugin/BSParam.cs | 33 +++++++++++++ .../Physics/BulletSPlugin/BSShapeCollection.cs | 55 ++++++++++++++++------ 2 files changed, 74 insertions(+), 14 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs index 4d89a88..26d2d60 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs @@ -142,6 +142,14 @@ public static class BSParam public static float VehicleAngularBankingTimescaleFudge { get; private set; } public static bool VehicleDebuggingEnabled { get; private set; } + // Convex Hulls + public static int CSHullMaxDepthSplit { get; private set; } + public static int CSHullMaxDepthSplitForSimpleShapes { get; private set; } + public static float CSHullConcavityThresholdPercent { get; private set; } + public static float CSHullVolumeConservationThresholdPercent { get; private set; } + public static int CSHullMaxVertices { get; private set; } + public static float CSHullMaxSkinWidth { get; private set; } + // Linkset implementation parameters public static float LinksetImplementation { get; private set; } public static bool LinkConstraintUseFrameOffset { get; private set; } @@ -623,6 +631,31 @@ public static class BSParam (s) => { return GlobalContactBreakingThreshold; }, (s,v) => { GlobalContactBreakingThreshold = v; s.UnmanagedParams[0].globalContactBreakingThreshold = v; } ), + new ParameterDefn("CSHullMaxDepthSplit", "CS impl: max depth to split for hull. 1-10 but > 7 is iffy", + 7, + (s) => { return CSHullMaxDepthSplit; }, + (s,v) => { CSHullMaxDepthSplit = v; } ), + new ParameterDefn("CSHullMaxDepthSplitForSimpleShapes", "CS impl: max depth setting for simple prim shapes", + 2, + (s) => { return CSHullMaxDepthSplitForSimpleShapes; }, + (s,v) => { CSHullMaxDepthSplitForSimpleShapes = v; } ), + new ParameterDefn("CSHullConcavityThresholdPercent", "CS impl: concavity threshold percent (0-20)", + 5f, + (s) => { return CSHullConcavityThresholdPercent; }, + (s,v) => { CSHullConcavityThresholdPercent = v; } ), + new ParameterDefn("CSHullVolumeConservationThresholdPercent", "percent volume conservation to collapse hulls (0-30)", + 5f, + (s) => { return CSHullVolumeConservationThresholdPercent; }, + (s,v) => { CSHullVolumeConservationThresholdPercent = v; } ), + new ParameterDefn("CSHullMaxVertices", "CS impl: maximum number of vertices in output hulls. Keep < 50.", + 32, + (s) => { return CSHullMaxVertices; }, + (s,v) => { CSHullMaxVertices = v; } ), + new ParameterDefn("CSHullMaxSkinWidth", "CS impl: skin width to apply to output hulls.", + 0, + (s) => { return CSHullMaxSkinWidth; }, + (s,v) => { CSHullMaxSkinWidth = v; } ), + new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)", (float)BSLinkset.LinksetImplementation.Compound, (s) => { return LinksetImplementation; }, diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index b16bc10..457f204 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -447,17 +447,10 @@ public sealed class BSShapeCollection : IDisposable // If the prim attributes are simple, this could be a simple Bullet native shape if (!haveShape + && nativeShapePossible && pbs != null && !pbs.SculptEntry - && nativeShapePossible - && ((pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim) - || (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 - && pbs.ProfileHollow == 0 - && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0 - && pbs.PathBegin == 0 && pbs.PathEnd == 0 - && pbs.PathTaperX == 0 && pbs.PathTaperY == 0 - && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 - && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) ) + && ((pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim) || PrimHasNoCuts(pbs)) ) { // Get the scale of any existing shape so we can see if the new shape is same native type and same size. OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero; @@ -508,6 +501,18 @@ public sealed class BSShapeCollection : IDisposable return ret; } + // return 'true' if this shape description does not include any cutting or twisting. + private bool PrimHasNoCuts(PrimitiveBaseShape pbs) + { + return pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 + && pbs.ProfileHollow == 0 + && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0 + && pbs.PathBegin == 0 && pbs.PathEnd == 0 + && pbs.PathTaperX == 0 && pbs.PathTaperY == 0 + && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 + && pbs.PathShearX == 0 && pbs.PathShearY == 0; + } + // return 'true' if the prim's shape was changed. public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) { @@ -518,7 +523,7 @@ public sealed class BSShapeCollection : IDisposable if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects) { // Update prim.BSShape to reference a hull of this shape. - ret = GetReferenceToHull(prim,shapeCallback); + ret = GetReferenceToHull(prim, shapeCallback); if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); } @@ -697,6 +702,7 @@ public sealed class BSShapeCollection : IDisposable // See that hull shape exists in the physical world and update prim.BSShape. // We could be creating the hull because scale changed or whatever. + // Return 'true' if a new hull was built. Otherwise, returning a shared hull instance. private bool GetReferenceToHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) { BulletShape newShape; @@ -715,6 +721,7 @@ public sealed class BSShapeCollection : IDisposable DereferenceShape(prim.PhysShape, shapeCallback); newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod); + // It might not have been created if we're waiting for an asset. newShape = VerifyMeshCreated(newShape, prim); ReferenceShape(newShape); @@ -733,14 +740,14 @@ public sealed class BSShapeCollection : IDisposable HullDesc hullDesc; if (Hulls.TryGetValue(newHullKey, out hullDesc)) { - // If the hull shape already is created, just use it. + // If the hull shape already has been created, just use the one shared instance. newShape = hullDesc.shape.Clone(); } else { - // Build a new hull in the physical world - // Pass true for physicalness as this creates some sort of bounding box which we don't need - IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false); + // Build a new hull in the physical world. + // Pass true for physicalness as this prevents the creation of bounding box which is not needed + IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */); if (meshData != null) { @@ -759,15 +766,35 @@ public sealed class BSShapeCollection : IDisposable convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); } + uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit; + if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes) + { + // Simple primitive shapes we know are convex so they are better implemented with + // fewer hulls. + // Check for simple shape (prim without cuts) and reduce split parameter if so. + if (PrimHasNoCuts(pbs)) + { + maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes; + } + } + // setup and do convex hull conversion m_hulls = new List(); DecompDesc dcomp = new DecompDesc(); dcomp.mIndices = convIndices; dcomp.mVertices = convVertices; + dcomp.mDepth = maxDepthSplit; + dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent; + dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent; + dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices; + dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth; ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); // create the hull into the _hulls variable convexBuilder.process(dcomp); + DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}", + BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count); + // Convert the vertices and indices for passing to unmanaged. // The hull information is passed as a large floating point array. // The format is: -- cgit v1.1 From 953090fd62c2f8647d0e04bc3890a04a7076dbad Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sat, 23 Mar 2013 11:00:52 -0700 Subject: BulletSim: fix possible race condition where an prim's asset can be requested quicker than the asset fetcher returns and thus falsely reporting that an asset was not fetched and defaulting the assset to a bounding box. --- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 12 ++++++++---- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 2 +- .../Physics/BulletSPlugin/BSShapeCollection.cs | 21 +++++++++++++++------ 3 files changed, 24 insertions(+), 11 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index f953c1e..6bb88c7 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -86,7 +86,7 @@ public abstract class BSPhysObject : PhysicsActor PhysBody = new BulletBody(localID); PhysShape = new BulletShape(); - LastAssetBuildFailed = false; + PrimAssetState = PrimAssetCondition.Unknown; // Default material type. Also sets Friction, Restitution and Density. SetMaterial((int)MaterialAttributes.Material.Wood); @@ -133,9 +133,13 @@ public abstract class BSPhysObject : PhysicsActor // Reference to the physical shape (btCollisionShape) of this object public BulletShape PhysShape; - // 'true' if the mesh's underlying asset failed to build. - // This will keep us from looping after the first time the build failed. - public bool LastAssetBuildFailed { get; set; } + // The physical representation of the prim might require an asset fetch. + // The asset state is first 'Unknown' then 'Waiting' then either 'Failed' or 'Fetched'. + public enum PrimAssetCondition + { + Unknown, Waiting, Failed, Fetched + } + public PrimAssetCondition PrimAssetState { get; set; } // The objects base shape information. Null if not a prim type shape. public PrimitiveBaseShape BaseShape { get; protected set; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 2cbbe9a..6a5461a 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -155,7 +155,7 @@ public class BSPrim : BSPhysObject public override PrimitiveBaseShape Shape { set { BaseShape = value; - LastAssetBuildFailed = false; + PrimAssetState = PrimAssetCondition.Unknown; ForceBodyShapeRebuild(false); } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 457f204..a6e20a8 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -930,11 +930,15 @@ public sealed class BSShapeCollection : IDisposable return newShape; // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset - if (prim.BaseShape.SculptEntry && !prim.LastAssetBuildFailed && prim.BaseShape.SculptTexture != OMV.UUID.Zero) + if (prim.BaseShape.SculptEntry + && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Failed + && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Waiting + && prim.BaseShape.SculptTexture != OMV.UUID.Zero + ) { - DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lastFailed={1}", prim.LocalID, prim.LastAssetBuildFailed); - // This will prevent looping through this code as we keep trying to get the failed shape - prim.LastAssetBuildFailed = true; + DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset", prim.LocalID); + // Multiple requestors will know we're waiting for this asset + prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Waiting; BSPhysObject xprim = prim; Util.FireAndForget(delegate @@ -945,7 +949,7 @@ public sealed class BSShapeCollection : IDisposable BSPhysObject yprim = xprim; // probably not necessary, but, just in case. assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset) { - bool assetFound = false; // DEBUG DEBUG + bool assetFound = false; string mismatchIDs = String.Empty; // DEBUG DEBUG if (asset != null && yprim.BaseShape.SculptEntry) { @@ -963,6 +967,10 @@ public sealed class BSShapeCollection : IDisposable mismatchIDs = yprim.BaseShape.SculptTexture.ToString() + "/" + asset.ID; } } + if (assetFound) + yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched; + else + yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed; DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}", yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs ); @@ -970,6 +978,7 @@ public sealed class BSShapeCollection : IDisposable } else { + xprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed; PhysicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}", LogHeader, PhysicsScene.Name); } @@ -977,7 +986,7 @@ public sealed class BSShapeCollection : IDisposable } else { - if (prim.LastAssetBuildFailed) + if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed) { PhysicsScene.Logger.ErrorFormat("{0} Mesh failed to fetch asset. lID={1}, texture={2}", LogHeader, prim.LocalID, prim.BaseShape.SculptTexture); -- cgit v1.1 From c96a6f1de6d5e66dd2055365c26144d7a92f2fc5 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sat, 23 Mar 2013 11:03:59 -0700 Subject: BulletSim: small tweaks and formatting in the parameter fetching code. --- OpenSim/Region/Physics/BulletSPlugin/BSParam.cs | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs index 26d2d60..f3454c8 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs @@ -203,10 +203,10 @@ public static class BSParam public delegate void PSetOnObject(BSScene scene, BSPhysObject obj); public sealed class ParameterDefn : ParameterDefnBase { - T defaultValue; - PSetValue setter; - PGetValue getter; - PSetOnObject objectSet; + private T defaultValue; + private PSetValue setter; + private PGetValue getter; + private PSetOnObject objectSet; public ParameterDefn(string pName, string pDesc, T pDefault, PGetValue pGetter, PSetValue pSetter) : base(pName, pDesc) { @@ -223,13 +223,23 @@ public static class BSParam getter = pGetter; objectSet = pObjSetter; } + /* Wish I could simplify using this definition but CLR doesn't store references so closure around delegates of references won't work + public ParameterDefn(string pName, string pDesc, T pDefault, ref T loc) + : base(pName, pDesc) + { + defaultValue = pDefault; + setter = (s, v) => { loc = v; }; + getter = (s) => { return loc; }; + objectSet = null; + } + */ public override void AssignDefault(BSScene s) { setter(s, defaultValue); } public override string GetValue(BSScene s) { - return String.Format("{0}", getter(s)); + return getter(s).ToString(); } public override void SetValue(BSScene s, string valAsString) { @@ -252,6 +262,7 @@ public static class BSParam try { T setValue = (T)parser.Invoke(genericType, new Object[] { valAsString }); + // Store the parsed value setter(s, setValue); // s.Logger.DebugFormat("{0} Parameter {1} = {2}", LogHeader, name, setValue); } -- cgit v1.1 From 285dc554ece0b504cb549193096f84c9c0cfe89f Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 25 Mar 2013 15:19:55 -0700 Subject: BulletSim: new algorithm for vertical attraction which uses quaternion arithmetic to compute the shortest path between the current tilt and vertical. --- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 48 ++++++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 5549984..65df741 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -321,7 +321,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin } } - internal void ProcessTypeChange(Vehicle pType) + public void ProcessTypeChange(Vehicle pType) { VDetailLog("{0},ProcessTypeChange,type={1}", Prim.LocalID, pType); // Set Defaults For Type @@ -1301,14 +1301,52 @@ namespace OpenSim.Region.Physics.BulletSPlugin // efficiency of 1.0 will cause the spring to reach its equilibrium with exponential decay. public void ComputeAngularVerticalAttraction() { + // If vertical attaction timescale is reasonable if (enableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff) { + // Possible solution derived from a discussion at: + // http://stackoverflow.com/questions/14939657/computing-vector-from-quaternion-works-computing-quaternion-from-vector-does-no + + // Create a rotation that is only the vehicle's rotation around Z + Vector3 currentEuler = Vector3.Zero; + VehicleOrientation.GetEulerAngles(out currentEuler.X, out currentEuler.Y, out currentEuler.Z); + Quaternion justZOrientation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, currentEuler.Z); + + // Create the axis that is perpendicular to the up vector and the rotated up vector. + Vector3 differenceAxis = Vector3.Cross(Vector3.UnitZ * justZOrientation, Vector3.UnitZ * VehicleOrientation); + // Compute the angle between those to vectors. + double differenceAngle = Math.Acos((double)Vector3.Dot(Vector3.UnitZ, Vector3.Normalize(Vector3.UnitZ * VehicleOrientation))); + // 'differenceAngle' is the angle to rotate and 'differenceAxis' is the plane to rotate in to get the vehicle vertical + + // Reduce the change by the time period it is to change in. Timestep is handled when velocity is applied. + // TODO: add 'efficiency'. + differenceAngle /= m_verticalAttractionTimescale; + + // Create the quaterian representing the correction angle + Quaternion correctionRotation = Quaternion.CreateFromAxisAngle(differenceAxis, (float)differenceAngle); + + // Turn that quaternion into Euler values to make it into velocities to apply. + Vector3 vertContributionV = Vector3.Zero; + correctionRotation.GetEulerAngles(out vertContributionV.X, out vertContributionV.Y, out vertContributionV.Z); + vertContributionV *= -1f; + + VehicleRotationalVelocity += vertContributionV; + + VDetailLog("{0}, MoveAngular,verticalAttraction,diffAxis={1},diffAng={2},corrRot={3},contrib={4}", + Prim.LocalID, + differenceAxis, + differenceAngle, + correctionRotation, + vertContributionV); + + // =================================================================== + /* Vector3 vertContributionV = Vector3.Zero; Vector3 origRotVelW = VehicleRotationalVelocity; // DEBUG DEBUG // Take a vector pointing up and convert it from world to vehicle relative coords. - Vector3 verticalError = Vector3.UnitZ * VehicleOrientation; + Vector3 verticalError = Vector3.Normalize(Vector3.UnitZ * VehicleOrientation); // If vertical attraction correction is needed, the vector that was pointing up (UnitZ) // is now: @@ -1334,13 +1372,17 @@ namespace OpenSim.Region.Physics.BulletSPlugin // 'vertContrbution' is now the necessary angular correction to correct tilt in one second. // Correction happens over a number of seconds. Vector3 unscaledContribVerticalErrorV = vertContributionV; // DEBUG DEBUG + + // The correction happens over the user's time period vertContributionV /= m_verticalAttractionTimescale; - VehicleRotationalVelocity += vertContributionV; + // Rotate the vehicle rotation to the world coordinates. + VehicleRotationalVelocity += (vertContributionV * VehicleOrientation); VDetailLog("{0}, MoveAngular,verticalAttraction,,origRotVW={1},vertError={2},unscaledV={3},eff={4},ts={5},vertContribV={6}", Prim.LocalID, origRotVelW, verticalError, unscaledContribVerticalErrorV, m_verticalAttractionEfficiency, m_verticalAttractionTimescale, vertContributionV); + */ } } -- cgit v1.1