From 2f5fe4b88e8eb0388cc2138c48a941b1317ed560 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 20 Nov 2012 08:34:18 -0800 Subject: BulletSim: tweek avatar capsule parameters so avatar feet don't go below ground. This solves the bouncing, short avatar problem (Mantis 6403). --- OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | 7 ++++--- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 11 ++++++----- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 3c48dcc..fa1a23f 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -184,8 +184,8 @@ public sealed class BSCharacter : BSPhysObject _size = value; ComputeAvatarScale(_size); ComputeAvatarVolumeAndMass(); - DetailLog("{0},BSCharacter.setSize,call,scale={1},density={2},volume={3},mass={4}", - LocalID, Scale, _avatarDensity, _avatarVolume, RawMass); + DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}", + LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass); PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() { @@ -619,7 +619,8 @@ public sealed class BSCharacter : BSPhysObject newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; // From the total height, remove the capsule half spheres that are at each end - newScale.Z = size.Z - (newScale.X + newScale.Y); + // The 1.15f came from ODE. Not sure what this factors in. + newScale.Z = (size.Z * 1.15f) - (newScale.X + newScale.Y); Scale = newScale; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 2fee95e..58dccea 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -712,7 +712,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // here just before the physics engine is called to step the simulation. public void ProcessTaints() { - InTaintTime = true; + InTaintTime = true; // Only used for debugging so locking is not necessary. ProcessRegularTaints(); ProcessPostTaintTaints(); InTaintTime = false; @@ -758,6 +758,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters DetailLog("{0},BSScene.ProcessTaints,leftTaintsOnList,numNotProcessed={1}", DetailLogZero, _taintOperations.Count); } */ + // swizzle a new list into the list location so we can process what's there List oldList; lock (_taintLock) @@ -787,8 +788,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // will replace any previous operation by the same object. public void PostTaintObject(String ident, uint ID, TaintCallback callback) { - if (!m_initialized) return; - string uniqueIdent = ident + "-" + ID.ToString(); lock (_taintLock) { @@ -864,13 +863,14 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters } } + // Only used for debugging. Does not change state of anything so locking is not necessary. public bool AssertInTaintTime(string whereFrom) { if (!InTaintTime) { DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom); m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom); - Util.PrintCallStack(); + Util.PrintCallStack(); // Prints the stack into the DEBUG log file. } return InTaintTime; } @@ -1186,7 +1186,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters (s) => { return s.m_params[0].avatarCapsuleRadius; }, (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ), new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar", - 1.5f, + // 1.5f, + 2.140599f, (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarCapsuleHeight; }, (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ), -- cgit v1.1 From 4d29488216f3619455cda72aaf2d6ccf8f3e2402 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 20 Nov 2012 08:43:43 -0800 Subject: BulletSim: change PositionSanityCheck to apply a force to correct position corrections (below ground and floating). --- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 61 ++++++++++------------ .../Physics/BulletSPlugin/BSShapeCollection.cs | 2 +- 2 files changed, 30 insertions(+), 33 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 500c84a..b1b5846 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -47,7 +47,6 @@ public sealed class BSPrim : BSPhysObject // _size is what the user passed. Scale is what we pass to the physics engine with the mesh. // Often Scale is unity because the meshmerizer will apply _size when creating the mesh. private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user - // private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer private bool _grabbed; private bool _isSelected; @@ -274,19 +273,19 @@ public sealed class BSPrim : BSPhysObject if (!Linkset.IsRoot(this)) _position = Linkset.Position(this); - // don't do the GetObjectPosition for root elements because this function is called a zillion times + // don't do the GetObjectPosition for root elements because this function is called a zillion times. // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); return _position; } set { - // If you must push the position into the physics engine, use ForcePosition. + // If the position must be forced into the physics engine, use ForcePosition. if (_position == value) { return; } _position = value; // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? - PositionSanityCheck(); + PositionSanityCheck(false); PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() { // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); @@ -302,7 +301,7 @@ public sealed class BSPrim : BSPhysObject } set { _position = value; - PositionSanityCheck(); + // PositionSanityCheck(); // Don't do this! Causes a loop and caller should know better. BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); ActivateIfPhysical(false); } @@ -311,52 +310,43 @@ public sealed class BSPrim : BSPhysObject // Check that the current position is sane and, if not, modify the position to make it so. // Check for being below terrain and being out of bounds. // Returns 'true' of the position was made sane by some action. - private bool PositionSanityCheck() + private bool PositionSanityCheck(bool inTaintTime) { bool ret = false; - // If totally below the ground, move the prim up - // TODO: figure out the right solution for this... only for dynamic objects? - /* float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); + OMV.Vector3 upForce = OMV.Vector3.Zero; if (Position.Z < terrainHeight) { DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); - _position.Z = terrainHeight + 2.0f; + float targetHeight = terrainHeight + (Size.Z / 2f); + // Upforce proportional to the distance away from the terrain. Correct the error in 1 sec. + upForce.Z = (terrainHeight - Position.Z) * 1f; ret = true; } - */ + if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) { float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); // TODO: a floating motor so object will bob in the water - if (Position.Z < waterHeight) + if (Math.Abs(Position.Z - waterHeight) > 0.1f) { - _position.Z = waterHeight; + // Upforce proportional to the distance away from the water. Correct the error in 1 sec. + upForce.Z = (waterHeight - Position.Z) * 1f; ret = true; } } // TODO: check for out of bounds - return ret; - } - // A version of the sanity check that also makes sure a new position value is - // pushed to the physics engine. This routine would be used by anyone - // who is not already pushing the value. - private bool PositionSanityCheck(bool inTaintTime) - { - bool ret = false; - if (PositionSanityCheck()) + // The above code computes a force to apply to correct any out-of-bounds problems. Apply same. + if (ret) { - // The new position value must be pushed into the physics engine but we can't - // just assign to "Position" because of potential call loops. - PhysicsScene.TaintedObject(inTaintTime, "BSPrim.PositionSanityCheck", delegate() + PhysicsScene.TaintedObject(inTaintTime, "BSPrim.PositionSanityCheck:belowTerrain", delegate() { - DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); - ForcePosition = _position; + // Apply upforce and overcome gravity. + ForceVelocity = ForceVelocity + upForce - PhysicsScene.DefaultGravity; }); - ret = true; } return ret; } @@ -940,6 +930,7 @@ public sealed class BSPrim : BSPhysObject public override void AddForce(OMV.Vector3 force, bool pushforce) { AddForce(force, pushforce, false); } + // Applying a force just adds this to the total force on the object. public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { // for an object, doesn't matter if force is a pushforce or not if (force.IsFinite()) @@ -971,6 +962,7 @@ public sealed class BSPrim : BSPhysObject }); } + // An impulse force is scaled by the mass of the object. public void ApplyForceImpulse(OMV.Vector3 impulse, bool inTaintTime) { OMV.Vector3 applyImpulse = impulse; @@ -1423,7 +1415,7 @@ public sealed class BSPrim : BSPhysObject if (changed != 0) { // Only update the position of single objects and linkset roots - if (this._parentPrim == null) + if (Linkset.IsRoot(this)) { base.RequestPhysicsterseUpdate(); } @@ -1435,19 +1427,24 @@ public sealed class BSPrim : BSPhysObject // Updates only for individual prims and for the root object of a linkset. if (Linkset.IsRoot(this)) { - // Assign to the local variables so the normal set action does not happen + // Assign directly to the local variables so the normal set action does not happen _position = entprop.Position; _orientation = entprop.Rotation; _velocity = entprop.Velocity; _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; + // The sanity check can change the velocity and/or position. + if (PositionSanityCheck(true)) + { + entprop.Position = _position; + entprop.Velocity = _velocity; + } + // remember the current and last set values LastEntityProperties = CurrentEntityProperties; CurrentEntityProperties = entprop; - PositionSanityCheck(true); - OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}", LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 29a23c0..7ef6429 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -940,7 +940,7 @@ public sealed class BSShapeCollection : IDisposable else { bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, - prim.LocalID, prim.ForcePosition, prim.ForceOrientation); + prim.LocalID, prim.RawPosition, prim.RawOrientation); DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); } aBody = new BulletBody(prim.LocalID, bodyPtr); -- cgit v1.1 From d6db0d5740dae03174f65846556f2f06d573b5c4 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 20 Nov 2012 11:24:25 -0800 Subject: BulletSim: uplevel PhysicsShapeType out of ShapeData structure (since it is getting simplified out of existance someday) and update all the references to that enum. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 4 +- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 4 +- .../Physics/BulletSPlugin/BSLinksetCompound.cs | 6 +-- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 4 +- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 2 +- .../Physics/BulletSPlugin/BSShapeCollection.cs | 56 +++++++++++----------- OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs | 16 +++---- .../Physics/BulletSPlugin/BSTerrainManager.cs | 4 +- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 37 +++++++------- 9 files changed, 67 insertions(+), 66 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index fa1a23f..92ff804 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -203,9 +203,9 @@ public sealed class BSCharacter : BSPhysObject set { BaseShape = value; } } // I want the physics engine to make an avatar capsule - public override ShapeData.PhysicsShapeType PreferredPhysicalShape + public override PhysicsShapeType PreferredPhysicalShape { - get {return ShapeData.PhysicsShapeType.SHAPE_AVATAR; } + get {return PhysicsShapeType.SHAPE_AVATAR; } } public override bool Grabbed { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 436e043..4ee047b 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -82,9 +82,9 @@ public abstract class BSLinkset // Some linksets have a preferred physical shape. // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected. - public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) + public virtual PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) { - return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; + return PhysicsShapeType.SHAPE_UNKNOWN; } // Linksets move around the children so the linkset might need to compute the child position diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index 3238c85..cb37840 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -42,12 +42,12 @@ public sealed class BSLinksetCompound : BSLinkset } // For compound implimented linksets, if there are children, use compound shape for the root. - public override ShapeData.PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) + public override PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) { - ShapeData.PhysicsShapeType ret = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; + PhysicsShapeType ret = PhysicsShapeType.SHAPE_UNKNOWN; if (IsRoot(requestor) && HasAnyChildren) { - ret = ShapeData.PhysicsShapeType.SHAPE_COMPOUND; + ret = PhysicsShapeType.SHAPE_COMPOUND; } // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret); return ret; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 991e5b1..e68b167 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -94,9 +94,9 @@ public abstract class BSPhysObject : PhysicsActor public PrimitiveBaseShape BaseShape { get; protected set; } // Some types of objects have preferred physical representations. // Returns SHAPE_UNKNOWN if there is no preference. - public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape + public virtual PhysicsShapeType PreferredPhysicalShape { - get { return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; } + get { return PhysicsShapeType.SHAPE_UNKNOWN; } } // When the physical properties are updated, an EntityProperty holds the update values. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index b1b5846..2657e4b 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -169,7 +169,7 @@ public sealed class BSPrim : BSPhysObject } } // Whatever the linkset wants is what I want. - public override ShapeData.PhysicsShapeType PreferredPhysicalShape + public override PhysicsShapeType PreferredPhysicalShape { get { return Linkset.PreferredPhysicalShape(this); } } public override bool ForceBodyShapeRebuild(bool inTaintTime) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 7ef6429..746a52e 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -178,7 +178,7 @@ public sealed class BSShapeCollection : IDisposable bool ret = false; switch (shape.type) { - case ShapeData.PhysicsShapeType.SHAPE_MESH: + case PhysicsShapeType.SHAPE_MESH: MeshDesc meshDesc; if (Meshes.TryGetValue(shape.shapeKey, out meshDesc)) { @@ -201,7 +201,7 @@ public sealed class BSShapeCollection : IDisposable meshDesc.lastReferenced = System.DateTime.Now; Meshes[shape.shapeKey] = meshDesc; break; - case ShapeData.PhysicsShapeType.SHAPE_HULL: + case PhysicsShapeType.SHAPE_HULL: HullDesc hullDesc; if (Hulls.TryGetValue(shape.shapeKey, out hullDesc)) { @@ -224,7 +224,7 @@ public sealed class BSShapeCollection : IDisposable hullDesc.lastReferenced = System.DateTime.Now; Hulls[shape.shapeKey] = hullDesc; break; - case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: + case PhysicsShapeType.SHAPE_UNKNOWN: break; default: // Native shapes are not tracked and they don't go into any list @@ -255,16 +255,16 @@ public sealed class BSShapeCollection : IDisposable { switch (shape.type) { - case ShapeData.PhysicsShapeType.SHAPE_HULL: + case PhysicsShapeType.SHAPE_HULL: DereferenceHull(shape, shapeCallback); break; - case ShapeData.PhysicsShapeType.SHAPE_MESH: + case PhysicsShapeType.SHAPE_MESH: DereferenceMesh(shape, shapeCallback); break; - case ShapeData.PhysicsShapeType.SHAPE_COMPOUND: + case PhysicsShapeType.SHAPE_COMPOUND: DereferenceCompound(shape, shapeCallback); break; - case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: + case PhysicsShapeType.SHAPE_UNKNOWN: break; default: break; @@ -352,28 +352,28 @@ public sealed class BSShapeCollection : IDisposable BulletShape shapeInfo = new BulletShape(cShape); if (TryGetMeshByPtr(cShape, out meshDesc)) { - shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_MESH; + shapeInfo.type = PhysicsShapeType.SHAPE_MESH; shapeInfo.shapeKey = meshDesc.shapeKey; } else { if (TryGetHullByPtr(cShape, out hullDesc)) { - shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_HULL; + shapeInfo.type = PhysicsShapeType.SHAPE_HULL; shapeInfo.shapeKey = hullDesc.shapeKey; } else { if (BulletSimAPI.IsCompound2(cShape)) { - shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_COMPOUND; + shapeInfo.type = PhysicsShapeType.SHAPE_COMPOUND; } else { if (BulletSimAPI.IsNativeShape2(cShape)) { shapeInfo.isNativeShape = true; - shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) + shapeInfo.type = PhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) } } } @@ -381,7 +381,7 @@ public sealed class BSShapeCollection : IDisposable DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo); - if (shapeInfo.type != ShapeData.PhysicsShapeType.SHAPE_UNKNOWN) + if (shapeInfo.type != PhysicsShapeType.SHAPE_UNKNOWN) { DereferenceShape(shapeInfo, true, null); } @@ -405,10 +405,10 @@ public sealed class BSShapeCollection : IDisposable bool ret = false; bool haveShape = false; - if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR) + if (!haveShape && prim.PreferredPhysicalShape == PhysicsShapeType.SHAPE_AVATAR) { // an avatar capsule is close to a native shape (it is not shared) - ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_AVATAR, + ret = GetReferenceToNativeShape(prim, PhysicsShapeType.SHAPE_AVATAR, ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape); ret = true; @@ -417,7 +417,7 @@ public sealed class BSShapeCollection : IDisposable // Compound shapes are handled special as they are rebuilt from scratch. // This isn't too great a hardship since most of the child shapes will already been created. - if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_COMPOUND) + if (!haveShape && prim.PreferredPhysicalShape == PhysicsShapeType.SHAPE_COMPOUND) { ret = GetReferenceToCompoundShape(prim, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape); @@ -460,10 +460,10 @@ public sealed class BSShapeCollection : IDisposable haveShape = true; if (forceRebuild || prim.Scale != prim.Size - || prim.PhysShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE + || prim.PhysShape.type != PhysicsShapeType.SHAPE_SPHERE ) { - ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_SPHERE, + ret = GetReferenceToNativeShape(prim, PhysicsShapeType.SHAPE_SPHERE, ShapeData.FixedShapeKey.KEY_SPHERE, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", prim.LocalID, forceRebuild, prim.PhysShape); @@ -474,10 +474,10 @@ public sealed class BSShapeCollection : IDisposable haveShape = true; if (forceRebuild || prim.Scale != prim.Size - || prim.PhysShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX + || prim.PhysShape.type != PhysicsShapeType.SHAPE_BOX ) { - ret = GetReferenceToNativeShape( prim, ShapeData.PhysicsShapeType.SHAPE_BOX, + ret = GetReferenceToNativeShape( prim, PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", prim.LocalID, forceRebuild, prim.PhysShape); @@ -519,7 +519,7 @@ public sealed class BSShapeCollection : IDisposable // Creates a native shape and assignes it to prim.BSShape. // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape(). private bool GetReferenceToNativeShape(BSPhysObject prim, - ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, + PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, ShapeDestructionCallback shapeCallback) { // release any previous shape @@ -538,7 +538,7 @@ public sealed class BSShapeCollection : IDisposable return true; } - private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, ShapeData.PhysicsShapeType shapeType, + private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) { BulletShape newShape; @@ -551,7 +551,7 @@ public sealed class BSShapeCollection : IDisposable nativeShapeData.MeshKey = (ulong)shapeKey; nativeShapeData.HullKey = (ulong)shapeKey; - if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) + if (shapeType == PhysicsShapeType.SHAPE_AVATAR) { newShape = new BulletShape( BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale) @@ -585,7 +585,7 @@ public sealed class BSShapeCollection : IDisposable System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); // if this new shape is the same as last time, don't recreate the mesh - if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) + if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == PhysicsShapeType.SHAPE_MESH) return false; DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}", @@ -643,7 +643,7 @@ public sealed class BSShapeCollection : IDisposable indices.GetLength(0), indices, vertices.Count, verticesAsFloats); } } - BulletShape newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH); + BulletShape newShape = new BulletShape(meshPtr, PhysicsShapeType.SHAPE_MESH); newShape.shapeKey = newMeshKey; return newShape; @@ -659,7 +659,7 @@ public sealed class BSShapeCollection : IDisposable System.UInt64 newHullKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); // if the hull hasn't changed, don't rebuild it - if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) + if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == PhysicsShapeType.SHAPE_HULL) return false; DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}", @@ -780,7 +780,7 @@ public sealed class BSShapeCollection : IDisposable } } - BulletShape newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL); + BulletShape newShape = new BulletShape(hullPtr, PhysicsShapeType.SHAPE_HULL); newShape.shapeKey = newHullKey; return newShape; // 'true' means a new shape has been added to this prim @@ -803,7 +803,7 @@ public sealed class BSShapeCollection : IDisposable // DereferenceShape(prim.PhysShape, true, shapeCallback); BulletShape cShape = new BulletShape( - BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr, false), ShapeData.PhysicsShapeType.SHAPE_COMPOUND); + BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr, false), PhysicsShapeType.SHAPE_COMPOUND); // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape. CreateGeomMeshOrHull(prim, shapeCallback); @@ -894,7 +894,7 @@ public sealed class BSShapeCollection : IDisposable // While we figure out the real problem, stick a simple native shape on the object. BulletShape fillinShape = - BuildPhysicalNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX); + BuildPhysicalNativeShape(prim, PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX); return fillinShape; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs index d59a486..2896805 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs @@ -35,7 +35,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin public abstract class BSShape { public IntPtr ptr { get; set; } - public ShapeData.PhysicsShapeType type { get; set; } + public PhysicsShapeType type { get; set; } public System.UInt64 key { get; set; } public int referenceCount { get; set; } public DateTime lastReferenced { get; set; } @@ -43,7 +43,7 @@ public abstract class BSShape public BSShape() { ptr = IntPtr.Zero; - type = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; + type = PhysicsShapeType.SHAPE_UNKNOWN; key = 0; referenceCount = 0; lastReferenced = DateTime.Now; @@ -54,17 +54,17 @@ public abstract class BSShape { BSShape ret = null; - if (prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR) + if (prim.PreferredPhysicalShape == PhysicsShapeType.SHAPE_AVATAR) { // an avatar capsule is close to a native shape (it is not shared) - ret = BSShapeNative.GetReference(physicsScene, prim, ShapeData.PhysicsShapeType.SHAPE_AVATAR, + ret = BSShapeNative.GetReference(physicsScene, prim, PhysicsShapeType.SHAPE_AVATAR, ShapeData.FixedShapeKey.KEY_CAPSULE); physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret); } // Compound shapes are handled special as they are rebuilt from scratch. // This isn't too great a hardship since most of the child shapes will already been created. - if (ret == null && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_COMPOUND) + if (ret == null && prim.PreferredPhysicalShape == PhysicsShapeType.SHAPE_COMPOUND) { // Getting a reference to a compound shape gets you the compound shape with the root prim shape added ret = BSShapeCompound.GetReference(prim); @@ -123,14 +123,14 @@ public class BSShapeNative : BSShape { } public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim, - ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) + PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) { // Native shapes are not shared and are always built anew. return new BSShapeNative(physicsScene, prim, shapeType, shapeKey); } private BSShapeNative(BSScene physicsScene, BSPhysObject prim, - ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) + PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) { ShapeData nativeShapeData = new ShapeData(); nativeShapeData.Type = shapeType; @@ -141,7 +141,7 @@ public class BSShapeNative : BSShape nativeShapeData.HullKey = (ulong)shapeKey; - if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) + if (shapeType == PhysicsShapeType.SHAPE_AVATAR) { ptr = BulletSimAPI.BuildCapsuleShape2(physicsScene.World.ptr, 1f, 1f, prim.Scale); physicsScene.DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 7c34af2..cc28e4d 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -109,7 +109,7 @@ public sealed class BSTerrainManager // The ground plane is here to catch things that are trying to drop to negative infinity BulletShape groundPlaneShape = new BulletShape( BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN), - ShapeData.PhysicsShapeType.SHAPE_GROUNDPLANE); + PhysicsShapeType.SHAPE_GROUNDPLANE); m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID, BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID, Vector3.Zero, Quaternion.Identity)); @@ -299,7 +299,7 @@ public sealed class BSTerrainManager // Create the terrain shape from the mapInfo mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr), - ShapeData.PhysicsShapeType.SHAPE_TERRAIN); + PhysicsShapeType.SHAPE_TERRAIN); // The terrain object initial position is at the center of the object Vector3 centerPos; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 28fae13..bb63b0a 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -88,11 +88,11 @@ public struct BulletShape public BulletShape(IntPtr xx) { ptr = xx; - type=ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; + type=PhysicsShapeType.SHAPE_UNKNOWN; shapeKey = 0; isNativeShape = false; } - public BulletShape(IntPtr xx, ShapeData.PhysicsShapeType typ) + public BulletShape(IntPtr xx, PhysicsShapeType typ) { ptr = xx; type = typ; @@ -100,7 +100,7 @@ public struct BulletShape isNativeShape = false; } public IntPtr ptr; - public ShapeData.PhysicsShapeType type; + public PhysicsShapeType type; public System.UInt64 shapeKey; public bool isNativeShape; public override string ToString() @@ -178,24 +178,25 @@ public struct ConvexHull int VertexCount; Vector3[] Vertices; } +public enum PhysicsShapeType +{ + SHAPE_UNKNOWN = 0, + SHAPE_AVATAR = 1, + SHAPE_BOX = 2, + SHAPE_CONE = 3, + SHAPE_CYLINDER = 4, + SHAPE_SPHERE = 5, + SHAPE_MESH = 6, + SHAPE_HULL = 7, + // following defined by BulletSim + SHAPE_GROUNDPLANE = 20, + SHAPE_TERRAIN = 21, + SHAPE_COMPOUND = 22, + SHAPE_HEIGHTMAP = 23, +}; [StructLayout(LayoutKind.Sequential)] public struct ShapeData { - public enum PhysicsShapeType - { - SHAPE_UNKNOWN = 0, - SHAPE_AVATAR = 1, - SHAPE_BOX = 2, - SHAPE_CONE = 3, - SHAPE_CYLINDER = 4, - SHAPE_SPHERE = 5, - SHAPE_MESH = 6, - SHAPE_HULL = 7, - // following defined by BulletSim - SHAPE_GROUNDPLANE = 20, - SHAPE_TERRAIN = 21, - SHAPE_COMPOUND = 22, - }; public uint ID; public PhysicsShapeType Type; public Vector3 Position; -- cgit v1.1 From 65e55ada87e110b65f3d69eb0a4f2402fb1f3ece Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 20 Nov 2012 11:30:22 -0800 Subject: BulletSim: uplevel FixedShapeKey out of ShapeData structure (since it is getting simplified out of existance someday) and update all the references to same. --- .../Physics/BulletSPlugin/BSShapeCollection.cs | 12 +++++------ OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs | 6 +++--- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 24 ++++++++++++---------- 3 files changed, 22 insertions(+), 20 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 746a52e..0232618 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -409,7 +409,7 @@ public sealed class BSShapeCollection : IDisposable { // an avatar capsule is close to a native shape (it is not shared) ret = GetReferenceToNativeShape(prim, PhysicsShapeType.SHAPE_AVATAR, - ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback); + FixedShapeKey.KEY_CAPSULE, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape); ret = true; haveShape = true; @@ -464,7 +464,7 @@ public sealed class BSShapeCollection : IDisposable ) { ret = GetReferenceToNativeShape(prim, PhysicsShapeType.SHAPE_SPHERE, - ShapeData.FixedShapeKey.KEY_SPHERE, shapeCallback); + FixedShapeKey.KEY_SPHERE, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", prim.LocalID, forceRebuild, prim.PhysShape); } @@ -478,7 +478,7 @@ public sealed class BSShapeCollection : IDisposable ) { ret = GetReferenceToNativeShape( prim, PhysicsShapeType.SHAPE_BOX, - ShapeData.FixedShapeKey.KEY_BOX, shapeCallback); + FixedShapeKey.KEY_BOX, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", prim.LocalID, forceRebuild, prim.PhysShape); } @@ -519,7 +519,7 @@ public sealed class BSShapeCollection : IDisposable // Creates a native shape and assignes it to prim.BSShape. // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape(). private bool GetReferenceToNativeShape(BSPhysObject prim, - PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, + PhysicsShapeType shapeType, FixedShapeKey shapeKey, ShapeDestructionCallback shapeCallback) { // release any previous shape @@ -539,7 +539,7 @@ public sealed class BSShapeCollection : IDisposable } private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, PhysicsShapeType shapeType, - ShapeData.FixedShapeKey shapeKey) + FixedShapeKey shapeKey) { BulletShape newShape; // Need to make sure the passed shape information is for the native type. @@ -894,7 +894,7 @@ public sealed class BSShapeCollection : IDisposable // While we figure out the real problem, stick a simple native shape on the object. BulletShape fillinShape = - BuildPhysicalNativeShape(prim, PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX); + BuildPhysicalNativeShape(prim, PhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX); return fillinShape; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs index 2896805..71b5074 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs @@ -58,7 +58,7 @@ public abstract class BSShape { // an avatar capsule is close to a native shape (it is not shared) ret = BSShapeNative.GetReference(physicsScene, prim, PhysicsShapeType.SHAPE_AVATAR, - ShapeData.FixedShapeKey.KEY_CAPSULE); + FixedShapeKey.KEY_CAPSULE); physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret); } @@ -123,14 +123,14 @@ public class BSShapeNative : BSShape { } public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim, - PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) + PhysicsShapeType shapeType, FixedShapeKey shapeKey) { // Native shapes are not shared and are always built anew. return new BSShapeNative(physicsScene, prim, shapeType, shapeKey); } private BSShapeNative(BSScene physicsScene, BSPhysObject prim, - PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) + PhysicsShapeType shapeType, FixedShapeKey shapeKey) { ShapeData nativeShapeData = new ShapeData(); nativeShapeData.Type = shapeType; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index bb63b0a..75e7f99 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -89,7 +89,7 @@ public struct BulletShape { ptr = xx; type=PhysicsShapeType.SHAPE_UNKNOWN; - shapeKey = 0; + shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE; isNativeShape = false; } public BulletShape(IntPtr xx, PhysicsShapeType typ) @@ -194,6 +194,18 @@ public enum PhysicsShapeType SHAPE_COMPOUND = 22, SHAPE_HEIGHTMAP = 23, }; + +// The native shapes have predefined shape hash keys +public enum FixedShapeKey : ulong +{ + KEY_NONE = 0, + KEY_BOX = 1, + KEY_SPHERE = 2, + KEY_CONE = 3, + KEY_CYLINDER = 4, + KEY_CAPSULE = 5, +} + [StructLayout(LayoutKind.Sequential)] public struct ShapeData { @@ -217,16 +229,6 @@ public struct ShapeData // note that bools are passed as floats since bool size changes by language and architecture public const float numericTrue = 1f; public const float numericFalse = 0f; - - // The native shapes have predefined shape hash keys - public enum FixedShapeKey : ulong - { - KEY_BOX = 1, - KEY_SPHERE = 2, - KEY_CONE = 3, - KEY_CYLINDER = 4, - KEY_CAPSULE = 5, - } } [StructLayout(LayoutKind.Sequential)] public struct SweepHit -- cgit v1.1 From 8dd5813889b17cc213d20491b41dbf8142b3ccb9 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 20 Nov 2012 11:33:42 -0800 Subject: BulletSim: rename SHAPE_AVATAR to SHAPE_CAPSULE with the eye to eventually having mesh avatars. --- OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | 6 +++--- OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs | 6 +++--- OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 92ff804..799211e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -205,7 +205,7 @@ public sealed class BSCharacter : BSPhysObject // I want the physics engine to make an avatar capsule public override PhysicsShapeType PreferredPhysicalShape { - get {return PhysicsShapeType.SHAPE_AVATAR; } + get {return PhysicsShapeType.SHAPE_CAPSULE; } } public override bool Grabbed { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 0232618..a53ad6e 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -405,10 +405,10 @@ public sealed class BSShapeCollection : IDisposable bool ret = false; bool haveShape = false; - if (!haveShape && prim.PreferredPhysicalShape == PhysicsShapeType.SHAPE_AVATAR) + if (!haveShape && prim.PreferredPhysicalShape == PhysicsShapeType.SHAPE_CAPSULE) { // an avatar capsule is close to a native shape (it is not shared) - ret = GetReferenceToNativeShape(prim, PhysicsShapeType.SHAPE_AVATAR, + ret = GetReferenceToNativeShape(prim, PhysicsShapeType.SHAPE_CAPSULE, FixedShapeKey.KEY_CAPSULE, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape); ret = true; @@ -551,7 +551,7 @@ public sealed class BSShapeCollection : IDisposable nativeShapeData.MeshKey = (ulong)shapeKey; nativeShapeData.HullKey = (ulong)shapeKey; - if (shapeType == PhysicsShapeType.SHAPE_AVATAR) + if (shapeType == PhysicsShapeType.SHAPE_CAPSULE) { newShape = new BulletShape( BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs index 71b5074..f2e62d9 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs @@ -54,10 +54,10 @@ public abstract class BSShape { BSShape ret = null; - if (prim.PreferredPhysicalShape == PhysicsShapeType.SHAPE_AVATAR) + if (prim.PreferredPhysicalShape == PhysicsShapeType.SHAPE_CAPSULE) { // an avatar capsule is close to a native shape (it is not shared) - ret = BSShapeNative.GetReference(physicsScene, prim, PhysicsShapeType.SHAPE_AVATAR, + ret = BSShapeNative.GetReference(physicsScene, prim, PhysicsShapeType.SHAPE_CAPSULE, FixedShapeKey.KEY_CAPSULE); physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret); } @@ -141,7 +141,7 @@ public class BSShapeNative : BSShape nativeShapeData.HullKey = (ulong)shapeKey; - if (shapeType == PhysicsShapeType.SHAPE_AVATAR) + if (shapeType == PhysicsShapeType.SHAPE_CAPSULE) { ptr = BulletSimAPI.BuildCapsuleShape2(physicsScene.World.ptr, 1f, 1f, prim.Scale); physicsScene.DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 75e7f99..407d6d7 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -181,7 +181,7 @@ public struct ConvexHull public enum PhysicsShapeType { SHAPE_UNKNOWN = 0, - SHAPE_AVATAR = 1, + SHAPE_CAPSULE = 1, SHAPE_BOX = 2, SHAPE_CONE = 3, SHAPE_CYLINDER = 4, -- cgit v1.1 From 71b9640dfa67e830769aad64ef208d767e102c92 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 20 Nov 2012 14:51:50 -0800 Subject: BulletSim: pull heightmap implementation out of the terrain manager so a mesh terrain can be implemented. --- .../Physics/BulletSPlugin/BSTerrainHeightmap.cs | 174 ++++++++++++++ .../Physics/BulletSPlugin/BSTerrainManager.cs | 257 +++++++-------------- .../Region/Physics/BulletSPlugin/BSTerrainMesh.cs | 73 ++++++ .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 4 +- 4 files changed, 327 insertions(+), 181 deletions(-) create mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs create mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs new file mode 100755 index 0000000..3bb63cd --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs @@ -0,0 +1,174 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; + +using OpenSim.Framework; +using OpenSim.Region.Framework; +using OpenSim.Region.CoreModules; +using OpenSim.Region.Physics.Manager; + +using Nini.Config; +using log4net; + +using OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ +public sealed class BSTerrainHeightmap : BSTerrainPhys +{ + static string LogHeader = "[BULLETSIM TERRAIN HEIGHTMAP]"; + + BulletHeightMapInfo m_mapInfo; + + public BSTerrainHeightmap(BSScene physicsScene, uint id, Vector3 regionSize) + : base(physicsScene) + { + Vector3 minTerrainCoords = new Vector3(0f, 0f, BSTerrainManager.HEIGHT_INITIALIZATION - BSTerrainManager.HEIGHT_EQUAL_FUDGE); + Vector3 maxTerrainCoords = new Vector3(regionSize.X, regionSize.Y, BSTerrainManager.HEIGHT_INITIALIZATION); + int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y; + float[] initialMap = new float[totalHeights]; + for (int ii = 0; ii < totalHeights; ii++) + { + initialMap[ii] = BSTerrainManager.HEIGHT_INITIALIZATION; + } + m_mapInfo = new BulletHeightMapInfo(id, initialMap, IntPtr.Zero); + m_mapInfo.minCoords = minTerrainCoords; + m_mapInfo.maxCoords = maxTerrainCoords; + // Don't have to free any previous since we just got here. + BuildHeightmapTerrain(); + } + + // This minCoords and maxCoords passed in give the size of the terrain (min and max Z + // are the high and low points of the heightmap). + public BSTerrainHeightmap(BSScene physicsScene, uint id, float[] initialMap, + Vector3 minCoords, Vector3 maxCoords) + : base(physicsScene) + { + m_mapInfo = new BulletHeightMapInfo(id, initialMap, IntPtr.Zero); + m_mapInfo.minCoords = minCoords; + m_mapInfo.maxCoords = maxCoords; + m_mapInfo.minZ = minCoords.Z; + m_mapInfo.maxZ = maxCoords.Z; + + // Don't have to free any previous since we just got here. + BuildHeightmapTerrain(); + } + + public override void Dispose() + { + ReleaseHeightMapTerrain(); + } + + // Using the information in m_mapInfo, create the physical representation of the heightmap. + private void BuildHeightmapTerrain() + { + m_mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, m_mapInfo.ID, + m_mapInfo.minCoords, m_mapInfo.maxCoords, + m_mapInfo.heightMap, BSTerrainManager.TERRAIN_COLLISION_MARGIN); + + // Create the terrain shape from the mapInfo + m_mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(m_mapInfo.Ptr), + PhysicsShapeType.SHAPE_TERRAIN); + + // The terrain object initial position is at the center of the object + Vector3 centerPos; + centerPos.X = m_mapInfo.minCoords.X + (m_mapInfo.sizeX / 2f); + centerPos.Y = m_mapInfo.minCoords.Y + (m_mapInfo.sizeY / 2f); + centerPos.Z = m_mapInfo.minZ + ((m_mapInfo.maxZ - m_mapInfo.minZ) / 2f); + + m_mapInfo.terrainBody = new BulletBody(m_mapInfo.ID, + BulletSimAPI.CreateBodyWithDefaultMotionState2(m_mapInfo.terrainShape.ptr, + m_mapInfo.ID, centerPos, Quaternion.Identity)); + + // Set current terrain attributes + BulletSimAPI.SetFriction2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainFriction); + BulletSimAPI.SetHitFraction2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainHitFraction); + BulletSimAPI.SetRestitution2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution); + BulletSimAPI.SetCollisionFlags2(m_mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); + + // Return the new terrain to the world of physical objects + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); + + // redo its bounding box now that it is in the world + BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); + + BulletSimAPI.SetCollisionFilterMask2(m_mapInfo.terrainBody.ptr, + (uint)CollisionFilterGroups.TerrainFilter, + (uint)CollisionFilterGroups.TerrainMask); + + // Make it so the terrain will not move or be considered for movement. + BulletSimAPI.ForceActivationState2(m_mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); + + return; + } + + // If there is information in m_mapInfo pointing to physical structures, release same. + private void ReleaseHeightMapTerrain() + { + if (m_mapInfo != null) + { + if (m_mapInfo.terrainBody.ptr != IntPtr.Zero) + { + if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr)) + { + // Frees both the body and the shape. + BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); + BulletSimAPI.ReleaseHeightMapInfo2(m_mapInfo.Ptr); + } + } + } + m_mapInfo = null; + } + + // The passed position is relative to the base of the region. + public override float GetHeightAtXYZ(Vector3 pos) + { + float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; + + int mapIndex = (int)pos.Y * (int)m_mapInfo.sizeY + (int)pos.X; + try + { + ret = m_mapInfo.heightMap[mapIndex]; + } + catch + { + // Sometimes they give us wonky values of X and Y. Give a warning and return something. + PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}", + LogHeader, m_mapInfo.terrainRegionBase, pos); + ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; + } + return ret; + } + + public override Vector3 TerrainBase + { + get { return m_mapInfo.terrainRegionBase; } + } +} +} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index cc28e4d..db04299 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -40,6 +40,22 @@ using OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin { + +// The physical implementation of the terrain is wrapped in this class. +public abstract class BSTerrainPhys : IDisposable +{ + public BSScene PhysicsScene { get; private set; } + + public BSTerrainPhys(BSScene physicsScene) + { + PhysicsScene = physicsScene; + } + public abstract void Dispose(); + public abstract float GetHeightAtXYZ(Vector3 pos); + public abstract Vector3 TerrainBase { get; } +} + +// ========================================================================================== public sealed class BSTerrainManager { static string LogHeader = "[BULLETSIM TERRAIN MANAGER]"; @@ -67,11 +83,10 @@ public sealed class BSTerrainManager // If doing mega-regions, if we're region zero we will be managing multiple // region terrains since region zero does the physics for the whole mega-region. - private Dictionary m_heightMaps; + private Dictionary m_terrains; - // True of the terrain has been modified. - // Used to force recalculation of terrain height after terrain has been modified - private bool m_terrainModified; + // Flags used to know when to recalculate the height. + private bool m_terrainModified = false; // If we are doing mega-regions, terrains are added from TERRAIN_ID to m_terrainCount. // This is incremented before assigning to new region so it is the last ID allocated. @@ -89,8 +104,7 @@ public sealed class BSTerrainManager public BSTerrainManager(BSScene physicsScene) { PhysicsScene = physicsScene; - m_heightMaps = new Dictionary(); - m_terrainModified = false; + m_terrains = new Dictionary(); // Assume one region of default size m_worldOffset = Vector3.Zero; @@ -99,9 +113,6 @@ public sealed class BSTerrainManager } // Create the initial instance of terrain and the underlying ground plane. - // The objects are allocated in the unmanaged space and the pointers are tracked - // by the managed code. - // The terrains and the groundPlane are not added to the list of PhysObjects. // 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. public void CreateInitialGroundPlaneAndTerrain() @@ -121,15 +132,9 @@ public sealed class BSTerrainManager BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr, (uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask); - Vector3 minTerrainCoords = new Vector3(0f, 0f, HEIGHT_INITIALIZATION - HEIGHT_EQUAL_FUDGE); - Vector3 maxTerrainCoords = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, HEIGHT_INITIALIZATION); - int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y; - float[] initialMap = new float[totalHeights]; - for (int ii = 0; ii < totalHeights; ii++) - { - initialMap[ii] = HEIGHT_INITIALIZATION; - } - UpdateOrCreateTerrain(BSScene.TERRAIN_ID, initialMap, minTerrainCoords, maxTerrainCoords, true); + // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain. + BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, BSScene.TERRAIN_ID, DefaultRegionSize); + m_terrains.Add(Vector3.Zero, initialTerrain); } // Release all the terrain structures we might have allocated @@ -150,15 +155,11 @@ public sealed class BSTerrainManager // Release all the terrain we have allocated public void ReleaseTerrain() { - foreach (KeyValuePair kvp in m_heightMaps) + foreach (KeyValuePair kvp in m_terrains) { - if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, kvp.Value.terrainBody.ptr)) - { - BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, kvp.Value.terrainBody.ptr); - BulletSimAPI.ReleaseHeightMapInfo2(kvp.Value.Ptr); - } + kvp.Value.Dispose(); } - m_heightMaps.Clear(); + m_terrains.Clear(); } // The simulator wants to set a new heightmap for the terrain. @@ -176,8 +177,9 @@ public sealed class BSTerrainManager { DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}", BSScene.DetailLogZero, m_worldOffset, m_worldMax); - ((BSScene)MegaRegionParentPhysicsScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID, - localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize, true); + ((BSScene)MegaRegionParentPhysicsScene).TerrainManager.UpdateTerrain( + BSScene.CHILDTERRAIN_ID, localHeightMap, + m_worldOffset, m_worldOffset + DefaultRegionSize, true); } } else @@ -185,7 +187,7 @@ public sealed class BSTerrainManager // If not doing the mega-prim thing, just change the terrain DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero); - UpdateOrCreateTerrain(BSScene.TERRAIN_ID, localHeightMap, + UpdateTerrain(BSScene.TERRAIN_ID, localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize, true); } }); @@ -195,56 +197,60 @@ public sealed class BSTerrainManager // based on the passed information. The 'id' should be either the terrain id or // BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used. // The latter feature is for creating child terrains for mega-regions. - // If called with a mapInfo in m_heightMaps but the terrain has no body yet (mapInfo.terrainBody.Ptr == 0) - // then a new body and shape is created and the mapInfo is filled. - // This call is used for doing the initial terrain creation. // If called with a mapInfo in m_heightMaps and there is an existing terrain body, a new // terrain shape is created and added to the body. // This call is most often used to update the heightMap and parameters of the terrain. // (The above does suggest that some simplification/refactoring is in order.) - private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool inTaintTime) + private void UpdateTerrain(uint id, float[] heightMap, + Vector3 minCoords, Vector3 maxCoords, bool inTaintTime) { - DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},inTaintTime={3}", + DetailLog("{0},BSTerrainManager.UpdateTerrain,call,minC={1},maxC={2},inTaintTime={3}", BSScene.DetailLogZero, minCoords, maxCoords, inTaintTime); + // Find high and low points of passed heightmap. + // The min and max passed in are usually the region objects can exist in (maximum + // object height, for instance). The terrain wants the bounding box for the + // terrain so we replace passed min and max Z with the actual terrain min/max Z. + // limit, for float minZ = float.MaxValue; float maxZ = float.MinValue; - Vector2 terrainRegionBase = new Vector2(minCoords.X, minCoords.Y); - - int heightMapSize = heightMap.Length; - for (int ii = 0; ii < heightMapSize; ii++) + foreach (float height in heightMap) { - float height = heightMap[ii]; if (height < minZ) minZ = height; if (height > maxZ) maxZ = height; } - - // The shape of the terrain is from its base to its extents. minCoords.Z = minZ; maxCoords.Z = maxZ; - BulletHeightMapInfo mapInfo; - if (m_heightMaps.TryGetValue(terrainRegionBase, out mapInfo)) + Vector3 terrainRegionBase = new Vector3(minCoords.X, minCoords.Y, 0f); + + BSTerrainPhys terrainPhys; + if (m_terrains.TryGetValue(terrainRegionBase, out terrainPhys)) { // If this is terrain we know about, it's easy to update - mapInfo.heightMap = heightMap; - mapInfo.minCoords = minCoords; - mapInfo.maxCoords = maxCoords; - mapInfo.minZ = minZ; - mapInfo.maxZ = maxZ; - mapInfo.sizeX = maxCoords.X - minCoords.X; - mapInfo.sizeY = maxCoords.Y - minCoords.Y; - DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,call,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}", - BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY); - - PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateOrCreateTerrain:UpdateExisting", delegate() + DetailLog("{0},UpdateTerrain:UpdateExisting,call,terrainBase={1}", BSScene.DetailLogZero, terrainRegionBase); + + PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateTerrain:UpdateExisting", delegate() { - if (MegaRegionParentPhysicsScene != null) + // Remove old terrain from the collection + m_terrains.Remove(terrainPhys.TerrainBase); + // Release any physical memory it may be using. + terrainPhys.Dispose(); + + if (MegaRegionParentPhysicsScene == null) + { + BSTerrainPhys newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, id, + heightMap, minCoords, maxCoords); + m_terrains.Add(terrainRegionBase, newTerrainPhys); + + m_terrainModified = true; + } + else { // It's possible that Combine() was called after this code was queued. // If we are a child of combined regions, we don't create any terrain for us. - DetailLog("{0},UpdateOrCreateTerrain:AmACombineChild,taint", BSScene.DetailLogZero); + DetailLog("{0},BSTerrainManager.UpdateTerrain:AmACombineChild,taint", BSScene.DetailLogZero); // Get rid of any terrain that may have been allocated for us. ReleaseGroundPlaneAndTerrain(); @@ -252,91 +258,6 @@ public sealed class BSTerrainManager // I hate doing this, but just bail return; } - - if (mapInfo.terrainBody.ptr != IntPtr.Zero) - { - // Updating an existing terrain. - DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,taint,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}", - BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY); - - // Remove from the dynamics world because we're going to mangle this object - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); - - // Get rid of the old terrain - BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); - BulletSimAPI.ReleaseHeightMapInfo2(mapInfo.Ptr); - mapInfo.Ptr = IntPtr.Zero; - - /* - // NOTE: This routine is half here because I can't get the terrain shape replacement - // to work. In the short term, the above three lines completely delete the old - // terrain and the code below recreates one from scratch. - // Hopefully the Bullet community will help me out on this one. - - // First, release the old collision shape (there is only one terrain) - BulletSimAPI.DeleteCollisionShape2(m_physicsScene.World.Ptr, mapInfo.terrainShape.Ptr); - - // Fill the existing height map info with the new location and size information - BulletSimAPI.FillHeightMapInfo2(m_physicsScene.World.Ptr, mapInfo.Ptr, mapInfo.ID, - mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN); - - // Create a terrain shape based on the new info - mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr)); - - // Stuff the shape into the existing terrain body - BulletSimAPI.SetBodyShape2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr, mapInfo.terrainShape.Ptr); - */ - } - // else - { - // Creating a new terrain. - DetailLog("{0},UpdateOrCreateTerrain:CreateNewTerrain,taint,baseX={1},baseY={2},minZ={3},maxZ={4}", - BSScene.DetailLogZero, mapInfo.minCoords.X, mapInfo.minCoords.Y, minZ, maxZ); - - mapInfo.ID = id; - mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, mapInfo.ID, - mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN); - - // Create the terrain shape from the mapInfo - mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr), - PhysicsShapeType.SHAPE_TERRAIN); - - // The terrain object initial position is at the center of the object - Vector3 centerPos; - centerPos.X = minCoords.X + (mapInfo.sizeX / 2f); - centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f); - centerPos.Z = minZ + ((maxZ - minZ) / 2f); - - mapInfo.terrainBody = new BulletBody(mapInfo.ID, - BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.ptr, - id, centerPos, Quaternion.Identity)); - } - - // Make sure the entry is in the heightmap table - m_heightMaps[terrainRegionBase] = mapInfo; - - // Set current terrain attributes - BulletSimAPI.SetFriction2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainFriction); - BulletSimAPI.SetHitFraction2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainHitFraction); - BulletSimAPI.SetRestitution2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution); - BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); - - // Return the new terrain to the world of physical objects - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); - - // redo its bounding box now that it is in the world - BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); - - BulletSimAPI.SetCollisionFilterMask2(mapInfo.terrainBody.ptr, - (uint)CollisionFilterGroups.TerrainFilter, - (uint)CollisionFilterGroups.TerrainMask); - - // Make sure the new shape is processed. - // BulletSimAPI.Activate2(mapInfo.terrainBody.ptr, true); - // BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.ISLAND_SLEEPING); - BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); - - m_terrainModified = true; }); } else @@ -353,34 +274,23 @@ public sealed class BSTerrainManager Vector3 minCoordsX = minCoords; Vector3 maxCoordsX = maxCoords; - DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,call,id={1}, minC={2}, maxC={3}", + DetailLog("{0},UpdateTerrain:NewTerrain,call,id={1}, minC={2}, maxC={3}", BSScene.DetailLogZero, newTerrainID, minCoords, minCoords); // Code that must happen at taint-time - PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateOrCreateTerrain:NewTerrain", delegate() + PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateTerrain:NewTerrain", delegate() { - DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y); - // Create a new mapInfo that will be filled with the new info - mapInfo = new BulletHeightMapInfo(id, heightMapX, - BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, newTerrainID, - minCoordsX, maxCoordsX, heightMapX, TERRAIN_COLLISION_MARGIN)); - // Put the unfilled heightmap info into the collection of same - m_heightMaps.Add(terrainRegionBase, mapInfo); - // Build the terrain - UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true); + DetailLog("{0},UpdateTerrain:NewTerrain,taint,baseX={1},baseY={2}", + BSScene.DetailLogZero, minCoordsX.X, minCoordsX.Y); + BSTerrainPhys newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, newTerrainID, + heightMapX, minCoordsX, maxCoordsX); + m_terrains.Add(terrainRegionBase, newTerrainPhys); m_terrainModified = true; }); } } - // Someday we will have complex terrain with caves and tunnels - public float GetTerrainHeightAtXYZ(Vector3 loc) - { - // For the moment, it's flat and convex - return GetTerrainHeightAtXY(loc.X, loc.Y); - } - // Given an X and Y, find the height of the terrain. // Since we could be handling multiple terrains for a mega-region, // the base of the region is calcuated assuming all regions are @@ -390,8 +300,10 @@ public sealed class BSTerrainManager private float lastHeightTX = 999999f; private float lastHeightTY = 999999f; private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT; - private float GetTerrainHeightAtXY(float tX, float tY) + public float GetTerrainHeightAtXYZ(Vector3 loc) { + float tX = loc.X; + float tY = loc.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) @@ -403,27 +315,14 @@ public sealed class BSTerrainManager int offsetX = ((int)(tX / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X; int offsetY = ((int)(tY / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y; - Vector2 terrainBaseXY = new Vector2(offsetX, offsetY); + Vector3 terrainBaseXYZ = new Vector3(offsetX, offsetY, 0f); - BulletHeightMapInfo mapInfo; - if (m_heightMaps.TryGetValue(terrainBaseXY, out mapInfo)) + BSTerrainPhys physTerrain; + if (m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain)) { - float regionX = tX - offsetX; - float regionY = tY - offsetY; - int mapIndex = (int)regionY * (int)mapInfo.sizeY + (int)regionX; - try - { - ret = mapInfo.heightMap[mapIndex]; - } - catch - { - // Sometimes they give us wonky values of X and Y. Give a warning and return something. - PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, x={2}, y={3}", - LogHeader, terrainBaseXY, regionX, regionY); - ret = HEIGHT_GETHEIGHT_RET; - } - // DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXY,bX={1},baseY={2},szX={3},szY={4},regX={5},regY={6},index={7},ht={8}", - // BSScene.DetailLogZero, offsetX, offsetY, mapInfo.sizeX, mapInfo.sizeY, regionX, regionY, mapIndex, ret); + ret = physTerrain.GetHeightAtXYZ(loc - terrainBaseXYZ); + DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXYZ,loc={1},base={2},height={3}", + BSScene.DetailLogZero, loc, terrainBaseXYZ, ret); } else { @@ -466,7 +365,7 @@ public sealed class BSTerrainManager // Unhook all the combining that I know about. public void UnCombine(PhysicsScene pScene) { - // Just like ODE, for the moment a NOP + // Just like ODE, we don't do anything yet. DetailLog("{0},BSTerrainManager.UnCombine", BSScene.DetailLogZero); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs new file mode 100755 index 0000000..387c78b --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs @@ -0,0 +1,73 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; + +using OpenSim.Framework; +using OpenSim.Region.Framework; +using OpenSim.Region.CoreModules; +using OpenSim.Region.Physics.Manager; + +using Nini.Config; +using log4net; + +using OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ +public sealed class BSTerrainMesh : BSTerrainPhys +{ + static string LogHeader = "[BULLETSIM TERRAIN MESH]"; + + public BSTerrainMesh(BSScene physicsScene, uint id, Vector3 regionSize) + : base(physicsScene) + { + } + + public BSTerrainMesh(BSScene physicsScene /* parameters for making mesh */) + : base(physicsScene) + { + } + + public override void Dispose() + { + return; + } + + public override float GetHeightAtXYZ(Vector3 pos) + { + return 12345f; + } + + public override Vector3 TerrainBase + { + get { return Vector3.Zero; } + } + +} +} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 407d6d7..bab3b3d 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -152,7 +152,7 @@ public class BulletHeightMapInfo ID = id; Ptr = xx; heightMap = hm; - terrainRegionBase = new Vector2(0f, 0f); + terrainRegionBase = Vector3.Zero; minCoords = new Vector3(100f, 100f, 25f); maxCoords = new Vector3(101f, 101f, 26f); minZ = maxZ = 0f; @@ -161,7 +161,7 @@ public class BulletHeightMapInfo public uint ID; public IntPtr Ptr; public float[] heightMap; - public Vector2 terrainRegionBase; + public Vector3 terrainRegionBase; public Vector3 minCoords; public Vector3 maxCoords; public float sizeX, sizeY; -- cgit v1.1 From 34cbc738a84b7946a87e8bfd3bb04869519b3dee Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 20 Nov 2012 20:36:49 -0800 Subject: BulletSim: enablement and debugging of mesh terrain. --- .../Physics/BulletSPlugin/BSTerrainHeightmap.cs | 28 ++- .../Physics/BulletSPlugin/BSTerrainManager.cs | 26 ++- .../Region/Physics/BulletSPlugin/BSTerrainMesh.cs | 229 ++++++++++++++++++++- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 6 +- 4 files changed, 253 insertions(+), 36 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs index 3bb63cd..e9fd0cb 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs @@ -44,10 +44,11 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys { static string LogHeader = "[BULLETSIM TERRAIN HEIGHTMAP]"; - BulletHeightMapInfo m_mapInfo; + BulletHeightMapInfo m_mapInfo = null; - public BSTerrainHeightmap(BSScene physicsScene, uint id, Vector3 regionSize) - : base(physicsScene) + // Constructor to build a default, flat heightmap terrain. + public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize) + : base(physicsScene, regionBase, id) { Vector3 minTerrainCoords = new Vector3(0f, 0f, BSTerrainManager.HEIGHT_INITIALIZATION - BSTerrainManager.HEIGHT_EQUAL_FUDGE); Vector3 maxTerrainCoords = new Vector3(regionSize.X, regionSize.Y, BSTerrainManager.HEIGHT_INITIALIZATION); @@ -60,21 +61,23 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys m_mapInfo = new BulletHeightMapInfo(id, initialMap, IntPtr.Zero); m_mapInfo.minCoords = minTerrainCoords; m_mapInfo.maxCoords = maxTerrainCoords; + m_mapInfo.terrainRegionBase = TerrainBase; // Don't have to free any previous since we just got here. BuildHeightmapTerrain(); } // This minCoords and maxCoords passed in give the size of the terrain (min and max Z // are the high and low points of the heightmap). - public BSTerrainHeightmap(BSScene physicsScene, uint id, float[] initialMap, + public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap, Vector3 minCoords, Vector3 maxCoords) - : base(physicsScene) + : base(physicsScene, regionBase, id) { m_mapInfo = new BulletHeightMapInfo(id, initialMap, IntPtr.Zero); m_mapInfo.minCoords = minCoords; m_mapInfo.maxCoords = maxCoords; m_mapInfo.minZ = minCoords.Z; m_mapInfo.maxZ = maxCoords.Z; + m_mapInfo.terrainRegionBase = TerrainBase; // Don't have to free any previous since we just got here. BuildHeightmapTerrain(); @@ -135,12 +138,10 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys { if (m_mapInfo.terrainBody.ptr != IntPtr.Zero) { - if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr)) - { - // Frees both the body and the shape. - BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); - BulletSimAPI.ReleaseHeightMapInfo2(m_mapInfo.Ptr); - } + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); + // Frees both the body and the shape. + BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); + BulletSimAPI.ReleaseHeightMapInfo2(m_mapInfo.Ptr); } } m_mapInfo = null; @@ -165,10 +166,5 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys } return ret; } - - public override Vector3 TerrainBase - { - get { return m_mapInfo.terrainRegionBase; } - } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index db04299..ed0dfa8 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -45,14 +45,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin public abstract class BSTerrainPhys : IDisposable { public BSScene PhysicsScene { get; private set; } + // Base of the region in world coordinates. Coordinates inside the region are relative to this. + public Vector3 TerrainBase { get; private set; } + public uint ID { get; private set; } - public BSTerrainPhys(BSScene physicsScene) + public BSTerrainPhys(BSScene physicsScene, Vector3 regionBase, uint id) { PhysicsScene = physicsScene; + TerrainBase = regionBase; + ID = id; } public abstract void Dispose(); public abstract float GetHeightAtXYZ(Vector3 pos); - public abstract Vector3 TerrainBase { get; } } // ========================================================================================== @@ -133,7 +137,7 @@ public sealed class BSTerrainManager (uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask); // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain. - BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, BSScene.TERRAIN_ID, DefaultRegionSize); + BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize); m_terrains.Add(Vector3.Zero, initialTerrain); } @@ -208,10 +212,9 @@ public sealed class BSTerrainManager BSScene.DetailLogZero, minCoords, maxCoords, inTaintTime); // Find high and low points of passed heightmap. - // The min and max passed in are usually the region objects can exist in (maximum + // The min and max passed in is usually the area objects can be in (maximum // object height, for instance). The terrain wants the bounding box for the // terrain so we replace passed min and max Z with the actual terrain min/max Z. - // limit, for float minZ = float.MaxValue; float maxZ = float.MinValue; foreach (float height in heightMap) @@ -219,6 +222,11 @@ public sealed class BSTerrainManager if (height < minZ) minZ = height; if (height > maxZ) maxZ = height; } + if (minZ == maxZ) + { + // If min and max are the same, reduce min a little bit so a good bounding box is created. + minZ -= BSTerrainManager.HEIGHT_EQUAL_FUDGE; + } minCoords.Z = minZ; maxCoords.Z = maxZ; @@ -240,7 +248,9 @@ public sealed class BSTerrainManager if (MegaRegionParentPhysicsScene == null) { - BSTerrainPhys newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, id, + // BSTerrainPhys newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id, + // heightMap, minCoords, maxCoords); + BSTerrainPhys newTerrainPhys = new BSTerrainMesh(PhysicsScene, terrainRegionBase, id, heightMap, minCoords, maxCoords); m_terrains.Add(terrainRegionBase, newTerrainPhys); @@ -282,8 +292,8 @@ public sealed class BSTerrainManager { DetailLog("{0},UpdateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoordsX.X, minCoordsX.Y); - BSTerrainPhys newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, newTerrainID, - heightMapX, minCoordsX, maxCoordsX); + BSTerrainPhys newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, + newTerrainID, heightMapX, minCoordsX, maxCoordsX); m_terrains.Add(terrainRegionBase, newTerrainPhys); m_terrainModified = true; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs index 387c78b..bbb014a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs @@ -44,30 +44,241 @@ public sealed class BSTerrainMesh : BSTerrainPhys { static string LogHeader = "[BULLETSIM TERRAIN MESH]"; - public BSTerrainMesh(BSScene physicsScene, uint id, Vector3 regionSize) - : base(physicsScene) + private float[] m_savedHeightMap; + int m_sizeX; + int m_sizeY; + + BulletShape m_terrainShape; + BulletBody m_terrainBody; + + public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize) + : base(physicsScene, regionBase, id) { } - public BSTerrainMesh(BSScene physicsScene /* parameters for making mesh */) - : base(physicsScene) + public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id /* parameters for making mesh */) + : base(physicsScene, regionBase, id) { } + // Create terrain mesh from a heightmap. + public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap, + Vector3 minCoords, Vector3 maxCoords) + : base(physicsScene, regionBase, id) + { + int indicesCount; + int[] indices; + int verticesCount; + float[] vertices; + + m_savedHeightMap = initialMap; + + m_sizeX = (int)(maxCoords.X - minCoords.X); + m_sizeY = (int)(maxCoords.Y - minCoords.Y); + + if (!BSTerrainMesh.ConvertHeightmapToMesh(PhysicsScene, initialMap, m_sizeX, m_sizeY, + (float)m_sizeX, (float)m_sizeY, + Vector3.Zero, 1.0f, + out indicesCount, out indices, out verticesCount, out vertices)) + { + // DISASTER!! + PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap", ID); + PhysicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh! base={1}", LogHeader, TerrainBase); + // Something is very messed up and a crash is in our future. + return; + } + PhysicsScene.DetailLog("{0},BSTerrainMesh.create,afterConvertHeightmapToMesh,ver={1},ind={2}", + ID, verticesCount, indicesCount); + + m_terrainShape = new BulletShape(BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, + indicesCount, indices, verticesCount, vertices), + PhysicsShapeType.SHAPE_MESH); + if (m_terrainShape.ptr == IntPtr.Zero) + { + // DISASTER!! + PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape", ID); + physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase); + // Something is very messed up and a crash is in our future. + return; + } + PhysicsScene.DetailLog("{0},BSTerrainMesh.create,afterCreateShape,shape={1}", ID, m_terrainShape); + + // The terrain object initial position is at the center of the object + Vector3 centerPos; + centerPos.X = minCoords.X + (m_sizeX / 2f); + centerPos.Y = minCoords.Y + (m_sizeY / 2f); + centerPos.Z = minCoords.Z + ((maxCoords.Z - minCoords.Z) / 2f); + Quaternion rot = Quaternion.Identity; + + PhysicsScene.DetailLog("{0},BSTerrainMesh.create,creatingBody,centerPos={1},rot={2}", ID, centerPos, rot); + m_terrainBody = new BulletBody(id, BulletSimAPI.CreateBodyWithDefaultMotionState2( + m_terrainShape.ptr, ID, centerPos, rot)); + if (m_terrainBody.ptr == IntPtr.Zero) + { + // DISASTER!! + physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase); + // Something is very messed up and a crash is in our future. + return; + } + PhysicsScene.DetailLog("{0},BSTerrainMesh.create,afterCreateBody,body={1}", ID, m_terrainBody); + + // Set current terrain attributes + BulletSimAPI.SetFriction2(m_terrainBody.ptr, PhysicsScene.Params.terrainFriction); + BulletSimAPI.SetHitFraction2(m_terrainBody.ptr, PhysicsScene.Params.terrainHitFraction); + BulletSimAPI.SetRestitution2(m_terrainBody.ptr, PhysicsScene.Params.terrainRestitution); + BulletSimAPI.SetCollisionFlags2(m_terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); + + // Static objects are not very massive. + BulletSimAPI.SetMassProps2(m_terrainBody.ptr, 0f, Vector3.Zero); + + // Return the new terrain to the world of physical objects + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr); + + // redo its bounding box now that it is in the world + BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_terrainBody.ptr); + + BulletSimAPI.SetCollisionFilterMask2(m_terrainBody.ptr, + (uint)CollisionFilterGroups.TerrainFilter, + (uint)CollisionFilterGroups.TerrainMask); + + // Make it so the terrain will not move or be considered for movement. + BulletSimAPI.ForceActivationState2(m_terrainBody.ptr, ActivationState.DISABLE_SIMULATION); + } + public override void Dispose() { - return; + if (m_terrainBody.ptr != IntPtr.Zero) + { + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr); + // Frees both the body and the shape. + BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_terrainBody.ptr); + } } public override float GetHeightAtXYZ(Vector3 pos) { - return 12345f; + // For the moment use the saved heightmap to get the terrain height. + // TODO: raycast downward to find the true terrain below the position. + float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; + + int mapIndex = (int)pos.Y * m_sizeY + (int)pos.X; + try + { + ret = m_savedHeightMap[mapIndex]; + } + catch + { + // Sometimes they give us wonky values of X and Y. Give a warning and return something. + PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}", + LogHeader, TerrainBase, pos); + ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; + } + return ret; } - public override Vector3 TerrainBase + // Convert the passed heightmap to mesh information suitable for CreateMeshShape2(). + // Return 'true' if successfully created. + public static bool ConvertHeightmapToMesh( + BSScene physicsScene, + float[] heightMap, int sizeX, int sizeY, // parameters of incoming heightmap + float extentX, float extentY, // zero based range for output vertices + Vector3 extentBase, // base to be added to all vertices + float magnification, // number of vertices to create between heightMap coords + out int indicesCountO, out int[] indicesO, + out int verticesCountO, out float[] verticesO) { - get { return Vector3.Zero; } - } + bool ret = false; + + int indicesCount = 0; + int verticesCount = 0; + int[] indices = new int[0]; + float[] vertices = new float[0]; + // Simple mesh creation which assumes magnification == 1, sizeX == extentX and sizeY == extentY. + // TODO: do a more general solution that scales, adds new vertices and smoothes the result. + + try + { + // One vertice per heightmap value plus the vertices off the top and bottom edge. + int totalVertices = (sizeX + 1) * (sizeY + 1); + vertices = new float[totalVertices * 3]; + int totalIndices = sizeX * sizeY * 6; + indices = new int[totalIndices]; + + physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2}", + BSScene.DetailLogZero, totalVertices, totalIndices); + float magX = (float)sizeX / extentX; + float magY = (float)sizeY / extentY; + // Note that sizeX+1 vertices are created since there is land between this and the next region. + for (int yy = 0; yy <= sizeY; yy++) + { + for (int xx = 0; xx <= sizeX; xx++) // Hint: the "<=" means we got through sizeX + 1 times + { + int offset = yy * sizeX + xx; + // Extend the height from the height from the last row or column + if (yy == sizeY) offset -= sizeX; + if (xx == sizeX) offset -= 1; + float height = heightMap[offset]; + vertices[verticesCount + 0] = (float)xx * magX + extentBase.X; + vertices[verticesCount + 1] = (float)yy * magY + extentBase.Y; + vertices[verticesCount + 2] = height + extentBase.Z; + if (physicsScene.PhysicsLogging.Enabled && verticesCount < 900) // DEBUG DEBUG DEBUG + { + Vector3 genVertex = new Vector3( + vertices[verticesCount + 0], + vertices[verticesCount + 1], + vertices[verticesCount + 2]); + physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,ii={1},vertex={2}", + BSScene.DetailLogZero, verticesCount/3, genVertex); + } + verticesCount += 3; + } + } + verticesCount = verticesCount / 3; + physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,completeVerts,verCount={1}", + BSScene.DetailLogZero, verticesCount); + + for (int yy = 0; yy < sizeY; yy++) + { + for (int xx = 0; xx < sizeX; xx++) + { + int offset = yy * sizeX + xx; + // Each vertices is presumed to be the upper left corner of a box of two triangles + indices[indicesCount + 0] = offset; + indices[indicesCount + 1] = offset + 1; + indices[indicesCount + 2] = offset + sizeX + 1; // accounting for the extra column + indices[indicesCount + 3] = offset + 1; + indices[indicesCount + 4] = offset + sizeX + 2; + indices[indicesCount + 5] = offset + sizeX + 1; + if (indicesCount < (300 * 6)) // DEBUG DEBUG DEBUG + physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,i0={1},i1={2},i2={3},i3={4},i4={5},i5={6}", // DEEBUG DEBUG DEBUG + BSScene.DetailLogZero, + indices[indicesCount + 0], + indices[indicesCount + 1], + indices[indicesCount + 2], + indices[indicesCount + 3], + indices[indicesCount + 4], + indices[indicesCount + 5] + ); + indicesCount += 6; + } + } + physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,completeIndices,indCount={1}", // DEEBUG DEBUG DEBUG + LogHeader, indicesCount); // DEBUG + ret = true; + } + catch (Exception e) + { + physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh. Base={1}, e={2}", + LogHeader, extentBase, e); + } + + indicesCountO = indicesCount; + indicesO = indices; + verticesCountO = verticesCount; + verticesO = vertices; + + return ret; + } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index bab3b3d..a2271a9 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -391,13 +391,13 @@ public enum CollisionFilterGroups : uint ObjectFilter = BSolidFilter, ObjectMask = BAllFilter, StaticObjectFilter = BStaticFilter, - StaticObjectMask = BAllFilter, + StaticObjectMask = BAllFilter & ~BStaticFilter, // static objects don't collide with each other LinksetFilter = BLinksetFilter, - LinksetMask = BAllFilter & ~BLinksetFilter, + LinksetMask = BAllFilter & ~BLinksetFilter, // linkset objects don't collide with each other VolumeDetectFilter = BSensorTrigger, VolumeDetectMask = ~BSensorTrigger, TerrainFilter = BTerrainFilter, - TerrainMask = BAllFilter & ~BStaticFilter, + TerrainMask = BAllFilter & ~BStaticFilter, // static objects on the ground don't collide GroundPlaneFilter = BGroundPlaneFilter, GroundPlaneMask = BAllFilter -- cgit v1.1 From 2dc7e9d3fa091418814af90565244a8c1972feec Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 20 Nov 2012 20:38:51 -0800 Subject: BulletSim: fix line endings to be all Linux style (windows style keeps creeping in) --- .../Physics/BulletSPlugin/BSTerrainHeightmap.cs | 340 ++++++------ .../Region/Physics/BulletSPlugin/BSTerrainMesh.cs | 568 ++++++++++----------- 2 files changed, 454 insertions(+), 454 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs index e9fd0cb..8fc36d1 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs @@ -1,170 +1,170 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -using OpenSim.Framework; -using OpenSim.Region.Framework; -using OpenSim.Region.CoreModules; -using OpenSim.Region.Physics.Manager; - -using Nini.Config; -using log4net; - -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -public sealed class BSTerrainHeightmap : BSTerrainPhys -{ - static string LogHeader = "[BULLETSIM TERRAIN HEIGHTMAP]"; - - BulletHeightMapInfo m_mapInfo = null; - - // Constructor to build a default, flat heightmap terrain. - public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize) - : base(physicsScene, regionBase, id) - { - Vector3 minTerrainCoords = new Vector3(0f, 0f, BSTerrainManager.HEIGHT_INITIALIZATION - BSTerrainManager.HEIGHT_EQUAL_FUDGE); - Vector3 maxTerrainCoords = new Vector3(regionSize.X, regionSize.Y, BSTerrainManager.HEIGHT_INITIALIZATION); - int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y; - float[] initialMap = new float[totalHeights]; - for (int ii = 0; ii < totalHeights; ii++) - { - initialMap[ii] = BSTerrainManager.HEIGHT_INITIALIZATION; - } - m_mapInfo = new BulletHeightMapInfo(id, initialMap, IntPtr.Zero); - m_mapInfo.minCoords = minTerrainCoords; - m_mapInfo.maxCoords = maxTerrainCoords; - m_mapInfo.terrainRegionBase = TerrainBase; - // Don't have to free any previous since we just got here. - BuildHeightmapTerrain(); - } - - // This minCoords and maxCoords passed in give the size of the terrain (min and max Z - // are the high and low points of the heightmap). - public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap, - Vector3 minCoords, Vector3 maxCoords) - : base(physicsScene, regionBase, id) - { - m_mapInfo = new BulletHeightMapInfo(id, initialMap, IntPtr.Zero); - m_mapInfo.minCoords = minCoords; - m_mapInfo.maxCoords = maxCoords; - m_mapInfo.minZ = minCoords.Z; - m_mapInfo.maxZ = maxCoords.Z; - m_mapInfo.terrainRegionBase = TerrainBase; - - // Don't have to free any previous since we just got here. - BuildHeightmapTerrain(); - } - - public override void Dispose() - { - ReleaseHeightMapTerrain(); - } - - // Using the information in m_mapInfo, create the physical representation of the heightmap. - private void BuildHeightmapTerrain() - { - m_mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, m_mapInfo.ID, - m_mapInfo.minCoords, m_mapInfo.maxCoords, - m_mapInfo.heightMap, BSTerrainManager.TERRAIN_COLLISION_MARGIN); - - // Create the terrain shape from the mapInfo - m_mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(m_mapInfo.Ptr), - PhysicsShapeType.SHAPE_TERRAIN); - - // The terrain object initial position is at the center of the object - Vector3 centerPos; - centerPos.X = m_mapInfo.minCoords.X + (m_mapInfo.sizeX / 2f); - centerPos.Y = m_mapInfo.minCoords.Y + (m_mapInfo.sizeY / 2f); - centerPos.Z = m_mapInfo.minZ + ((m_mapInfo.maxZ - m_mapInfo.minZ) / 2f); - - m_mapInfo.terrainBody = new BulletBody(m_mapInfo.ID, - BulletSimAPI.CreateBodyWithDefaultMotionState2(m_mapInfo.terrainShape.ptr, - m_mapInfo.ID, centerPos, Quaternion.Identity)); - - // Set current terrain attributes - BulletSimAPI.SetFriction2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainFriction); - BulletSimAPI.SetHitFraction2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainHitFraction); - BulletSimAPI.SetRestitution2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution); - BulletSimAPI.SetCollisionFlags2(m_mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); - - // Return the new terrain to the world of physical objects - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); - - // redo its bounding box now that it is in the world - BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); - - BulletSimAPI.SetCollisionFilterMask2(m_mapInfo.terrainBody.ptr, - (uint)CollisionFilterGroups.TerrainFilter, - (uint)CollisionFilterGroups.TerrainMask); - - // Make it so the terrain will not move or be considered for movement. - BulletSimAPI.ForceActivationState2(m_mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); - - return; - } - - // If there is information in m_mapInfo pointing to physical structures, release same. - private void ReleaseHeightMapTerrain() - { - if (m_mapInfo != null) - { - if (m_mapInfo.terrainBody.ptr != IntPtr.Zero) - { - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); - // Frees both the body and the shape. - BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); - BulletSimAPI.ReleaseHeightMapInfo2(m_mapInfo.Ptr); - } - } - m_mapInfo = null; - } - - // The passed position is relative to the base of the region. - public override float GetHeightAtXYZ(Vector3 pos) - { - float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; - - int mapIndex = (int)pos.Y * (int)m_mapInfo.sizeY + (int)pos.X; - try - { - ret = m_mapInfo.heightMap[mapIndex]; - } - catch - { - // Sometimes they give us wonky values of X and Y. Give a warning and return something. - PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}", - LogHeader, m_mapInfo.terrainRegionBase, pos); - ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; - } - return ret; - } -} -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; + +using OpenSim.Framework; +using OpenSim.Region.Framework; +using OpenSim.Region.CoreModules; +using OpenSim.Region.Physics.Manager; + +using Nini.Config; +using log4net; + +using OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ +public sealed class BSTerrainHeightmap : BSTerrainPhys +{ + static string LogHeader = "[BULLETSIM TERRAIN HEIGHTMAP]"; + + BulletHeightMapInfo m_mapInfo = null; + + // Constructor to build a default, flat heightmap terrain. + public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize) + : base(physicsScene, regionBase, id) + { + Vector3 minTerrainCoords = new Vector3(0f, 0f, BSTerrainManager.HEIGHT_INITIALIZATION - BSTerrainManager.HEIGHT_EQUAL_FUDGE); + Vector3 maxTerrainCoords = new Vector3(regionSize.X, regionSize.Y, BSTerrainManager.HEIGHT_INITIALIZATION); + int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y; + float[] initialMap = new float[totalHeights]; + for (int ii = 0; ii < totalHeights; ii++) + { + initialMap[ii] = BSTerrainManager.HEIGHT_INITIALIZATION; + } + m_mapInfo = new BulletHeightMapInfo(id, initialMap, IntPtr.Zero); + m_mapInfo.minCoords = minTerrainCoords; + m_mapInfo.maxCoords = maxTerrainCoords; + m_mapInfo.terrainRegionBase = TerrainBase; + // Don't have to free any previous since we just got here. + BuildHeightmapTerrain(); + } + + // This minCoords and maxCoords passed in give the size of the terrain (min and max Z + // are the high and low points of the heightmap). + public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap, + Vector3 minCoords, Vector3 maxCoords) + : base(physicsScene, regionBase, id) + { + m_mapInfo = new BulletHeightMapInfo(id, initialMap, IntPtr.Zero); + m_mapInfo.minCoords = minCoords; + m_mapInfo.maxCoords = maxCoords; + m_mapInfo.minZ = minCoords.Z; + m_mapInfo.maxZ = maxCoords.Z; + m_mapInfo.terrainRegionBase = TerrainBase; + + // Don't have to free any previous since we just got here. + BuildHeightmapTerrain(); + } + + public override void Dispose() + { + ReleaseHeightMapTerrain(); + } + + // Using the information in m_mapInfo, create the physical representation of the heightmap. + private void BuildHeightmapTerrain() + { + m_mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, m_mapInfo.ID, + m_mapInfo.minCoords, m_mapInfo.maxCoords, + m_mapInfo.heightMap, BSTerrainManager.TERRAIN_COLLISION_MARGIN); + + // Create the terrain shape from the mapInfo + m_mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(m_mapInfo.Ptr), + PhysicsShapeType.SHAPE_TERRAIN); + + // The terrain object initial position is at the center of the object + Vector3 centerPos; + centerPos.X = m_mapInfo.minCoords.X + (m_mapInfo.sizeX / 2f); + centerPos.Y = m_mapInfo.minCoords.Y + (m_mapInfo.sizeY / 2f); + centerPos.Z = m_mapInfo.minZ + ((m_mapInfo.maxZ - m_mapInfo.minZ) / 2f); + + m_mapInfo.terrainBody = new BulletBody(m_mapInfo.ID, + BulletSimAPI.CreateBodyWithDefaultMotionState2(m_mapInfo.terrainShape.ptr, + m_mapInfo.ID, centerPos, Quaternion.Identity)); + + // Set current terrain attributes + BulletSimAPI.SetFriction2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainFriction); + BulletSimAPI.SetHitFraction2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainHitFraction); + BulletSimAPI.SetRestitution2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution); + BulletSimAPI.SetCollisionFlags2(m_mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); + + // Return the new terrain to the world of physical objects + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); + + // redo its bounding box now that it is in the world + BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); + + BulletSimAPI.SetCollisionFilterMask2(m_mapInfo.terrainBody.ptr, + (uint)CollisionFilterGroups.TerrainFilter, + (uint)CollisionFilterGroups.TerrainMask); + + // Make it so the terrain will not move or be considered for movement. + BulletSimAPI.ForceActivationState2(m_mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); + + return; + } + + // If there is information in m_mapInfo pointing to physical structures, release same. + private void ReleaseHeightMapTerrain() + { + if (m_mapInfo != null) + { + if (m_mapInfo.terrainBody.ptr != IntPtr.Zero) + { + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); + // Frees both the body and the shape. + BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); + BulletSimAPI.ReleaseHeightMapInfo2(m_mapInfo.Ptr); + } + } + m_mapInfo = null; + } + + // The passed position is relative to the base of the region. + public override float GetHeightAtXYZ(Vector3 pos) + { + float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; + + int mapIndex = (int)pos.Y * (int)m_mapInfo.sizeY + (int)pos.X; + try + { + ret = m_mapInfo.heightMap[mapIndex]; + } + catch + { + // Sometimes they give us wonky values of X and Y. Give a warning and return something. + PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}", + LogHeader, m_mapInfo.terrainRegionBase, pos); + ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; + } + return ret; + } +} +} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs index bbb014a..a199078 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs @@ -1,284 +1,284 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -using OpenSim.Framework; -using OpenSim.Region.Framework; -using OpenSim.Region.CoreModules; -using OpenSim.Region.Physics.Manager; - -using Nini.Config; -using log4net; - -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -public sealed class BSTerrainMesh : BSTerrainPhys -{ - static string LogHeader = "[BULLETSIM TERRAIN MESH]"; - - private float[] m_savedHeightMap; - int m_sizeX; - int m_sizeY; - - BulletShape m_terrainShape; - BulletBody m_terrainBody; - - public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize) - : base(physicsScene, regionBase, id) - { - } - - public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id /* parameters for making mesh */) - : base(physicsScene, regionBase, id) - { - } - - // Create terrain mesh from a heightmap. - public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap, - Vector3 minCoords, Vector3 maxCoords) - : base(physicsScene, regionBase, id) - { - int indicesCount; - int[] indices; - int verticesCount; - float[] vertices; - - m_savedHeightMap = initialMap; - - m_sizeX = (int)(maxCoords.X - minCoords.X); - m_sizeY = (int)(maxCoords.Y - minCoords.Y); - - if (!BSTerrainMesh.ConvertHeightmapToMesh(PhysicsScene, initialMap, m_sizeX, m_sizeY, - (float)m_sizeX, (float)m_sizeY, - Vector3.Zero, 1.0f, - out indicesCount, out indices, out verticesCount, out vertices)) - { - // DISASTER!! - PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap", ID); - PhysicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh! base={1}", LogHeader, TerrainBase); - // Something is very messed up and a crash is in our future. - return; - } - PhysicsScene.DetailLog("{0},BSTerrainMesh.create,afterConvertHeightmapToMesh,ver={1},ind={2}", - ID, verticesCount, indicesCount); - - m_terrainShape = new BulletShape(BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, - indicesCount, indices, verticesCount, vertices), - PhysicsShapeType.SHAPE_MESH); - if (m_terrainShape.ptr == IntPtr.Zero) - { - // DISASTER!! - PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape", ID); - physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase); - // Something is very messed up and a crash is in our future. - return; - } - PhysicsScene.DetailLog("{0},BSTerrainMesh.create,afterCreateShape,shape={1}", ID, m_terrainShape); - - // The terrain object initial position is at the center of the object - Vector3 centerPos; - centerPos.X = minCoords.X + (m_sizeX / 2f); - centerPos.Y = minCoords.Y + (m_sizeY / 2f); - centerPos.Z = minCoords.Z + ((maxCoords.Z - minCoords.Z) / 2f); - Quaternion rot = Quaternion.Identity; - - PhysicsScene.DetailLog("{0},BSTerrainMesh.create,creatingBody,centerPos={1},rot={2}", ID, centerPos, rot); - m_terrainBody = new BulletBody(id, BulletSimAPI.CreateBodyWithDefaultMotionState2( - m_terrainShape.ptr, ID, centerPos, rot)); - if (m_terrainBody.ptr == IntPtr.Zero) - { - // DISASTER!! - physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase); - // Something is very messed up and a crash is in our future. - return; - } - PhysicsScene.DetailLog("{0},BSTerrainMesh.create,afterCreateBody,body={1}", ID, m_terrainBody); - - // Set current terrain attributes - BulletSimAPI.SetFriction2(m_terrainBody.ptr, PhysicsScene.Params.terrainFriction); - BulletSimAPI.SetHitFraction2(m_terrainBody.ptr, PhysicsScene.Params.terrainHitFraction); - BulletSimAPI.SetRestitution2(m_terrainBody.ptr, PhysicsScene.Params.terrainRestitution); - BulletSimAPI.SetCollisionFlags2(m_terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); - - // Static objects are not very massive. - BulletSimAPI.SetMassProps2(m_terrainBody.ptr, 0f, Vector3.Zero); - - // Return the new terrain to the world of physical objects - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr); - - // redo its bounding box now that it is in the world - BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_terrainBody.ptr); - - BulletSimAPI.SetCollisionFilterMask2(m_terrainBody.ptr, - (uint)CollisionFilterGroups.TerrainFilter, - (uint)CollisionFilterGroups.TerrainMask); - - // Make it so the terrain will not move or be considered for movement. - BulletSimAPI.ForceActivationState2(m_terrainBody.ptr, ActivationState.DISABLE_SIMULATION); - } - - public override void Dispose() - { - if (m_terrainBody.ptr != IntPtr.Zero) - { - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr); - // Frees both the body and the shape. - BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_terrainBody.ptr); - } - } - - public override float GetHeightAtXYZ(Vector3 pos) - { - // For the moment use the saved heightmap to get the terrain height. - // TODO: raycast downward to find the true terrain below the position. - float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; - - int mapIndex = (int)pos.Y * m_sizeY + (int)pos.X; - try - { - ret = m_savedHeightMap[mapIndex]; - } - catch - { - // Sometimes they give us wonky values of X and Y. Give a warning and return something. - PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}", - LogHeader, TerrainBase, pos); - ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; - } - return ret; - } - - // Convert the passed heightmap to mesh information suitable for CreateMeshShape2(). - // Return 'true' if successfully created. - public static bool ConvertHeightmapToMesh( - BSScene physicsScene, - float[] heightMap, int sizeX, int sizeY, // parameters of incoming heightmap - float extentX, float extentY, // zero based range for output vertices - Vector3 extentBase, // base to be added to all vertices - float magnification, // number of vertices to create between heightMap coords - out int indicesCountO, out int[] indicesO, - out int verticesCountO, out float[] verticesO) - { - bool ret = false; - - int indicesCount = 0; - int verticesCount = 0; - int[] indices = new int[0]; - float[] vertices = new float[0]; - - // Simple mesh creation which assumes magnification == 1, sizeX == extentX and sizeY == extentY. - // TODO: do a more general solution that scales, adds new vertices and smoothes the result. - - try - { - // One vertice per heightmap value plus the vertices off the top and bottom edge. - int totalVertices = (sizeX + 1) * (sizeY + 1); - vertices = new float[totalVertices * 3]; - int totalIndices = sizeX * sizeY * 6; - indices = new int[totalIndices]; - - physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2}", - BSScene.DetailLogZero, totalVertices, totalIndices); - float magX = (float)sizeX / extentX; - float magY = (float)sizeY / extentY; - // Note that sizeX+1 vertices are created since there is land between this and the next region. - for (int yy = 0; yy <= sizeY; yy++) - { - for (int xx = 0; xx <= sizeX; xx++) // Hint: the "<=" means we got through sizeX + 1 times - { - int offset = yy * sizeX + xx; - // Extend the height from the height from the last row or column - if (yy == sizeY) offset -= sizeX; - if (xx == sizeX) offset -= 1; - float height = heightMap[offset]; - vertices[verticesCount + 0] = (float)xx * magX + extentBase.X; - vertices[verticesCount + 1] = (float)yy * magY + extentBase.Y; - vertices[verticesCount + 2] = height + extentBase.Z; - if (physicsScene.PhysicsLogging.Enabled && verticesCount < 900) // DEBUG DEBUG DEBUG - { - Vector3 genVertex = new Vector3( - vertices[verticesCount + 0], - vertices[verticesCount + 1], - vertices[verticesCount + 2]); - physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,ii={1},vertex={2}", - BSScene.DetailLogZero, verticesCount/3, genVertex); - } - verticesCount += 3; - } - } - verticesCount = verticesCount / 3; - physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,completeVerts,verCount={1}", - BSScene.DetailLogZero, verticesCount); - - for (int yy = 0; yy < sizeY; yy++) - { - for (int xx = 0; xx < sizeX; xx++) - { - int offset = yy * sizeX + xx; - // Each vertices is presumed to be the upper left corner of a box of two triangles - indices[indicesCount + 0] = offset; - indices[indicesCount + 1] = offset + 1; - indices[indicesCount + 2] = offset + sizeX + 1; // accounting for the extra column - indices[indicesCount + 3] = offset + 1; - indices[indicesCount + 4] = offset + sizeX + 2; - indices[indicesCount + 5] = offset + sizeX + 1; - if (indicesCount < (300 * 6)) // DEBUG DEBUG DEBUG - physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,i0={1},i1={2},i2={3},i3={4},i4={5},i5={6}", // DEEBUG DEBUG DEBUG - BSScene.DetailLogZero, - indices[indicesCount + 0], - indices[indicesCount + 1], - indices[indicesCount + 2], - indices[indicesCount + 3], - indices[indicesCount + 4], - indices[indicesCount + 5] - ); - indicesCount += 6; - } - } - physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,completeIndices,indCount={1}", // DEEBUG DEBUG DEBUG - LogHeader, indicesCount); // DEBUG - ret = true; - } - catch (Exception e) - { - physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh. Base={1}, e={2}", - LogHeader, extentBase, e); - } - - indicesCountO = indicesCount; - indicesO = indices; - verticesCountO = verticesCount; - verticesO = vertices; - - return ret; - } -} -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; + +using OpenSim.Framework; +using OpenSim.Region.Framework; +using OpenSim.Region.CoreModules; +using OpenSim.Region.Physics.Manager; + +using Nini.Config; +using log4net; + +using OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ +public sealed class BSTerrainMesh : BSTerrainPhys +{ + static string LogHeader = "[BULLETSIM TERRAIN MESH]"; + + private float[] m_savedHeightMap; + int m_sizeX; + int m_sizeY; + + BulletShape m_terrainShape; + BulletBody m_terrainBody; + + public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize) + : base(physicsScene, regionBase, id) + { + } + + public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id /* parameters for making mesh */) + : base(physicsScene, regionBase, id) + { + } + + // Create terrain mesh from a heightmap. + public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap, + Vector3 minCoords, Vector3 maxCoords) + : base(physicsScene, regionBase, id) + { + int indicesCount; + int[] indices; + int verticesCount; + float[] vertices; + + m_savedHeightMap = initialMap; + + m_sizeX = (int)(maxCoords.X - minCoords.X); + m_sizeY = (int)(maxCoords.Y - minCoords.Y); + + if (!BSTerrainMesh.ConvertHeightmapToMesh(PhysicsScene, initialMap, m_sizeX, m_sizeY, + (float)m_sizeX, (float)m_sizeY, + Vector3.Zero, 1.0f, + out indicesCount, out indices, out verticesCount, out vertices)) + { + // DISASTER!! + PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap", ID); + PhysicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh! base={1}", LogHeader, TerrainBase); + // Something is very messed up and a crash is in our future. + return; + } + PhysicsScene.DetailLog("{0},BSTerrainMesh.create,afterConvertHeightmapToMesh,ver={1},ind={2}", + ID, verticesCount, indicesCount); + + m_terrainShape = new BulletShape(BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, + indicesCount, indices, verticesCount, vertices), + PhysicsShapeType.SHAPE_MESH); + if (m_terrainShape.ptr == IntPtr.Zero) + { + // DISASTER!! + PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape", ID); + physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase); + // Something is very messed up and a crash is in our future. + return; + } + PhysicsScene.DetailLog("{0},BSTerrainMesh.create,afterCreateShape,shape={1}", ID, m_terrainShape); + + // The terrain object initial position is at the center of the object + Vector3 centerPos; + centerPos.X = minCoords.X + (m_sizeX / 2f); + centerPos.Y = minCoords.Y + (m_sizeY / 2f); + centerPos.Z = minCoords.Z + ((maxCoords.Z - minCoords.Z) / 2f); + Quaternion rot = Quaternion.Identity; + + PhysicsScene.DetailLog("{0},BSTerrainMesh.create,creatingBody,centerPos={1},rot={2}", ID, centerPos, rot); + m_terrainBody = new BulletBody(id, BulletSimAPI.CreateBodyWithDefaultMotionState2( + m_terrainShape.ptr, ID, centerPos, rot)); + if (m_terrainBody.ptr == IntPtr.Zero) + { + // DISASTER!! + physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase); + // Something is very messed up and a crash is in our future. + return; + } + PhysicsScene.DetailLog("{0},BSTerrainMesh.create,afterCreateBody,body={1}", ID, m_terrainBody); + + // Set current terrain attributes + BulletSimAPI.SetFriction2(m_terrainBody.ptr, PhysicsScene.Params.terrainFriction); + BulletSimAPI.SetHitFraction2(m_terrainBody.ptr, PhysicsScene.Params.terrainHitFraction); + BulletSimAPI.SetRestitution2(m_terrainBody.ptr, PhysicsScene.Params.terrainRestitution); + BulletSimAPI.SetCollisionFlags2(m_terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); + + // Static objects are not very massive. + BulletSimAPI.SetMassProps2(m_terrainBody.ptr, 0f, Vector3.Zero); + + // Return the new terrain to the world of physical objects + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr); + + // redo its bounding box now that it is in the world + BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_terrainBody.ptr); + + BulletSimAPI.SetCollisionFilterMask2(m_terrainBody.ptr, + (uint)CollisionFilterGroups.TerrainFilter, + (uint)CollisionFilterGroups.TerrainMask); + + // Make it so the terrain will not move or be considered for movement. + BulletSimAPI.ForceActivationState2(m_terrainBody.ptr, ActivationState.DISABLE_SIMULATION); + } + + public override void Dispose() + { + if (m_terrainBody.ptr != IntPtr.Zero) + { + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr); + // Frees both the body and the shape. + BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_terrainBody.ptr); + } + } + + public override float GetHeightAtXYZ(Vector3 pos) + { + // For the moment use the saved heightmap to get the terrain height. + // TODO: raycast downward to find the true terrain below the position. + float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; + + int mapIndex = (int)pos.Y * m_sizeY + (int)pos.X; + try + { + ret = m_savedHeightMap[mapIndex]; + } + catch + { + // Sometimes they give us wonky values of X and Y. Give a warning and return something. + PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}", + LogHeader, TerrainBase, pos); + ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; + } + return ret; + } + + // Convert the passed heightmap to mesh information suitable for CreateMeshShape2(). + // Return 'true' if successfully created. + public static bool ConvertHeightmapToMesh( + BSScene physicsScene, + float[] heightMap, int sizeX, int sizeY, // parameters of incoming heightmap + float extentX, float extentY, // zero based range for output vertices + Vector3 extentBase, // base to be added to all vertices + float magnification, // number of vertices to create between heightMap coords + out int indicesCountO, out int[] indicesO, + out int verticesCountO, out float[] verticesO) + { + bool ret = false; + + int indicesCount = 0; + int verticesCount = 0; + int[] indices = new int[0]; + float[] vertices = new float[0]; + + // Simple mesh creation which assumes magnification == 1, sizeX == extentX and sizeY == extentY. + // TODO: do a more general solution that scales, adds new vertices and smoothes the result. + + try + { + // One vertice per heightmap value plus the vertices off the top and bottom edge. + int totalVertices = (sizeX + 1) * (sizeY + 1); + vertices = new float[totalVertices * 3]; + int totalIndices = sizeX * sizeY * 6; + indices = new int[totalIndices]; + + physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2}", + BSScene.DetailLogZero, totalVertices, totalIndices); + float magX = (float)sizeX / extentX; + float magY = (float)sizeY / extentY; + // Note that sizeX+1 vertices are created since there is land between this and the next region. + for (int yy = 0; yy <= sizeY; yy++) + { + for (int xx = 0; xx <= sizeX; xx++) // Hint: the "<=" means we got through sizeX + 1 times + { + int offset = yy * sizeX + xx; + // Extend the height from the height from the last row or column + if (yy == sizeY) offset -= sizeX; + if (xx == sizeX) offset -= 1; + float height = heightMap[offset]; + vertices[verticesCount + 0] = (float)xx * magX + extentBase.X; + vertices[verticesCount + 1] = (float)yy * magY + extentBase.Y; + vertices[verticesCount + 2] = height + extentBase.Z; + if (physicsScene.PhysicsLogging.Enabled && verticesCount < 900) // DEBUG DEBUG DEBUG + { + Vector3 genVertex = new Vector3( + vertices[verticesCount + 0], + vertices[verticesCount + 1], + vertices[verticesCount + 2]); + physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,ii={1},vertex={2}", + BSScene.DetailLogZero, verticesCount/3, genVertex); + } + verticesCount += 3; + } + } + verticesCount = verticesCount / 3; + physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,completeVerts,verCount={1}", + BSScene.DetailLogZero, verticesCount); + + for (int yy = 0; yy < sizeY; yy++) + { + for (int xx = 0; xx < sizeX; xx++) + { + int offset = yy * sizeX + xx; + // Each vertices is presumed to be the upper left corner of a box of two triangles + indices[indicesCount + 0] = offset; + indices[indicesCount + 1] = offset + 1; + indices[indicesCount + 2] = offset + sizeX + 1; // accounting for the extra column + indices[indicesCount + 3] = offset + 1; + indices[indicesCount + 4] = offset + sizeX + 2; + indices[indicesCount + 5] = offset + sizeX + 1; + if (indicesCount < (300 * 6)) // DEBUG DEBUG DEBUG + physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,i0={1},i1={2},i2={3},i3={4},i4={5},i5={6}", // DEEBUG DEBUG DEBUG + BSScene.DetailLogZero, + indices[indicesCount + 0], + indices[indicesCount + 1], + indices[indicesCount + 2], + indices[indicesCount + 3], + indices[indicesCount + 4], + indices[indicesCount + 5] + ); + indicesCount += 6; + } + } + physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,completeIndices,indCount={1}", // DEEBUG DEBUG DEBUG + LogHeader, indicesCount); // DEBUG + ret = true; + } + catch (Exception e) + { + physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh. Base={1}, e={2}", + LogHeader, extentBase, e); + } + + indicesCountO = indicesCount; + indicesO = indices; + verticesCountO = verticesCount; + verticesO = vertices; + + return ret; + } +} +} -- cgit v1.1 From a59368c4a1889ccd79da9e564ee84b213a7f6fbd Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 21 Nov 2012 10:37:40 -0800 Subject: BulletSim: add terrainImplementation parameter with default to Mesh. --- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 5 +++ .../Physics/BulletSPlugin/BSTerrainManager.cs | 45 +++++++++++++++++++--- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 1 + 3 files changed, 46 insertions(+), 5 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 58dccea..0e73d04 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -1145,6 +1145,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); }, (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.PhysBody.ptr, v); } ), + new ParameterDefn("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)", + (float)BSTerrainPhys.TerrainImplementation.Mesh, + (s,cf,p,v) => { s.m_params[0].terrainImplementation = cf.GetFloat(p,v); }, + (s) => { return s.m_params[0].terrainImplementation; }, + (s,p,l,v) => { s.m_params[0].terrainImplementation = v; } ), new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , 0.5f, (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); }, diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index ed0dfa8..b88f561 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -44,6 +44,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin // The physical implementation of the terrain is wrapped in this class. public abstract class BSTerrainPhys : IDisposable { + public enum TerrainImplementation + { + Heightmap = 0, + Mesh = 1 + } + public BSScene PhysicsScene { get; private set; } // Base of the region in world coordinates. Coordinates inside the region are relative to this. public Vector3 TerrainBase { get; private set; } @@ -246,12 +252,27 @@ public sealed class BSTerrainManager // Release any physical memory it may be using. terrainPhys.Dispose(); + BSTerrainPhys newTerrainPhys = null; ; if (MegaRegionParentPhysicsScene == null) { - // BSTerrainPhys newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id, - // heightMap, minCoords, maxCoords); - BSTerrainPhys newTerrainPhys = new BSTerrainMesh(PhysicsScene, terrainRegionBase, id, + // TODO: redo terrain implementation selection to be centralized (there is another + // use below) and to accept an asset specification (for a mesh). + switch ((int)PhysicsScene.Params.terrainImplementation) + { + case (int)BSTerrainPhys.TerrainImplementation.Heightmap: + newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id, + heightMap, minCoords, maxCoords); + break; + case (int)BSTerrainPhys.TerrainImplementation.Mesh: + newTerrainPhys = new BSTerrainMesh(PhysicsScene, terrainRegionBase, id, heightMap, minCoords, maxCoords); + break; + default: + PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. type={1}/{2}", + LogHeader, (int)PhysicsScene.Params.terrainImplementation, PhysicsScene.Params.terrainImplementation); + break; + } + m_terrains.Add(terrainRegionBase, newTerrainPhys); m_terrainModified = true; @@ -292,8 +313,22 @@ public sealed class BSTerrainManager { DetailLog("{0},UpdateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoordsX.X, minCoordsX.Y); - BSTerrainPhys newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, - newTerrainID, heightMapX, minCoordsX, maxCoordsX); + BSTerrainPhys newTerrainPhys = null; + switch ((int)PhysicsScene.Params.terrainImplementation) + { + case (int)BSTerrainPhys.TerrainImplementation.Heightmap: + newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id, + heightMap, minCoords, maxCoords); + break; + case (int)BSTerrainPhys.TerrainImplementation.Mesh: + newTerrainPhys = new BSTerrainMesh(PhysicsScene, terrainRegionBase, id, + heightMap, minCoords, maxCoords); + break; + default: + PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. type={1}/{2}", + LogHeader, (int)PhysicsScene.Params.terrainImplementation, PhysicsScene.Params.terrainImplementation); + break; + } m_terrains.Add(terrainRegionBase, newTerrainPhys); m_terrainModified = true; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index a2271a9..e218053 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -283,6 +283,7 @@ public struct ConfigurationParameters public float ccdSweptSphereRadius; public float contactProcessingThreshold; + public float terrainImplementation; public float terrainFriction; public float terrainHitFraction; public float terrainRestitution; -- cgit v1.1 From 4a0de0170412a939bade6cd149c94c7fd3ef020e Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 21 Nov 2012 13:44:02 -0800 Subject: BulletSim: Properly position mesh terrain on creation (fixes terrain not appearing to be working). Centralize terrain shape creation logic. Remove very chatty detail log messages. --- .../Physics/BulletSPlugin/BSTerrainManager.cs | 74 ++++++++++------------ .../Region/Physics/BulletSPlugin/BSTerrainMesh.cs | 46 +++----------- 2 files changed, 44 insertions(+), 76 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index b88f561..097cd3e 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -241,38 +241,20 @@ public sealed class BSTerrainManager BSTerrainPhys terrainPhys; if (m_terrains.TryGetValue(terrainRegionBase, out terrainPhys)) { - // If this is terrain we know about, it's easy to update - - DetailLog("{0},UpdateTerrain:UpdateExisting,call,terrainBase={1}", BSScene.DetailLogZero, terrainRegionBase); + // There is already a terrain in this spot. Free the old and build the new. + DetailLog("{0},UpdateTerrain:UpdateExisting,call,id={1},base={2},minC={3},maxC={4}", + BSScene.DetailLogZero, id, terrainRegionBase, minCoords, minCoords); PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateTerrain:UpdateExisting", delegate() { // Remove old terrain from the collection - m_terrains.Remove(terrainPhys.TerrainBase); + m_terrains.Remove(terrainRegionBase); // Release any physical memory it may be using. terrainPhys.Dispose(); - BSTerrainPhys newTerrainPhys = null; ; if (MegaRegionParentPhysicsScene == null) { - // TODO: redo terrain implementation selection to be centralized (there is another - // use below) and to accept an asset specification (for a mesh). - switch ((int)PhysicsScene.Params.terrainImplementation) - { - case (int)BSTerrainPhys.TerrainImplementation.Heightmap: - newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id, - heightMap, minCoords, maxCoords); - break; - case (int)BSTerrainPhys.TerrainImplementation.Mesh: - newTerrainPhys = new BSTerrainMesh(PhysicsScene, terrainRegionBase, id, - heightMap, minCoords, maxCoords); - break; - default: - PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. type={1}/{2}", - LogHeader, (int)PhysicsScene.Params.terrainImplementation, PhysicsScene.Params.terrainImplementation); - break; - } - + BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords); m_terrains.Add(terrainRegionBase, newTerrainPhys); m_terrainModified = true; @@ -313,22 +295,7 @@ public sealed class BSTerrainManager { DetailLog("{0},UpdateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoordsX.X, minCoordsX.Y); - BSTerrainPhys newTerrainPhys = null; - switch ((int)PhysicsScene.Params.terrainImplementation) - { - case (int)BSTerrainPhys.TerrainImplementation.Heightmap: - newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id, - heightMap, minCoords, maxCoords); - break; - case (int)BSTerrainPhys.TerrainImplementation.Mesh: - newTerrainPhys = new BSTerrainMesh(PhysicsScene, terrainRegionBase, id, - heightMap, minCoords, maxCoords); - break; - default: - PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. type={1}/{2}", - LogHeader, (int)PhysicsScene.Params.terrainImplementation, PhysicsScene.Params.terrainImplementation); - break; - } + BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords); m_terrains.Add(terrainRegionBase, newTerrainPhys); m_terrainModified = true; @@ -336,6 +303,35 @@ public sealed class BSTerrainManager } } + // TODO: redo terrain implementation selection to allow other base types than heightMap. + private BSTerrainPhys BuildPhysicalTerrain(Vector3 terrainRegionBase, uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords) + { + PhysicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}", + LogHeader, PhysicsScene.RegionName, terrainRegionBase, + PhysicsScene.Params.terrainImplementation); + BSTerrainPhys newTerrainPhys = null; + switch ((int)PhysicsScene.Params.terrainImplementation) + { + case (int)BSTerrainPhys.TerrainImplementation.Heightmap: + newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id, + heightMap, minCoords, maxCoords); + break; + case (int)BSTerrainPhys.TerrainImplementation.Mesh: + newTerrainPhys = new BSTerrainMesh(PhysicsScene, terrainRegionBase, id, + heightMap, minCoords, maxCoords); + break; + default: + PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. Type={1}/{2},Region={3}/{4}", + LogHeader, + (int)PhysicsScene.Params.terrainImplementation, + PhysicsScene.Params.terrainImplementation, + PhysicsScene.RegionName, terrainRegionBase); + break; + } + return newTerrainPhys; + } + + // Given an X and Y, find the height of the terrain. // Since we could be handling multiple terrains for a mega-region, // the base of the region is calcuated assuming all regions are diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs index a199078..3279b6f 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs @@ -76,7 +76,8 @@ public sealed class BSTerrainMesh : BSTerrainPhys m_sizeX = (int)(maxCoords.X - minCoords.X); m_sizeY = (int)(maxCoords.Y - minCoords.Y); - if (!BSTerrainMesh.ConvertHeightmapToMesh(PhysicsScene, initialMap, m_sizeX, m_sizeY, + if (!BSTerrainMesh.ConvertHeightmapToMesh(PhysicsScene, initialMap, + m_sizeX, m_sizeY, (float)m_sizeX, (float)m_sizeY, Vector3.Zero, 1.0f, out indicesCount, out indices, out verticesCount, out vertices)) @@ -87,8 +88,6 @@ public sealed class BSTerrainMesh : BSTerrainPhys // Something is very messed up and a crash is in our future. return; } - PhysicsScene.DetailLog("{0},BSTerrainMesh.create,afterConvertHeightmapToMesh,ver={1},ind={2}", - ID, verticesCount, indicesCount); m_terrainShape = new BulletShape(BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, indicesCount, indices, verticesCount, vertices), @@ -101,18 +100,11 @@ public sealed class BSTerrainMesh : BSTerrainPhys // Something is very messed up and a crash is in our future. return; } - PhysicsScene.DetailLog("{0},BSTerrainMesh.create,afterCreateShape,shape={1}", ID, m_terrainShape); - // The terrain object initial position is at the center of the object - Vector3 centerPos; - centerPos.X = minCoords.X + (m_sizeX / 2f); - centerPos.Y = minCoords.Y + (m_sizeY / 2f); - centerPos.Z = minCoords.Z + ((maxCoords.Z - minCoords.Z) / 2f); + Vector3 pos = regionBase; Quaternion rot = Quaternion.Identity; - PhysicsScene.DetailLog("{0},BSTerrainMesh.create,creatingBody,centerPos={1},rot={2}", ID, centerPos, rot); - m_terrainBody = new BulletBody(id, BulletSimAPI.CreateBodyWithDefaultMotionState2( - m_terrainShape.ptr, ID, centerPos, rot)); + m_terrainBody = new BulletBody(id, BulletSimAPI.CreateBodyWithDefaultMotionState2( m_terrainShape.ptr, ID, pos, rot)); if (m_terrainBody.ptr == IntPtr.Zero) { // DISASTER!! @@ -120,7 +112,6 @@ public sealed class BSTerrainMesh : BSTerrainPhys // Something is very messed up and a crash is in our future. return; } - PhysicsScene.DetailLog("{0},BSTerrainMesh.create,afterCreateBody,body={1}", ID, m_terrainBody); // Set current terrain attributes BulletSimAPI.SetFriction2(m_terrainBody.ptr, PhysicsScene.Params.terrainFriction); @@ -194,7 +185,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys int[] indices = new int[0]; float[] vertices = new float[0]; - // Simple mesh creation which assumes magnification == 1, sizeX == extentX and sizeY == extentY. + // Simple mesh creation which assumes magnification == 1. // TODO: do a more general solution that scales, adds new vertices and smoothes the result. try @@ -205,10 +196,10 @@ public sealed class BSTerrainMesh : BSTerrainPhys int totalIndices = sizeX * sizeY * 6; indices = new int[totalIndices]; - physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2}", - BSScene.DetailLogZero, totalVertices, totalIndices); float magX = (float)sizeX / extentX; float magY = (float)sizeY / extentY; + physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2},extentBase={3},magX={4},magY={5}", + BSScene.DetailLogZero, totalVertices, totalIndices, extentBase, magX, magY); // Note that sizeX+1 vertices are created since there is land between this and the next region. for (int yy = 0; yy <= sizeY; yy++) { @@ -222,15 +213,6 @@ public sealed class BSTerrainMesh : BSTerrainPhys vertices[verticesCount + 0] = (float)xx * magX + extentBase.X; vertices[verticesCount + 1] = (float)yy * magY + extentBase.Y; vertices[verticesCount + 2] = height + extentBase.Z; - if (physicsScene.PhysicsLogging.Enabled && verticesCount < 900) // DEBUG DEBUG DEBUG - { - Vector3 genVertex = new Vector3( - vertices[verticesCount + 0], - vertices[verticesCount + 1], - vertices[verticesCount + 2]); - physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,ii={1},vertex={2}", - BSScene.DetailLogZero, verticesCount/3, genVertex); - } verticesCount += 3; } } @@ -250,16 +232,6 @@ public sealed class BSTerrainMesh : BSTerrainPhys indices[indicesCount + 3] = offset + 1; indices[indicesCount + 4] = offset + sizeX + 2; indices[indicesCount + 5] = offset + sizeX + 1; - if (indicesCount < (300 * 6)) // DEBUG DEBUG DEBUG - physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,i0={1},i1={2},i2={3},i3={4},i4={5},i5={6}", // DEEBUG DEBUG DEBUG - BSScene.DetailLogZero, - indices[indicesCount + 0], - indices[indicesCount + 1], - indices[indicesCount + 2], - indices[indicesCount + 3], - indices[indicesCount + 4], - indices[indicesCount + 5] - ); indicesCount += 6; } } @@ -269,8 +241,8 @@ public sealed class BSTerrainMesh : BSTerrainPhys } catch (Exception e) { - physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh. Base={1}, e={2}", - LogHeader, extentBase, e); + physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh. For={1}/{2}, e={3}", + LogHeader, physicsScene.RegionName, extentBase, e); } indicesCountO = indicesCount; -- cgit v1.1 From cbc7e7bf85bfd9e916146b0ae4a605996c24720b Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 21 Nov 2012 16:31:23 -0800 Subject: BulletSim: Make avatar capsule so it is not circular. Simple attempt to make avatars better shaped. Replace parameter 'avatarCapsuleRadius' with 'avatarCapsuleWidth' and 'avatarCapsuleDepth'. More tweeking to avatar height calculation. A little better but short avatar's feet are above the terrain and tall avatar's feet are a little below the ground. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 24 +++++++++++++++------- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 4 +++- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 18 +++++++++------- .../Physics/BulletSPlugin/BSShapeCollection.cs | 9 ++++---- .../Physics/BulletSPlugin/BSTerrainManager.cs | 2 +- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 3 ++- 6 files changed, 39 insertions(+), 21 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 799211e..e2aa41e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -82,7 +82,13 @@ public sealed class BSCharacter : BSPhysObject { _physicsActorType = (int)ActorTypes.Agent; _position = pos; + + // Old versions of ScenePresence passed only the height. If width and/or depth are zero, + // replace with the default values. _size = size; + if (_size.X == 0f) _size.X = PhysicsScene.Params.avatarCapsuleDepth; + if (_size.Y == 0f) _size.Y = PhysicsScene.Params.avatarCapsuleWidth; + _flying = isFlying; _orientation = OMV.Quaternion.Identity; _velocity = OMV.Vector3.Zero; @@ -175,8 +181,7 @@ public sealed class BSCharacter : BSPhysObject get { // Avatar capsule size is kept in the scale parameter. - // return _size; - return new OMV.Vector3(Scale.X * 2f, Scale.Y * 2f, Scale.Z); + return _size; } set { @@ -614,14 +619,19 @@ public sealed class BSCharacter : BSPhysObject // The 'size' given by the simulator is the mid-point of the avatar // and X and Y are unspecified. - OMV.Vector3 newScale = OMV.Vector3.Zero; - newScale.X = PhysicsScene.Params.avatarCapsuleRadius; - newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; + OMV.Vector3 newScale = size; + // newScale.X = PhysicsScene.Params.avatarCapsuleWidth; + // newScale.Y = PhysicsScene.Params.avatarCapsuleDepth; // From the total height, remove the capsule half spheres that are at each end // The 1.15f came from ODE. Not sure what this factors in. - newScale.Z = (size.Z * 1.15f) - (newScale.X + newScale.Y); - Scale = newScale; + // newScale.Z = (size.Z * 1.15f) - (newScale.X + newScale.Y); + + // The total scale height is the central cylindar plus the caps on the two ends. + newScale.Z = size.Z + (Math.Min(size.X, size.Y) * 2f); + + // Convert diameters to radii and height to half height -- the way Bullet expects it. + Scale = newScale / 2f; } // set _avatarVolume and _mass based on capsule size, _density and Scale diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 2657e4b..5d16bbf 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -93,7 +93,7 @@ public sealed class BSPrim : BSPhysObject _physicsActorType = (int)ActorTypes.Prim; _position = pos; _size = size; - Scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type + Scale = size; // the scale will be set by CreateGeom depending on object type _orientation = rotation; _buoyancy = 1f; _velocity = OMV.Vector3.Zero; @@ -154,6 +154,8 @@ public sealed class BSPrim : BSPhysObject public override OMV.Vector3 Size { get { return _size; } set { + // We presume the scale and size are the same. If scale must be changed for + // the physical shape, that is done when the geometry is built. _size = value; ForceBodyShapeRebuild(false); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 0e73d04..27a78d1 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -1185,14 +1185,18 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarRestitution; }, (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarRestitution, p, l, v); } ), - new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar", - 0.37f, - (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); }, - (s) => { return s.m_params[0].avatarCapsuleRadius; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ), + new ParameterDefn("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule", + 0.6f, + (s,cf,p,v) => { s.m_params[0].avatarCapsuleWidth = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].avatarCapsuleWidth; }, + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleWidth, p, l, v); } ), + new ParameterDefn("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule", + 0.45f, + (s,cf,p,v) => { s.m_params[0].avatarCapsuleDepth = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].avatarCapsuleDepth; }, + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleDepth, p, l, v); } ), new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar", - // 1.5f, - 2.140599f, + 1.5f, (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarCapsuleHeight; }, (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ), diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index a53ad6e..869735c 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -525,9 +525,6 @@ public sealed class BSShapeCollection : IDisposable // release any previous shape DereferenceShape(prim.PhysShape, true, shapeCallback); - // Bullet native objects are scaled by the Bullet engine so pass the size in - prim.Scale = prim.Size; - BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey); // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. @@ -547,12 +544,13 @@ public sealed class BSShapeCollection : IDisposable nativeShapeData.Type = shapeType; nativeShapeData.ID = prim.LocalID; nativeShapeData.Scale = prim.Scale; - nativeShapeData.Size = prim.Scale; + nativeShapeData.Size = prim.Scale; // unneeded, I think. nativeShapeData.MeshKey = (ulong)shapeKey; nativeShapeData.HullKey = (ulong)shapeKey; if (shapeType == PhysicsShapeType.SHAPE_CAPSULE) { + // The proper scale has been calculated in the prim. newShape = new BulletShape( BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale) , shapeType); @@ -560,6 +558,9 @@ public sealed class BSShapeCollection : IDisposable } else { + // Native shapes are scaled in Bullet so set the scaling to the size + prim.Scale = prim.Size; + nativeShapeData.Scale = prim.Scale; newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, nativeShapeData), shapeType); } if (newShape.ptr == IntPtr.Zero) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 097cd3e..71fca33 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -308,7 +308,7 @@ public sealed class BSTerrainManager { PhysicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}", LogHeader, PhysicsScene.RegionName, terrainRegionBase, - PhysicsScene.Params.terrainImplementation); + (BSTerrainPhys.TerrainImplementation)PhysicsScene.Params.terrainImplementation); BSTerrainPhys newTerrainPhys = null; switch ((int)PhysicsScene.Params.terrainImplementation) { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index e218053..4647c2d 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -291,7 +291,8 @@ public struct ConfigurationParameters public float avatarStandingFriction; public float avatarDensity; public float avatarRestitution; - public float avatarCapsuleRadius; + public float avatarCapsuleWidth; + public float avatarCapsuleDepth; public float avatarCapsuleHeight; public float avatarContactProcessingThreshold; -- cgit v1.1