// 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); }
// called when this character is being destroyed and the resources should be released public void Destroy() { _scene.TaintedObject(delegate() { BulletSimAPI.DestroyObject(_scene.WorldID, _localID); }); }
/* * // Remove linkage between myself and any possible children I might have. * // Called at taint time! * private void PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) * { * DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); * * PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody); * } */ // Call each of the constraints that make up this linkset and recompute the // various transforms and variables. Used when objects are added or removed // from a linkset to make sure the constraints know about the new mass and // geometry. // Must only be called at taint time!! private void RecomputeLinksetConstraintVariables() { float linksetMass = LinksetMass; foreach (BSPhysObject child in m_taintChildren) { BSConstraint constrain; if (PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain)) { // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID); constrain.RecomputeConstraintVariables(linksetMass); } else { // Non-fatal error that happens when children are being added to the linkset but // their constraints have not been created yet. break; } } // If the whole linkset is not here, doesn't make sense to recompute linkset wide values if (m_children.Count == m_taintChildren.Count) { // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); foreach (BSPhysObject child in m_taintChildren) { BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); } } return; }
// 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() { // 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); m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID, BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID, Vector3.Zero, Quaternion.Identity)); BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr); // Everything collides with the ground plane. 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); }
// update all the localIDs specified // If the local ID is APPLY_TO_NONE, just change the default value // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs // If the localID is a specific object, apply the parameter change to only that object private void UpdateParameterSet(List <uint> lIDs, ref float defaultLoc, string parm, uint localID, float val) { switch (localID) { case PhysParameterEntry.APPLY_TO_NONE: defaultLoc = val; // setting only the default value break; case PhysParameterEntry.APPLY_TO_ALL: defaultLoc = val; // setting ALL also sets the default value List <uint> objectIDs = lIDs; string xparm = parm.ToLower(); float xval = val; TaintedObject(delegate() { foreach (uint lID in objectIDs) { BulletSimAPI.UpdateParameter(m_worldID, lID, xparm, xval); } }); break; default: // setting only one localID TaintedUpdateParameter(parm, localID, val); break; } }
// called when this character is being destroyed and the resources should be released public override void Destroy() { DetailLog("{0},BSCharacter.Destroy", LocalID); PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() { BulletSimAPI.DestroyObject(PhysicsScene.WorldID, LocalID); }); }
public override void SetTerrain(float[] heightMap) { m_heightMap = heightMap; this.TaintedObject(delegate() { BulletSimAPI.SetHeightmap(m_worldID, m_heightMap); }); }
public override void UnSubscribeEvents() { // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName); SubscribedEventsMs = 0; PhysicsScene.TaintedObject(TypeName + ".UnSubscribeEvents", delegate() { CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); }); }
public virtual bool SetAngularLimits(Vector3 low, Vector3 high) { bool ret = false; if (m_enabled) { ret = BulletSimAPI.SetAngularLimits2(m_constraint.ptr, low, high); } return(ret); }
public virtual void Dispose() { if (m_enabled) { m_enabled = false; bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr); m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success); m_constraint.ptr = System.IntPtr.Zero; } }
// schedule the actual updating of the paramter to when the phys engine is not busy private void TaintedUpdateParameter(string parm, uint localID, float val) { uint xlocalID = localID; string xparm = parm.ToLower(); float xval = val; TaintedObject(delegate() { BulletSimAPI.UpdateParameter(m_worldID, xlocalID, xparm, xval); }); }
public bool SetBreakingImpulseThreshold(float threshold) { bool ret = false; if (m_enabled) { ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.ptr, threshold); } return(ret); }
// Release the usage of a body. // Called when releasing use of a BSBody. BSShape is handled separately. public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback) { if (body.ptr == IntPtr.Zero) { return; } lock (m_collectionActivityLock) { BodyDesc bodyDesc; if (Bodies.TryGetValue(body.ID, out bodyDesc)) { bodyDesc.referenceCount--; bodyDesc.lastReferenced = System.DateTime.Now; Bodies[body.ID] = bodyDesc; DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", body.ID, bodyDesc.referenceCount); // If body is no longer being used, free it -- bodies are never shared. if (bodyDesc.referenceCount == 0) { Bodies.Remove(body.ID); BSScene.TaintCallback removeOperation = delegate() { DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}", body.ID, body.ptr.ToString("X")); // If the caller needs to know, pass the event up. if (bodyCallback != null) { bodyCallback(body); } // Zero any reference to the shape so it is not freed when the body is deleted. BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); // It may have already been removed from the world in which case the next is a NOOP. BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); }; // If already in taint-time, do the operations now. Otherwise queue for later. if (inTaintTime) { removeOperation(); } else { PhysicsScene.TaintedObject("BSShapeCollection.DereferenceBody", removeOperation); } } } else { DetailLog("{0},BSShapeCollection.DereferenceBody,DID NOT FIND BODY", body.ID, bodyDesc.referenceCount); } } }
public virtual bool SetSolverIterations(float cnt) { bool ret = false; if (m_enabled) { BulletSimAPI.SetConstraintNumSolverIterations2(m_constraint.ptr, cnt); ret = true; } return(ret); }
public void Destroy() { #if (!ISWIN) _scene.TaintedObject(delegate() { BulletSimAPI.DestroyObject(_scene.WorldID, _localID); }); #else _scene.TaintedObject(() => BulletSimAPI.DestroyObject(_scene.WorldID, _localID)); #endif }
public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce) { bool ret = false; float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; if (m_enabled) { ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.ptr, onOff, targetVelocity, maxMotorForce); } return(ret); }
public bool UseFrameOffset(bool useOffset) { bool ret = false; float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; if (m_enabled) { ret = BulletSimAPI.UseFrameOffset2(m_constraint.ptr, onOff); } return(ret); }
public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot) { bool ret = false; if (m_enabled) { BulletSimAPI.SetFrames2(m_constraint.ptr, frameA, frameArot, frameB, frameBrot); ret = true; } return(ret); }
// Release all the terrain we have allocated public void ReleaseTerrain() { foreach (KeyValuePair <Vector2, BulletHeightMapInfo> kvp in m_heightMaps) { if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, kvp.Value.terrainBody.ptr)) { BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, kvp.Value.terrainBody.ptr); BulletSimAPI.ReleaseHeightMapInfo2(kvp.Value.Ptr); } } m_heightMaps.Clear(); }
public virtual bool CalculateTransforms() { bool ret = false; if (m_enabled) { // Recompute the internal transforms BulletSimAPI.CalculateTransforms2(m_constraint.ptr); ret = true; } return(ret); }
// Set motion values to zero. // Do it to the properties so the values get set in the physics engine. // Push the setting of the values to the viewer. // Called at taint time! public override void ZeroMotion() { _velocity = OMV.Vector3.Zero; _acceleration = OMV.Vector3.Zero; _rotationalVelocity = OMV.Vector3.Zero; // Zero some other properties directly into the physics engine BulletSimAPI.SetLinearVelocity2(BSBody.ptr, OMV.Vector3.Zero); BulletSimAPI.SetAngularVelocity2(BSBody.ptr, OMV.Vector3.Zero); BulletSimAPI.SetInterpolationVelocity2(BSBody.ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); BulletSimAPI.ClearForces2(BSBody.ptr); }
public bool SetCFMAndERP(float cfm, float erp) { bool ret = false; if (m_enabled) { BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL); BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL); BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); ret = true; } return(ret); }
// Release all the terrain structures we might have allocated public void ReleaseGroundPlaneAndTerrain() { if (m_groundPlane.ptr != IntPtr.Zero) { if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr)) { BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_groundPlane.ptr); } m_groundPlane.ptr = IntPtr.Zero; } ReleaseTerrain(); }
public override void SetTerrain(ITerrainChannel channel, short[] heightMap) { m_heightMap = channel; this.TaintedObject(delegate { float[] t = new float[heightMap.Length]; for (int i = 0; i < heightMap.Length; i++) { t[i] = (heightMap[i]) / Constants.TerrainCompression; } BulletSimAPI.SetHeightmap(m_worldID, t); }); }
public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying) { base.BaseInitialize(parent_scene, localID, avName, "BSCharacter"); _physicsActorType = (int)ActorTypes.Agent; _position = pos; _size = size; _flying = isFlying; _orientation = OMV.Quaternion.Identity; _velocity = OMV.Vector3.Zero; _buoyancy = ComputeBuoyancyFromFlying(isFlying); // The dimensions of the avatar capsule are kept in the scale. // Physics creates a unit capsule which is scaled by the physics engine. ComputeAvatarScale(_size); _avatarDensity = PhysicsScene.Params.avatarDensity; // set _avatarVolume and _mass based on capsule size, _density and _scale ComputeAvatarVolumeAndMass(); ShapeData shapeData = new ShapeData(); shapeData.ID = LocalID; shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR; shapeData.Position = _position; shapeData.Rotation = _orientation; shapeData.Velocity = _velocity; shapeData.Scale = _scale; shapeData.Mass = _mass; shapeData.Buoyancy = _buoyancy; shapeData.Static = ShapeData.numericFalse; shapeData.Friction = PhysicsScene.Params.avatarFriction; shapeData.Restitution = PhysicsScene.Params.avatarRestitution; // do actual create at taint time PhysicsScene.TaintedObject("BSCharacter.create", delegate() { DetailLog("{0},BSCharacter.create,taint", LocalID); BulletSimAPI.CreateObject(PhysicsScene.WorldID, shapeData); // Set the buoyancy for flying. This will be refactored when all the settings happen in C#. // If not set at creation, the avatar will stop flying when created after crossing a region boundry. BulletSimAPI.SetObjectBuoyancy(PhysicsScene.WorldID, LocalID, _buoyancy); BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(PhysicsScene.World.ptr, LocalID)); // This works here because CreateObject has already put the character into the physical world. BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, (uint)CollisionFilterGroups.AvatarFilter, (uint)CollisionFilterGroups.AvatarMask); }); return; }
// 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 linkage between myself and a particular child // The root and child bodies are passed in because we need to remove the constraint between // the bodies that were at unlink time. // Called at taint time! private void PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BulletBody rootBody, BSPhysObject childPrim, BulletBody childBody) { DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", rootPrim.LocalID, rootPrim.LocalID, rootBody.ptr.ToString("X"), childPrim.LocalID, childBody.ptr.ToString("X")); // Find the constraint for this link and get rid of it from the overall collection and from my list PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootBody, childBody); // Make the child refresh its location BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr); }
}//end SetDefaultsForType // Some of the properties of this prim may have changed. // Do any updating needed for a vehicle public void Refresh() { if (Type == Vehicle.TYPE_NONE) { return; } // Set the prim's inertia to zero. The vehicle code handles that and this // removes the torque action introduced by Bullet. Vector3 inertia = Vector3.Zero; BulletSimAPI.SetMassProps2(Prim.BSBody.ptr, Prim.MassRaw, inertia); BulletSimAPI.UpdateInertiaTensor2(Prim.BSBody.ptr); }
// Release the usage of a shape. // The collisionObject is released since it is a copy of the real collision shape. public void DereferenceShape(BulletShape shape, bool atTaintTime, ShapeDestructionCallback shapeCallback) { if (shape.ptr == IntPtr.Zero) { return; } BSScene.TaintCallback dereferenceOperation = delegate() { switch (shape.type) { case ShapeData.PhysicsShapeType.SHAPE_HULL: DereferenceHull(shape, shapeCallback); break; case ShapeData.PhysicsShapeType.SHAPE_MESH: DereferenceMesh(shape, shapeCallback); break; case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: break; default: // Native shapes are not tracked and are released immediately if (shape.ptr != IntPtr.Zero & shape.isNativeShape) { DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", BSScene.DetailLogZero, shape.ptr.ToString("X"), atTaintTime); if (shapeCallback != null) { shapeCallback(shape); } BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); } break; } }; if (atTaintTime) { lock (m_collectionActivityLock) { dereferenceOperation(); } } else { PhysicsScene.TaintedObject("BSShapeCollection.DereferenceShape", dereferenceOperation); } }
public BSHingeConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, Vector3 pivotInA, Vector3 pivotInB, Vector3 axisInA, Vector3 axisInB, bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) { m_world = world; m_body1 = obj1; m_body2 = obj2; m_constraint = new BulletConstraint( BulletSimAPI.CreateHingeConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr, pivotInA, pivotInB, axisInA, axisInB, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); m_enabled = true; }