// Creates a native shape and assignes it to prim.BSShape private bool GetReferenceToNativeShape(BSPrim prim, ShapeData shapeData, ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, ShapeDestructionCallback shapeCallback) { BulletShape newShape; shapeData.Type = shapeType; // Bullet native objects are scaled by the Bullet engine so pass the size in prim.Scale = shapeData.Size; shapeData.Scale = shapeData.Size; // release any previous shape DereferenceShape(prim.BSShape, true, shapeCallback); // Native shapes are always built independently. newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); newShape.shapeKey = (ulong)shapeKey; newShape.isNativeShape = true; // Don't need to do a 'ReferenceShape()' here because native shapes are not tracked. // DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1}", shapeData.ID, newShape); prim.BSShape = newShape; return(true); }
// See that hull shape exists in the physical world and update prim.BSShape. // We could be creating the hull because scale changed or whatever. private bool GetReferenceToHull(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback) { BulletShape newShape; float lod; ulong newHullKey = ComputeShapeKey(shapeData, pbs, out lod); // if the hull hasn't changed, don't rebuild it if (newHullKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) { return(false); } DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}", prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newHullKey.ToString("X")); // Remove usage of the previous shape. Also removes reference to underlying mesh if it is a hull. DereferenceShape(prim.BSShape, true, shapeCallback); newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod); ReferenceShape(newShape); // hulls are already scaled by the meshmerizer prim.Scale = new OMV.Vector3(1f, 1f, 1f); prim.BSShape = newShape; return(true); // 'true' means a new shape has been added to this prim }
// Builds a mesh shape in the physical world and updates prim.BSShape. // Dereferences previous shape in BSShape and adds a reference for this new shape. // Returns 'true' of a mesh was actually built. Otherwise . // Called at taint-time! private bool GetReferenceToMesh(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback) { BulletShape newShape = new BulletShape(IntPtr.Zero); float lod; ulong newMeshKey = ComputeShapeKey(shapeData, pbs, out lod); // if this new shape is the same as last time, don't recreate the mesh if (prim.BSShape.shapeKey == newMeshKey) { return(false); } DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,oldKey={1},newKey={2}", prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); // Since we're recreating new, get rid of the reference to the previous shape DereferenceShape(prim.BSShape, true, shapeCallback); newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, pbs, shapeData.Size, lod); ReferenceShape(newShape); // meshes are already scaled by the meshmerizer prim.Scale = new OMV.Vector3(1f, 1f, 1f); prim.BSShape = newShape; return(true); // 'true' means a new shape has been added to this prim }
public override void RemovePrim(PhysicsActor prim) { if (!m_initialized) { return; } BSPrim bsprim = prim as BSPrim; if (bsprim != null) { DetailLog("{0},RemovePrim,call", bsprim.LocalID); // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID); try { lock (PhysObjects) PhysObjects.Remove(bsprim.LocalID); } catch (Exception e) { m_log.ErrorFormat("{0}: Attempt to remove prim that is not in physics scene: {1}", LogHeader, e); } bsprim.Destroy(); // bsprim.dispose(); } else { m_log.ErrorFormat("{0}: Attempt to remove prim that is not a BSPrim type.", LogHeader); } }
// Routine used when rebuilding the body of the root of the linkset // Destroy all the constraints have have been made to root. // This is called when the root body is changing. // Returns 'true' of something eas actually removed and would need restoring // Called at taint-time!! public bool RemoveBodyDependencies(BSPrim child) { bool ret = false; lock (m_linksetActivityLock) { if (IsRoot(child)) { // If the one with the dependency is root, must undo all children DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},numChild={2}", child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); foreach (BSPhysObject bpo in m_taintChildren) { PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody); ret = true; } } else { DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeSingleChild,rID={1},rBody={2},cID={3},cBody={4}", child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), child.LocalID, child.BSBody.ptr.ToString("X")); // Remove the dependency on the body of this one if (m_taintChildren.Contains(child)) { PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody); ret = true; } } } return(ret); }
public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, Vector3 size, Quaternion rotation, bool isPhysical, uint localID) { // m_log.DebugFormat("{0}: AddPrimShape2: {1}", LogHeader, primName); BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical); lock (m_prims) m_prims.Add(localID, prim); return(prim); }
// Remove a prim from our list of vehicles. // Safe to call if the prim is not in the vehicle list. public void RemoveVehiclePrim(BSPrim vehicle) { lock (m_vehicles) { if (m_vehicles.Contains(vehicle)) { m_vehicles.Remove(vehicle); } } }
// Make so the scene will call this prim for vehicle actions each tick. // Safe to call if prim is already in the vehicle list. public void AddVehiclePrim(BSPrim vehicle) { lock (m_vehicles) { if (!m_vehicles.Contains(vehicle)) { m_vehicles.Add(vehicle); } } }
// Create a body object in Bullet. // Updates prim.BSBody with the information about the new body if one is created. // Returns 'true' if an object was actually created. // Called at taint-time. private bool CreateBody(bool forceRebuild, BSPrim prim, BulletSim sim, BulletShape shape, ShapeData shapeData, BodyDestructionCallback bodyCallback) { bool ret = false; // the mesh, hull or native shape must have already been created in Bullet bool mustRebuild = (prim.BSBody.ptr == IntPtr.Zero); // If there is an existing body, verify it's of an acceptable type. // If not a solid object, body is a GhostObject. Otherwise a RigidBody. if (!mustRebuild) { CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(prim.BSBody.ptr); if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT) { // If the collisionObject is not the correct type for solidness, rebuild what's there mustRebuild = true; } } if (mustRebuild || forceRebuild) { DereferenceBody(prim.BSBody, true, bodyCallback); BulletBody aBody; IntPtr bodyPtr = IntPtr.Zero; if (prim.IsSolid) { bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, shapeData.ID, shapeData.Position, shapeData.Rotation); // DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); } else { bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, shapeData.ID, shapeData.Position, shapeData.Rotation); // DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); } aBody = new BulletBody(shapeData.ID, bodyPtr); ReferenceBody(aBody, true); prim.BSBody = aBody; ret = true; } return(ret); }
public override PhysicsObject AddPrimShape(ISceneChildEntity entity) { bool isPhysical = ((entity.ParentEntity.RootChild.Flags & PrimFlags.Physics) != 0); bool isPhantom = ((entity.ParentEntity.RootChild.Flags & PrimFlags.Phantom) != 0); bool physical = isPhysical & !isPhantom; /*IOpenRegionSettingsModule WSModule = entity.ParentEntity.Scene.RequestModuleInterface<IOpenRegionSettingsModule> (); * if (WSModule != null) * if (!WSModule.AllowPhysicalPrims) * physical = false;*/ BSPrim prim = new BSPrim(entity, isPhysical, this); lock (m_prims) m_prims.Add(entity.LocalId, prim); return(prim); }
// Routine called when rebuilding the body of some member of the linkset. // Destroy all the constraints have have been made to root and set // up to rebuild the constraints before the next simulation step. // Returns 'true' of something was actually removed and would need restoring // Called at taint-time!! public override bool RemoveBodyDependencies(BSPrim child) { bool ret = false; DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString); lock (m_linksetActivityLock) { // Just undo all the constraints for this linkset. Rebuild at the end of the step. ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); // Cause the constraints, et al to be rebuilt before the next simulation step. Refresh(LinksetRoot); } return(ret); }
public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, Vector3 size, Quaternion rotation, bool isPhysical, uint localID) { // m_log.DebugFormat("{0}: AddPrimShape2: {1}", LogHeader, primName); if (!m_initialized) { return(null); } DetailLog("{0},AddPrimShape,call", localID); BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical); lock (PhysObjects) PhysObjects.Add(localID, prim); return(prim); }
private void ReportShapeGeom(BSPrim prim) { if (prim != null) { if (prim.PhysShape.HasPhysicalShape) { BSShape physShape = prim.PhysShape; string shapeType = physShape.GetType().ToString(); switch (shapeType) { case "OpenSim.Region.Physics.BulletSPlugin.BSShapeNative": BSShapeNative nShape = physShape as BSShapeNative; prim.PhysScene.DetailLog("{0}, type={1}", prim.Name, shapeType); break; case "OpenSim.Region.Physics.BulletSPlugin.BSShapeMesh": BSShapeMesh mShape = physShape as BSShapeMesh; prim.PhysScene.DetailLog("{0}, mesh, shapeInfo={1}", prim.Name, mShape.shapeInfo); break; case "OpenSim.Region.Physics.BulletSPlugin.BSShapeHull": // BSShapeHull hShape = physShape as BSShapeHull; // prim.PhysScene.DetailLog("{0}, hull, shapeInfo={1}", prim.Name, hShape.shapeInfo); break; case "OpenSim.Region.Physics.BulletSPlugin.BSShapeConvexHull": BSShapeConvexHull chShape = physShape as BSShapeConvexHull; prim.PhysScene.DetailLog("{0}, convexHull, shapeInfo={1}", prim.Name, chShape.shapeInfo); break; case "OpenSim.Region.Physics.BulletSPlugin.BSShapeCompound": BSShapeCompound cShape = physShape as BSShapeCompound; prim.PhysScene.DetailLog("{0}, type={1}", prim.Name, shapeType); break; default: prim.PhysScene.DetailLog("{0}, type={1}", prim.Name, shapeType); break; } } } }
// Routine called when rebuilding the body of some member of the linkset. // Since we don't keep in world relationships, do nothing unless it's a child changing. // Returns 'true' of something was actually removed and would need restoring // Called at taint-time!! public override bool RemoveBodyDependencies(BSPrim child) { bool ret = false; DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}", child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString, IsRoot(child)); if (!IsRoot(child)) { // Because it is a convenient time, recompute child world position and rotation based on // its position in the linkset. RecomputeChildWorldPosition(child, true); } // Cannot schedule a refresh/rebuild here because this routine is called when // the linkset is being rebuilt. // InternalRefresh(LinksetRoot); return(ret); }
// Called to update/change the body and shape for an object. // First checks the shape and updates that if necessary then makes // sure the body is of the right type. // Return 'true' if either the body or the shape changed. // Called at taint-time!! public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) { bool ret = false; // This lock could probably be pushed down lower but building shouldn't take long lock (m_collectionActivityLock) { // Do we have the correct geometry for this type of object? // Updates prim.BSShape with information/pointers to requested shape bool newGeom = CreateGeom(forceRebuild, prim, shapeData, pbs, shapeCallback); // If we had to select a new shape geometry for the object, // rebuild the body around it. // Updates prim.BSBody with information/pointers to requested body bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, prim.BSShape, shapeData, bodyCallback); ret = newGeom || newBody; } DetailLog("{0},BSShapeCollection.GetBodyAndShape,force={1},ret={2},body={3},shape={4}", prim.LocalID, forceRebuild, ret, prim.BSBody, prim.BSShape); return(ret); }
// Routine used when rebuilding the body of the root of the linkset // This is called after RemoveAllLinksToRoot() to restore all the constraints. // This is called when the root body has been changed. // Called at taint-time!! public void RestoreBodyDependencies(BSPrim child) { lock (m_linksetActivityLock) { if (IsRoot(child)) { DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreChildrenForRoot,rID={1},numChild={2}", child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); foreach (BSPhysObject bpo in m_taintChildren) { PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody); } } else { DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreSingleChild,rID={1},rBody={2},cID={3},cBody={4}", LinksetRoot.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), child.LocalID, child.BSBody.ptr.ToString("X")); PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody); } } }
private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. public BSDynamics(BSPrim myPrim) { m_prim = myPrim; m_type = Vehicle.TYPE_NONE; }
// Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', // this routine will restore the removed constraints. // Called at taint-time!! public abstract void RestoreBodyDependencies(BSPrim child);
// Routine used when rebuilding the body of the root of the linkset // Destroy all the constraints have have been made to root. // This is called when the root body is changing. // Returns 'true' of something was actually removed and would need restoring // Called at taint-time!! public abstract bool RemoveBodyDependencies(BSPrim child);
// Create the geometry information in Bullet for later use. // The objects needs a hull if it's physical otherwise a mesh is enough. // No locking here because this is done when we know physics is not simulating. // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used. // Returns 'true' if the geometry was rebuilt. // Called at taint-time! private bool CreateGeom(bool forceRebuild, BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback) { bool ret = false; bool haveShape = false; bool nativeShapePossible = true; // If the prim attributes are simple, this could be a simple Bullet native shape if (nativeShapePossible && ((pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim) || (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 && pbs.ProfileHollow == 0 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0 && pbs.PathBegin == 0 && pbs.PathEnd == 0 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 && pbs.PathShearX == 0 && pbs.PathShearY == 0))) { if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) { haveShape = true; if (forceRebuild || prim.Scale != shapeData.Size || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE ) { ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_SPHERE, ShapeData.FixedShapeKey.KEY_SPHERE, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", prim.LocalID, forceRebuild, prim.BSShape); } } else { haveShape = true; if (forceRebuild || prim.Scale != shapeData.Size || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX ) { ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", prim.LocalID, forceRebuild, prim.BSShape); } } } // If a simple shape is not happening, create a mesh and possibly a hull. // Note that if it's a native shape, the check for physical/non-physical is not // made. Native shapes are best used in either case. if (!haveShape) { if (prim.IsPhysical) { // Update prim.BSShape to reference a hull of this shape. ret = GetReferenceToHull(prim, shapeData, pbs, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", shapeData.ID, prim.BSShape, prim.BSShape.shapeKey.ToString("X")); } else { ret = GetReferenceToMesh(prim, shapeData, pbs, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", shapeData.ID, prim.BSShape, prim.BSShape.shapeKey.ToString("X")); } } return(ret); }
private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. public BSDynamics(BSScene myScene, BSPrim myPrim) { PhysicsScene = myScene; Prim = myPrim; Type = Vehicle.TYPE_NONE; }
[TestCase(7, 2, 5f, 5f, 32, 0f)] /* default hull parameters */ public void GeomHullConvexDecomp(int maxDepthSplit, int maxDepthSplitForSimpleShapes, float concavityThresholdPercent, float volumeConservationThresholdPercent, int maxVertices, float maxSkinWidth) { // Setup the physics engine to use the C# version of convex decomp Dictionary <string, string> engineParams = new Dictionary <string, string>(); engineParams.Add("MeshSculptedPrim", "true"); // ShouldMeshSculptedPrim engineParams.Add("ForceSimplePrimMeshing", "false"); // ShouldForceSimplePrimMeshing engineParams.Add("UseHullsForPhysicalObjects", "true"); // ShouldUseHullsForPhysicalObjects engineParams.Add("ShouldRemoveZeroWidthTriangles", "true"); engineParams.Add("ShouldUseBulletHACD", "false"); engineParams.Add("ShouldUseSingleConvexHullForPrims", "true"); engineParams.Add("ShouldUseGImpactShapeForPrims", "false"); engineParams.Add("ShouldUseAssetHulls", "true"); engineParams.Add("CSHullMaxDepthSplit", maxDepthSplit.ToString()); engineParams.Add("CSHullMaxDepthSplitForSimpleShapes", maxDepthSplitForSimpleShapes.ToString()); engineParams.Add("CSHullConcavityThresholdPercent", concavityThresholdPercent.ToString()); engineParams.Add("CSHullVolumeConservationThresholdPercent", volumeConservationThresholdPercent.ToString()); engineParams.Add("CSHullMaxVertices", maxVertices.ToString()); engineParams.Add("CSHullMaxSkinWidth", maxSkinWidth.ToString()); PhysicsScene = BulletSimTestsUtil.CreateBasicPhysicsEngine(engineParams); PrimitiveBaseShape pbs; Vector3 pos; Vector3 size; Quaternion rot; bool isPhys; // Cylinder pbs = PrimitiveBaseShape.CreateCylinder(); pos = new Vector3(100.0f, 100.0f, 0f); pos.Z = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos) + 10f; ObjectInitPosition = pos; size = new Vector3(2f, 2f, 2f); pbs.Scale = size; rot = Quaternion.Identity; isPhys = true; uint cylinderLocalID = 123; PhysicsScene.AddPrimShape("testCylinder", pbs, pos, size, rot, isPhys, cylinderLocalID); BSPrim primTypeCylinder = (BSPrim)PhysicsScene.PhysObjects[cylinderLocalID]; // Hollow Cylinder pbs = PrimitiveBaseShape.CreateCylinder(); pbs.ProfileHollow = (ushort)(0.70f * 50000); pos = new Vector3(110.0f, 110.0f, 0f); pos.Z = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos) + 10f; ObjectInitPosition = pos; size = new Vector3(2f, 2f, 2f); pbs.Scale = size; rot = Quaternion.Identity; isPhys = true; uint hollowCylinderLocalID = 124; PhysicsScene.AddPrimShape("testHollowCylinder", pbs, pos, size, rot, isPhys, hollowCylinderLocalID); BSPrim primTypeHollowCylinder = (BSPrim)PhysicsScene.PhysObjects[hollowCylinderLocalID]; // Torus // ProfileCurve = Circle, PathCurve = Curve1 pbs = PrimitiveBaseShape.CreateSphere(); pbs.ProfileShape = (byte)ProfileShape.Circle; pbs.PathCurve = (byte)Extrusion.Curve1; pbs.PathScaleX = 100; // default hollow info as set in the viewer pbs.PathScaleY = (int)(.25f / 0.01f) + 200; pos = new Vector3(120.0f, 120.0f, 0f); pos.Z = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos) + 10f; ObjectInitPosition = pos; size = new Vector3(2f, 4f, 4f); pbs.Scale = size; rot = Quaternion.Identity; isPhys = true; uint torusLocalID = 125; PhysicsScene.AddPrimShape("testTorus", pbs, pos, size, rot, isPhys, torusLocalID); BSPrim primTypeTorus = (BSPrim)PhysicsScene.PhysObjects[torusLocalID]; // The actual prim shape creation happens at taint time PhysicsScene.ProcessTaints(); // Check out the created hull shapes and report their characteristics ReportShapeGeom(primTypeCylinder); ReportShapeGeom(primTypeHollowCylinder); ReportShapeGeom(primTypeTorus); }
// Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', // this routine will restore the removed constraints. // Called at taint-time!! public override void RestoreBodyDependencies(BSPrim child) { // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints. }
// Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', // this routine will restore the removed constraints. // Called at taint-time!! public override void RestoreBodyDependencies(BSPrim child) { }