// 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; }
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; }
// I am the root of a linkset and a new child is being added public void AddChildToLinkset(BSPrim pchild) { BSPrim child = pchild; _scene.TaintedObject(delegate() { if (!_childrenPrims.Contains(child)) { _childrenPrims.Add(child); child.ParentPrim = this; // the child has gained a parent RecreateGeomAndObject(); // rebuild my shape with the new child added } }); return; }
public BSDynamics(BSScene myScene, BSPrim myPrim, string actorName) : base(myScene, myPrim, actorName) { ControllingPrim = myPrim; Type = Vehicle.TYPE_NONE; m_haveRegisteredForSceneEvents = false; SetupVehicleDebugging(); }
// 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); } } }
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; }
// 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 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; }
// 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; }
// 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; }
// Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', // this routine will restore the removed constraints. // Called at taint-time!! public override void RestoreBodyDependencies(BSPrim child) { }
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; }
// 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);
public BSDynamics(BSScene myScene, BSPrim myPrim) { PhysicsScene = myScene; Prim = myPrim; Type = Vehicle.TYPE_NONE; SetupVehicleDebugging(); }
// 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 (newMeshKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) 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 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; }
// 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 }
public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType) { if (newType == Vehicle.TYPE_NONE) { RemoveVehiclePrim(vehic); } else { // make it so the scene will call us each tick to do vehicle things AddVehiclePrim(vehic); } }
// 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; }
// 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); } } }
// 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 // 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; }
private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. public BSDynamics(BSPrim myPrim) { m_prim = myPrim; m_type = Vehicle.TYPE_NONE; }
#pragma warning restore 414 public BSDynamics(BSScene myScene, BSPrim myPrim, string actorName) : base(myScene, myPrim, actorName) { Type = Vehicle.TYPE_NONE; m_haveRegisteredForSceneEvents = false; ControllingPrim = myPrim as BSPrimLinkable; if (ControllingPrim == null) { // THIS CANNOT HAPPEN!! } VDetailLog("{0},Creation", ControllingPrim.LocalID); }
// 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 override 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},rBody={2}", child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); } 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")); // ret = PhysicallyUnlinkAChildFromRoot(LinksetRoot, child); // Despite the function name, this removes any link to the specified object. ret = PhysicallyUnlinkAllChildrenFromRoot(child); } } return ret; }
public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) { // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); _localID = localID; _avName = primName; _scene = parent_scene; _position = pos; _size = size; _scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type _orientation = rotation; _buoyancy = 1f; _velocity = OMV.Vector3.Zero; _rotationalVelocity = OMV.Vector3.Zero; _angularVelocity = OMV.Vector3.Zero; _hullKey = 0; _meshKey = 0; _pbs = pbs; _isPhysical = pisPhysical; _isVolumeDetect = false; _subscribedEventsMs = 0; _friction = _scene.Params.defaultFriction; // TODO: compute based on object material _density = _scene.Params.defaultDensity; // TODO: compute based on object material _restitution = _scene.Params.defaultRestitution; _parentPrim = null; // not a child or a parent _vehicle = new BSDynamics(this); // add vehicleness _childrenPrims = new List<BSPrim>(); if (_isPhysical) _mass = CalculateMass(); else _mass = 0f; // do the actual object creation at taint time _scene.TaintedObject(delegate() { RecreateGeomAndObject(); }); }
public BSPrim(ISceneChildEntity entity, bool isPhysical, BSScene parent_scene) { _parent_entity = entity; // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); _localID = _parent_entity.LocalId; _avName = _parent_entity.Name; _scene = parent_scene; _position = _parent_entity.AbsolutePosition; _size = _parent_entity.Scale; _scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type _orientation = _parent_entity.Rotation; _buoyancy = 1f; _velocity = OMV.Vector3.Zero; _rotationalVelocity = OMV.Vector3.Zero; _angularVelocity = OMV.Vector3.Zero; _hullKey = 0; _pbs = _parent_entity.Shape; _isPhysical = isPhysical; _isVolumeDetect = _parent_entity.VolumeDetectActive; _subscribedEventsMs = 0; _parentPrim = null; _vehicle = new BSDynamics(this); _childrenPrims = new List<BSPrim>(); if (_isPhysical) _mass = CalculateMass(); else _mass = 0f; // do the actual object creation at taint time _scene.TaintedObject(delegate() { RecreateGeomAndObject(); }); }
// I am the root of a linkset and one of my children is being removed. // Safe to call even if the child is not really in my linkset. public void RemoveChildFromLinkset(BSPrim pchild) { BSPrim child = pchild; _scene.TaintedObject(delegate() { if (_childrenPrims.Contains(child)) { BulletSimAPI.RemoveConstraint(_scene.WorldID, child.LocalID, this.LocalID); _childrenPrims.Remove(child); child.ParentPrim = null; // the child has lost its parent RecreateGeomAndObject(); // rebuild my shape with the child removed } else { m_log.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset"); } }); return; }
// 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. }