protected void TriggerPreUpdatePropertyAction(ref EntityProperties entprop) { PreUpdatePropertyAction actions = OnPreUpdateProperty; if (actions != null) { actions(ref entprop); } }
// Called just as the property update is received from the physics engine. // Do any mode necessary for avatar movement. private void Process_OnPreUpdateProperty(ref EntityProperties entprop) { // Don't change position if standing on a stationary object. if (m_controllingPrim.IsStationary) { entprop.Position = m_controllingPrim.RawPosition; m_physicsScene.PE.SetTranslation(m_controllingPrim.PhysBody, entprop.Position, entprop.Rotation); } }
// The physics engine says that properties have updated. Update same and inform // the world that things have changed. public override void UpdateProperties(EntityProperties entprop) { // Don't change position if standing on a stationary object. if (!IsStationary) { _position = entprop.Position; } _orientation = entprop.Rotation; if (entprop.Velocity != OMV.Vector3.Zero && entprop.Velocity.ApproxEquals(OMV.Vector3.Zero, 0.01f) && Velocity != OMV.Vector3.Zero) { entprop.Velocity = OMV.Vector3.Zero; entprop.Acceleration = OMV.Vector3.Zero; entprop.RotationalVelocity = OMV.Vector3.Zero; Velocity = OMV.Vector3.Zero; TriggerSignificantMovement(); TriggerMovementUpdate(); } if (!entprop.Velocity.ApproxEquals(RawVelocity, 0.4f)) { RawVelocity = entprop.Velocity; TriggerSignificantMovement(); TriggerMovementUpdate(); } _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. if (PositionSanityCheck(true)) { DetailLog("{0},BSCharacter.UpdateProperties,updatePosForSanity,pos={1}", LocalID, _position); entprop.Position = _position; } // remember the current and last set values LastEntityProperties = CurrentEntityProperties; CurrentEntityProperties = entprop; // Tell the linkset about value changes // Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this); // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. // base.RequestPhysicsterseUpdate(); DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, _position, _orientation, RawVelocity, _acceleration, _rotationalVelocity); }
public override void UpdateProperties(EntityProperties entprop) { // Undo any center-of-mass displacement that might have been done. if (PositionDisplacement != OMV.Vector3.Zero || OrientationDisplacement != OMV.Quaternion.Identity) { // Correct for any rotation around the center-of-mass // TODO!!! entprop.Position = entprop.Position + (PositionDisplacement * entprop.Rotation); // entprop.Rotation = something; } base.UpdateProperties(entprop); }
// The physics engine says that properties have updated. Update same and inform // the world that things have changed. public override void UpdateProperties(EntityProperties entprop) { // Let anyone (like the actors) modify the updated properties before they are pushed into the object and the simulator. TriggerPreUpdatePropertyAction(ref entprop); RawPosition = entprop.Position; RawOrientation = entprop.Rotation; // Smooth velocity. OpenSimulator is VERY sensitive to changes in velocity of the avatar // and will send agent updates to the clients if velocity changes by more than // 0.001m/s. Bullet introduces a lot of jitter in the velocity which causes many // extra updates. // // XXX: Contrary to the above comment, setting an update threshold here above 0.4 actually introduces jitter to // avatar movement rather than removes it. The larger the threshold, the bigger the jitter. // This is most noticeable in level flight and can be seen with // the "show updates" option in a viewer. With an update threshold, the RawVelocity cycles between a lower // bound and an upper bound, where the difference between the two is enough to trigger a large delta v update // and subsequently trigger an update in ScenePresence.SendTerseUpdateToAllClients(). The cause of this cycle (feedback?) // has not yet been identified. // // If there is a threshold below 0.4 or no threshold check at all (as in ODE), then RawVelocity stays constant and extra // updates are not triggered in ScenePresence.SendTerseUpdateToAllClients(). // if (!entprop.Velocity.ApproxEquals(RawVelocity, 0.1f)) RawVelocity = entprop.Velocity; _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. if (PositionSanityCheck(true)) { DetailLog("{0},BSCharacter.UpdateProperties,updatePosForSanity,pos={1}", LocalID, RawPosition); entprop.Position = RawPosition; } // remember the current and last set values LastEntityProperties = CurrentEntityProperties; CurrentEntityProperties = entprop; // Tell the linkset about value changes // Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this); // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. // PhysScene.PostUpdate(this); DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, RawPosition, RawOrientation, RawVelocity, _acceleration, _rotationalVelocity); }
public override void UpdateProperties(EntityProperties entprop) { // Undo any center-of-mass displacement that might have been done. if (PositionDisplacement != OMV.Vector3.Zero || OrientationDisplacement != OMV.Quaternion.Identity) { // Correct for any rotation around the center-of-mass // TODO!!! OMV.Vector3 displacedPos = entprop.Position + (PositionDisplacement * entprop.Rotation); DetailLog("{0},BSPrimDisplaced.ForcePosition,physPos={1},disp={2},newPos={3}", LocalID, entprop.Position, PositionDisplacement, displacedPos); entprop.Position = displacedPos; // entprop.Rotation = something; } base.UpdateProperties(entprop); }
// The physics engine says that properties have updated. Update same and inform // the world that things have changed. public override void UpdateProperties(EntityProperties entprop) { _position = entprop.Position; _orientation = entprop.Rotation; _velocity = entprop.Velocity; _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. // base.RequestPhysicsterseUpdate(); // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. PositionSanityCheck2(); float heightHere = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); // only for debug DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5},terrain={6}", LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity, heightHere); }
public override void UpdateProperties(EntityProperties entprop) { // Undo any center-of-mass displacement that might have been done. if (PositionDisplacement != OMV.Vector3.Zero) { // The origional shape was offset from 'zero' by PositionDisplacement. // These physical location must be back converted to be centered around the displaced // root shape. // Move the returned center-of-mass location to the root prim location. OMV.Vector3 displacement = PositionDisplacement * entprop.Rotation; OMV.Vector3 displacedPos = entprop.Position - displacement; DetailLog("{0},BSPrimDisplaced.UpdateProperties,physPos={1},disp={2},simPos={3}", LocalID, entprop.Position, displacement, displacedPos); entprop.Position = displacedPos; } base.UpdateProperties(entprop); }
// The physics engine says that properties have updated. Update same and inform // the world that things have changed. public override void UpdateProperties(EntityProperties entprop) { // Don't change position if standing on a stationary object. if (!IsStationary) { _position = entprop.Position; } _orientation = entprop.Rotation; // Smooth velocity. OpenSimulator is VERY sensitive to changes in velocity of the avatar // and will send agent updates to the clients if velocity changes by more than // 0.001m/s. Bullet introduces a lot of jitter in the velocity which causes many // extra updates. if (!entprop.Velocity.ApproxEquals(RawVelocity, 0.1f)) { RawVelocity = entprop.Velocity; } _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. if (PositionSanityCheck(true)) { DetailLog("{0},BSCharacter.UpdateProperties,updatePosForSanity,pos={1}", LocalID, _position); entprop.Position = _position; } // remember the current and last set values LastEntityProperties = CurrentEntityProperties; CurrentEntityProperties = entprop; // Tell the linkset about value changes // Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this); // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. // base.RequestPhysicsterseUpdate(); DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, _position, _orientation, RawVelocity, _acceleration, _rotationalVelocity); }
// Called after a simulation step for the changes in physical object properties. // Do any filtering/modification needed for linksets. public override void UpdateProperties(EntityProperties entprop) { if (Linkset.IsRoot(this) || Linkset.ShouldReportPropertyUpdates(this)) { // Properties are only updated for the roots of a linkset. // TODO: this will have to change when linksets are articulated. base.UpdateProperties(entprop); } /* * else * { * // For debugging, report the movement of children * DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", * LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, * entprop.Acceleration, entprop.RotationalVelocity); * } */ // The linkset might like to know about changing locations Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this); }
// The physics engine says that properties have updated. Update same and inform // the world that things have changed. public void UpdateProperties(EntityProperties entprop) { bool changed = false; // we assign to the local variables so the normal set action does not happen if (_position != entprop.Position) { _position = entprop.Position; changed = true; } if (_orientation != entprop.Rotation) { _orientation = entprop.Rotation; changed = true; } if (_velocity != entprop.Velocity) { _velocity = entprop.Velocity; changed = true; } if (_acceleration != entprop.Acceleration) { _acceleration = entprop.Acceleration; changed = true; } if (_rotationalVelocity != entprop.RotationalVelocity) { _rotationalVelocity = entprop.RotationalVelocity; changed = true; } if (changed) { // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation); // Avatar movement is not done by generating this event. There is a system that // checks for avatar updates each heartbeat loop. // base.RequestPhysicsterseUpdate(); } }
// The physics engine says that properties have updated. Update same and inform // the world that things have changed. public override void UpdateProperties(EntityProperties entprop) { _position = entprop.Position; _orientation = entprop.Rotation; _velocity = entprop.Velocity; _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. PositionSanityCheck(true); // remember the current and last set values LastEntityProperties = CurrentEntityProperties; CurrentEntityProperties = entprop; // Tell the linkset about value changes Linkset.UpdateProperties(this, true); // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. // base.RequestPhysicsterseUpdate(); DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); }
public override void UpdatesLoop() { //Things work better if we do this... however bad it may be foreach (BSCharacter character in m_avatars.Values) { character.UpdateProperties(new EntityProperties()); } // If any of the objects had updated properties, tell the object it has been changed by the physics engine EntityProperties[] props = null; lock (m_entProperties) { if (m_entProperties.Count > 0) { props = new EntityProperties[m_entProperties.Count]; m_entProperties.CopyTo(props); m_entProperties.Clear(); } } if (props != null) { foreach (EntityProperties entprop in props) { // MainConsole.Instance.DebugFormat("{0}: entprop[{1}]: id={2}, pos={3}", LogHeader, ii, entprop.ID, entprop.Position); BSCharacter character; if (m_avatars.TryGetValue(entprop.ID, out character)) { character.UpdateProperties(entprop); } BSPrim prim; if (m_prims.TryGetValue(entprop.ID, out prim)) { prim.UpdateProperties(entprop); } } } }
// The physics engine says that properties have updated. Update same and inform // the world that things have changed. // NOTE: BSPrim.UpdateProperties is overloaded by BSPrimLinkable which modifies updates from root and children prims. // NOTE: BSPrim.UpdateProperties is overloaded by BSPrimDisplaced which handles mapping physical position to simulator position. public override void UpdateProperties(EntityProperties entprop) { // Let anyone (like the actors) modify the updated properties before they are pushed into the object and the simulator. TriggerPreUpdatePropertyAction(ref entprop); // DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG // Assign directly to the local variables so the normal set actions do not happen RawPosition = entprop.Position; RawOrientation = entprop.Rotation; // DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be // very sensitive to velocity changes. if (entprop.Velocity == OMV.Vector3.Zero || !entprop.Velocity.ApproxEquals(RawVelocity, BSParam.UpdateVelocityChangeThreshold)) RawVelocity = entprop.Velocity; _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; // DetailLog("{0},BSPrim.UpdateProperties,afterAssign,entprop={1}", LocalID, entprop); // DEBUG DEBUG // The sanity check can change the velocity and/or position. if (PositionSanityCheck(true /* inTaintTime */ )) { entprop.Position = RawPosition; entprop.Velocity = RawVelocity; entprop.RotationalVelocity = _rotationalVelocity; entprop.Acceleration = _acceleration; } OMV.Vector3 direction = OMV.Vector3.UnitX * RawOrientation; // DEBUG DEBUG DEBUG DetailLog("{0},BSPrim.UpdateProperties,call,entProp={1},dir={2}", LocalID, entprop, direction); // remember the current and last set values LastEntityProperties = CurrentEntityProperties; CurrentEntityProperties = entprop; PhysScene.PostUpdate(this); }
public override void UpdateProperties(EntityProperties entprop) { /* UpdatedProperties changed = 0; // assign to the local variables so the normal set action does not happen // if (_position != entprop.Position) if (!_position.ApproxEquals(entprop.Position, POSITION_TOLERANCE)) { _position = entprop.Position; changed |= UpdatedProperties.Position; } // if (_orientation != entprop.Rotation) if (!_orientation.ApproxEquals(entprop.Rotation, ROTATION_TOLERANCE)) { _orientation = entprop.Rotation; changed |= UpdatedProperties.Rotation; } // if (_velocity != entprop.Velocity) if (!_velocity.ApproxEquals(entprop.Velocity, VELOCITY_TOLERANCE)) { _velocity = entprop.Velocity; changed |= UpdatedProperties.Velocity; } // if (_acceleration != entprop.Acceleration) if (!_acceleration.ApproxEquals(entprop.Acceleration, ACCELERATION_TOLERANCE)) { _acceleration = entprop.Acceleration; changed |= UpdatedProperties.Acceleration; } // if (_rotationalVelocity != entprop.RotationalVelocity) if (!_rotationalVelocity.ApproxEquals(entprop.RotationalVelocity, ROTATIONAL_VELOCITY_TOLERANCE)) { _rotationalVelocity = entprop.RotationalVelocity; changed |= UpdatedProperties.RotationalVel; } if (changed != 0) { // Only update the position of single objects and linkset roots if (this._parentPrim == null) { base.RequestPhysicsterseUpdate(); } } */ // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. // 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 _position = entprop.Position; _orientation = entprop.Rotation; _velocity = entprop.Velocity; _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; // remember the current and last set values LastEntityProperties = CurrentEntityProperties; CurrentEntityProperties = entprop; PositionSanityCheck(true); DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); // BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, BSBody.ptr); // DEBUG DEBUG DEBUG base.RequestPhysicsterseUpdate(); } /* else { // For debugging, report the movement of children DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, entprop.Acceleration, entprop.RotationalVelocity); } */ // The linkset implimentation might want to know about this. Linkset.UpdateProperties(this); }
// Initialization and simulation public override BulletWorld Initialize(Vector3 maxPosition, ConfigurationParameters parms, int maxCollisions, ref CollisionDesc[] collisionArray, int maxUpdates, ref EntityProperties[] updateArray ) { // Pin down the memory that will be used to pass object collisions and updates back from unmanaged code m_paramsHandle = GCHandle.Alloc(parms, GCHandleType.Pinned); m_collisionArrayPinnedHandle = GCHandle.Alloc(collisionArray, GCHandleType.Pinned); m_updateArrayPinnedHandle = GCHandle.Alloc(updateArray, GCHandleType.Pinned); // If Debug logging level, enable logging from the unmanaged code m_DebugLogCallbackHandle = null; if (BSScene.m_log.IsDebugEnabled && PhysicsScene.PhysicsLogging.Enabled) { BSScene.m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", BSScene.LogHeader); if (PhysicsScene.PhysicsLogging.Enabled) // The handle is saved in a variable to make sure it doesn't get freed after this call m_DebugLogCallbackHandle = new BSAPICPP.DebugLogCallback(BulletLoggerPhysLog); else m_DebugLogCallbackHandle = new BSAPICPP.DebugLogCallback(BulletLogger); } // Get the version of the DLL // TODO: this doesn't work yet. Something wrong with marshaling the returned string. // BulletEngineVersion = BulletSimAPI.GetVersion2(); BulletEngineVersion = ""; // Call the unmanaged code with the buffers and other information return new BulletWorldUnman(0, PhysicsScene, BSAPICPP.Initialize2(maxPosition, m_paramsHandle.AddrOfPinnedObject(), maxCollisions, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), maxUpdates, m_updateArrayPinnedHandle.AddrOfPinnedObject(), m_DebugLogCallbackHandle)); }
protected void TriggerPreUpdatePropertyAction(ref EntityProperties entprop) { PreUpdatePropertyAction actions = OnPreUpdateProperty; if (actions != null) actions(ref entprop); }
public override void UpdateProperties(EntityProperties entprop) { if (Linkset.IsRoot(this)) { // Properties are only updated for the roots of a linkset. // TODO: this will have to change when linksets are articulated. base.UpdateProperties(entprop); } // The linkset might like to know about changing locations Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this); }
public override void UpdatesLoop() { //Things work better if we do this... however bad it may be foreach (BSCharacter character in m_avatars.Values) { character.UpdateProperties(new EntityProperties()); } // If any of the objects had updated properties, tell the object it has been changed by the physics engine EntityProperties[] props = null; lock (m_entProperties) { if (m_entProperties.Count > 0) { props = new EntityProperties[m_entProperties.Count]; m_entProperties.CopyTo(props); m_entProperties.Clear(); } } if (props != null) { foreach (EntityProperties entprop in props) { // MainConsole.Instance.DebugFormat("{0}: entprop[{1}]: id={2}, pos={3}", LogHeader, ii, entprop.ID, entprop.Position); BSCharacter character; if (m_avatars.TryGetValue(entprop.ID, out character)) character.UpdateProperties(entprop); BSPrim prim; if (m_prims.TryGetValue(entprop.ID, out prim)) prim.UpdateProperties(entprop); } } }
// The physics engine says that properties have updated. Update same and inform // the world that things have changed. public override void UpdateProperties(EntityProperties entprop) { // Let anyone (like the actors) modify the updated properties before they are pushed into the object and the simulator. TriggerPreUpdatePropertyAction(ref entprop); // DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG // Assign directly to the local variables so the normal set actions do not happen _position = entprop.Position; _orientation = entprop.Rotation; bool terseUpdate = false; if (entprop.Velocity != OMV.Vector3.Zero && entprop.Velocity.ApproxEquals(OMV.Vector3.Zero, 0.01f) && Velocity != OMV.Vector3.Zero) { entprop.Velocity = OMV.Vector3.Zero; entprop.Acceleration = OMV.Vector3.Zero; entprop.RotationalVelocity = OMV.Vector3.Zero; Velocity = RawVelocity = OMV.Vector3.Zero; ZeroMotion(true); terseUpdate = true; } // DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be // very sensitive to velocity changes. if (entprop.Velocity == OMV.Vector3.Zero || (VehicleType != 0 /*&& !entprop.Velocity.ApproxEquals(RawVelocity, 0.01f)*/) || !entprop.Velocity.ApproxEquals(RawVelocity, BSParam.UpdateVelocityChangeThreshold / 2f)) { terseUpdate = true; RawVelocity = entprop.Velocity; } _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; // DetailLog("{0},BSPrim.UpdateProperties,afterAssign,entprop={1}", LocalID, entprop); // DEBUG DEBUG // The sanity check can change the velocity and/or position. if (PositionSanityCheck(true /* inTaintTime */ )) { entprop.Position = _position; entprop.Velocity = RawVelocity; entprop.RotationalVelocity = _rotationalVelocity; entprop.Acceleration = _acceleration; } OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; // DEBUG DEBUG DEBUG //DetailLog("{0},BSPrim.UpdateProperties,call,entProp={1},dir={2}", LocalID, entprop, direction); // remember the current and last set values LastEntityProperties = CurrentEntityProperties; CurrentEntityProperties = entprop; if (terseUpdate) base.RequestPhysicsterseUpdate(); /* else { // For debugging, report the movement of children DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, entprop.Acceleration, entprop.RotationalVelocity); } */ }
// Simulate one timestep public override float Simulate(float timeStep) { int updatedEntityCount; IntPtr updatedEntitiesPtr; int collidersCount; IntPtr collidersPtr; // prevent simulation until we've been initialized if (!m_initialized) { return(10.0f); } // update the prim states while we know the physics engine is not busy ProcessTaints(); // Some of the prims operate with special vehicle properties ProcessVehicles(timeStep); ProcessTaints(); // the vehicles might have added taints // step the physical world one interval m_simulationStep++; int numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in // Get a value for 'now' so all the collision and update routines don't have to get their own m_simulationNowTime = Util.EnvironmentTickCount(); // If there were collisions, process them by sending the event to the prim. // Collisions must be processed before updates. if (collidersCount > 0) { for (int ii = 0; ii < collidersCount; ii++) { uint cA = m_collisionArray[ii].aID; uint cB = m_collisionArray[ii].bID; Vector3 point = m_collisionArray[ii].point; Vector3 normal = m_collisionArray[ii].normal; SendCollision(cA, cB, point, normal, 0.01f); SendCollision(cB, cA, point, -normal, 0.01f); } } // If any of the objects had updated properties, tell the object it has been changed by the physics engine if (updatedEntityCount > 0) { for (int ii = 0; ii < updatedEntityCount; ii++) { EntityProperties entprop = m_updateArray[ii]; // m_log.DebugFormat("{0}: entprop[{1}]: id={2}, pos={3}", LogHeader, ii, entprop.ID, entprop.Position); BSCharacter actor; if (m_avatars.TryGetValue(entprop.ID, out actor)) { actor.UpdateProperties(entprop); continue; } BSPrim prim; if (m_prims.TryGetValue(entprop.ID, out prim)) { prim.UpdateProperties(entprop); } } } if (m_detailedStatsStep > 0) { if ((m_simulationStep % m_detailedStatsStep) == 0) { BulletSimAPI.DumpBulletStatistics(); } } // TODO: FIX THIS: fps calculation wrong. This calculation always returns about 1 in normal operation. return(timeStep / (numSubSteps * m_fixedTimeStep) * 1000f); }
// The physics engine says that properties have updated. Update same and inform // the world that things have changed. public override void UpdateProperties(EntityProperties entprop) { _position = entprop.Position; _orientation = entprop.Rotation; _velocity = entprop.Velocity; _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. PositionSanityCheck(true); // remember the current and last set values LastEntityProperties = CurrentEntityProperties; CurrentEntityProperties = entprop; if (entprop.Velocity != LastEntityProperties.Velocity) { // Changes in the velocity are suppressed in avatars. // That's just the way they are defined. OMV.Vector3 avVel = new OMV.Vector3(_appliedVelocity.X, _appliedVelocity.Y, entprop.Velocity.Z); _velocity = avVel; BulletSimAPI.SetLinearVelocity2(BSBody.ptr, avVel); } // Tell the linkset about value changes Linkset.UpdateProperties(this); // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. // base.RequestPhysicsterseUpdate(); DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); }
// Update the physical location and motion of the object. Called with data from Bullet. public abstract void UpdateProperties(EntityProperties entprop);
public override void UpdateProperties(EntityProperties entprop) { if (Linkset.IsRoot(this)) { // Properties are only updated for the roots of a linkset. // TODO: this will have to change when linksets are articulated. base.UpdateProperties(entprop); } /* else { // For debugging, report the movement of children DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, entprop.Acceleration, entprop.RotationalVelocity); } */ // The linkset might like to know about changing locations Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this); }
// The physics engine says that properties have updated. Update same and inform // the world that things have changed. public void UpdateProperties(EntityProperties entprop) { bool changed = false; #region Updating Position if (entprop.ID != 0) { // we assign to the local variables so the normal set action does not happen if (_position != entprop.Position) { _position = entprop.Position; changed = true; } if (_orientation != entprop.Rotation) { _orientation = entprop.Rotation; changed = true; } if (_velocity != entprop.Velocity) { changed = true; _velocity = entprop.Velocity; } if (_acceleration != entprop.Acceleration) { _acceleration = entprop.Acceleration; changed = true; } if (_rotationalVelocity != entprop.RotationalVelocity) { changed = true; _rotationalVelocity = entprop.RotationalVelocity; } if (changed) TriggerMovementUpdate(); } #endregion #region Jump code if (_preJumping && Util.EnvironmentTickCountSubtract(_preJumpTime) > _scene.PreJumpTime) { //Time to jump _jumping = true; _preJumping = false; Velocity += _preJumpForce; _targetVelocityIsDecaying = false; TriggerMovementUpdate(); } if (_jumping && Util.EnvironmentTickCountSubtract(_preJumpTime) > _scene.PreJumpTime + 2000) { _jumping = false; _targetVelocity = Vector3.Zero; TriggerMovementUpdate(); } else if (_jumping && Util.EnvironmentTickCountSubtract(_preJumpTime) > _scene.PreJumpTime + 750) { _targetVelocityIsDecaying = false; TriggerMovementUpdate(); } else if (_jumping && Util.EnvironmentTickCountSubtract(_preJumpTime) > _scene.PreJumpTime + 500) { _targetVelocityIsDecaying = false; Velocity -= _preJumpForce/100; //Cut down on going up TriggerMovementUpdate(); } #endregion #region Decaying velocity if (_targetVelocityIsDecaying) { _targetVelocity *= _scene.DelayingVelocityMultiplier; if (_targetVelocity.ApproxEquals(Vector3.Zero, 0.1f) || _velocity == Vector3.Zero) _targetVelocity = Vector3.Zero; } if (_targetVelocity != Vector3.Zero) Velocity = new Vector3( _targetVelocity.X == 0 ? Velocity.X : (_targetVelocity.X*0.25f) + (Velocity.X*0.75f), _targetVelocity.Y == 0 ? Velocity.Y : (_targetVelocity.Y*0.25f) + (Velocity.Y*0.75f), _targetVelocity.Z == 0 ? Velocity.Z : (_targetVelocity.Z*0.25f) + (Velocity.Z*0.75f)); else if (Velocity.X != 0 || Velocity.Y != 0 || Velocity.Z > 0) Velocity *= _scene.DelayingVelocityMultiplier; if (Velocity.ApproxEquals(Vector3.Zero, 0.3f)) Velocity = Vector3.Zero; #endregion }
// Initialization and simulation public abstract BulletWorld Initialize(Vector3 maxPosition, ConfigurationParameters parms, int maxCollisions, ref CollisionDesc[] collisionArray, int maxUpdates, ref EntityProperties[] updateArray );
// Call the physics engine to do one 'timeStep' and collect collisions and updates // into ObjectsWithCollisions and ObjectsWithUpdates data structures. private void DoPhysicsStep(float timeStep) { // prevent simulation until we've been initialized if (!m_initialized) { return; } LastTimeStep = timeStep; int updatedEntityCount = 0; int collidersCount = 0; int beforeTime = Util.EnvironmentTickCount(); int simTime = 0; int numTaints = _taintOperations.Count; InTaintTime = true; // Only used for debugging so locking is not necessary. // update the prim states while we know the physics engine is not busy ProcessTaints(); // Some of the physical objects requre individual, pre-step calls // (vehicles and avatar movement, in particular) TriggerPreStepEvent(timeStep); // the prestep actions might have added taints numTaints += _taintOperations.Count; ProcessTaints(); InTaintTime = false; // Only used for debugging so locking is not necessary. // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world. // Only enable this in a limited test world with few objects. if (m_physicsPhysicalDumpEnabled) { PE.DumpAllInfo(World); } // step the physical world one interval m_simulationStep++; int numSubSteps = 0; try { numSubSteps = PE.PhysicsStep(World, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out collidersCount); } catch (Exception e) { m_log.WarnFormat("{0},PhysicsStep Exception: nTaints={1}, substeps={2}, updates={3}, colliders={4}, e={5}", LogHeader, numTaints, numSubSteps, updatedEntityCount, collidersCount, e); DetailLog("{0},PhysicsStepException,call, nTaints={1}, substeps={2}, updates={3}, colliders={4}", DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount); updatedEntityCount = 0; collidersCount = 0; } // Make the physics engine dump useful statistics periodically if (PhysicsMetricDumpFrames != 0 && ((m_simulationStep % PhysicsMetricDumpFrames) == 0)) { PE.DumpPhysicsStatistics(World); } // Get a value for 'now' so all the collision and update routines don't have to get their own. SimulationNowTime = Util.EnvironmentTickCount(); // Send collision information to the colliding objects. The objects decide if the collision // is 'real' (like linksets don't collide with themselves) and the individual objects // know if the simulator has subscribed to collisions. lock (CollisionLock) { if (collidersCount > 0) { for (int ii = 0; ii < collidersCount; ii++) { uint cA = m_collisionArray[ii].aID; uint cB = m_collisionArray[ii].bID; Vector3 point = m_collisionArray[ii].point; Vector3 normal = m_collisionArray[ii].normal; float penetration = m_collisionArray[ii].penetration; SendCollision(cA, cB, point, normal, penetration); SendCollision(cB, cA, point, -normal, penetration); } } } // If any of the objects had updated properties, tell the managed objects about the update // and remember that there was a change so it will be passed to the simulator. lock (UpdateLock) { if (updatedEntityCount > 0) { for (int ii = 0; ii < updatedEntityCount; ii++) { EntityProperties entprop = m_updateArray[ii]; BSPhysObject pobj; if (PhysObjects.TryGetValue(entprop.ID, out pobj)) { if (pobj.IsInitialized) { pobj.UpdateProperties(entprop); } } } } } // Some actors want to know when the simulation step is complete. TriggerPostStepEvent(timeStep); simTime = Util.EnvironmentTickCountSubtract(beforeTime); if (PhysicsLogging.Enabled) { DetailLog("{0},DoPhysicsStep,complete,frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}, objWColl={7}", DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount, ObjectsWithCollisions.Count); } // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world. // Only enable this in a limited test world with few objects. if (m_physicsPhysicalDumpEnabled) { PE.DumpAllInfo(World); } // The physics engine returns the number of milliseconds it simulated this call. // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. // Multiply by a fixed nominal frame rate to give a rate similar to the simulator (usually 55). m_simulatedTime += (float)numSubSteps * m_fixedTimeStep * 1000f * NominalFrameRate; }
// The physics engine says that properties have updated. Update same and inform // the world that things have changed. public override void UpdateProperties(EntityProperties entprop) { TriggerPreUpdatePropertyAction(ref entprop); // A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet // TODO: handle physics introduced by Bullet with computed vehicle physics. if (VehicleController.IsActive) { entprop.RotationalVelocity = OMV.Vector3.Zero; } // DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG // Assign directly to the local variables so the normal set actions do not happen _position = entprop.Position; _orientation = entprop.Rotation; // DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be // very sensitive to velocity changes. if (entprop.Velocity == OMV.Vector3.Zero || !entprop.Velocity.ApproxEquals(_velocity, BSParam.UpdateVelocityChangeThreshold)) _velocity = entprop.Velocity; _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; // DetailLog("{0},BSPrim.UpdateProperties,afterAssign,entprop={1}", LocalID, entprop); // DEBUG DEBUG // The sanity check can change the velocity and/or position. if (PositionSanityCheck(true /* inTaintTime */ )) { entprop.Position = _position; entprop.Velocity = _velocity; entprop.RotationalVelocity = _rotationalVelocity; entprop.Acceleration = _acceleration; } OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; // DEBUG DEBUG DEBUG DetailLog("{0},BSPrim.UpdateProperties,call,entProp={1},dir={2}", LocalID, entprop, direction); // remember the current and last set values LastEntityProperties = CurrentEntityProperties; CurrentEntityProperties = entprop; base.RequestPhysicsterseUpdate(); /* else { // For debugging, report the movement of children DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, entprop.Acceleration, entprop.RotationalVelocity); } */ }
// The physics engine says that properties have updated. Update same and inform // the world that things have changed. public void UpdateProperties(EntityProperties entprop) { bool changed = false; #region Updating Position if (entprop.ID != 0) { // we assign to the local variables so the normal set action does not happen if (_position != entprop.Position) { _position = entprop.Position; changed = true; } if (_orientation != entprop.Rotation) { _orientation = entprop.Rotation; changed = true; } if (_velocity != entprop.Velocity) { changed = true; _velocity = entprop.Velocity; } if (_acceleration != entprop.Acceleration) { _acceleration = entprop.Acceleration; changed = true; } if (_rotationalVelocity != entprop.RotationalVelocity) { changed = true; _rotationalVelocity = entprop.RotationalVelocity; } if (changed) { TriggerMovementUpdate(); } } #endregion #region Jump code if (_preJumping && Util.EnvironmentTickCountSubtract(_preJumpTime) > _scene.PreJumpTime) { //Time to jump _jumping = true; _preJumping = false; Velocity += _preJumpForce; _targetVelocityIsDecaying = false; TriggerMovementUpdate(); } if (_jumping && Util.EnvironmentTickCountSubtract(_preJumpTime) > _scene.PreJumpTime + 2000) { _jumping = false; _targetVelocity = Vector3.Zero; TriggerMovementUpdate(); } else if (_jumping && Util.EnvironmentTickCountSubtract(_preJumpTime) > _scene.PreJumpTime + 750) { _targetVelocityIsDecaying = false; TriggerMovementUpdate(); } else if (_jumping && Util.EnvironmentTickCountSubtract(_preJumpTime) > _scene.PreJumpTime + 500) { _targetVelocityIsDecaying = false; Velocity -= _preJumpForce / 100; //Cut down on going up TriggerMovementUpdate(); } #endregion #region Decaying velocity if (_targetVelocityIsDecaying) { _targetVelocity *= _scene.DelayingVelocityMultiplier; if (_targetVelocity.ApproxEquals(Vector3.Zero, 0.1f) || _velocity == Vector3.Zero) { _targetVelocity = Vector3.Zero; } } if (_targetVelocity != Vector3.Zero) { Velocity = new Vector3( _targetVelocity.X == 0 ? Velocity.X : (_targetVelocity.X * 0.25f) + (Velocity.X * 0.75f), _targetVelocity.Y == 0 ? Velocity.Y : (_targetVelocity.Y * 0.25f) + (Velocity.Y * 0.75f), _targetVelocity.Z == 0 ? Velocity.Z : (_targetVelocity.Z * 0.25f) + (Velocity.Z * 0.75f)); } else if (Velocity.X != 0 || Velocity.Y != 0 || Velocity.Z > 0) { Velocity *= _scene.DelayingVelocityMultiplier; } if (Velocity.ApproxEquals(Vector3.Zero, 0.3f)) { Velocity = Vector3.Zero; } #endregion }
// The physics engine says that properties have updated. Update same and inform // the world that things have changed. // TODO: do we really need to check for changed? Maybe just copy values and call RequestPhysicsterseUpdate() public void UpdateProperties(EntityProperties entprop) { UpdatedProperties changed = 0; if (SHOULD_DAMP_UPDATES && !IsStatic) //Only physical prims get updated tyvm { // assign to the local variables so the normal set action does not happen // if (_position != entprop.Position) if (!_position.ApproxEquals(entprop.Position, POSITION_TOLERANCE)) { _position = entprop.Position; // MainConsole.Instance.DebugFormat("{0}: UpdateProperties: id={1}, pos = {2}", LogHeader, LocalID, _position); //changed |= UpdatedProperties.Position; } // if (_orientation != entprop.Rotation) if (!_orientation.ApproxEquals(entprop.Rotation, ROTATION_TOLERANCE)) { _orientation = entprop.Rotation; // MainConsole.Instance.DebugFormat("{0}: UpdateProperties: id={1}, rot = {2}", LogHeader, LocalID, _orientation); //changed |= UpdatedProperties.Rotation; } // if (_velocity != entprop.Velocity) if (!_velocity.ApproxEquals(entprop.Velocity, VELOCITY_TOLERANCE)) { if (!_lastVelocity.ApproxEquals(entprop.Velocity, 0.1f)) { _lastVelocity = entprop.Velocity; changed |= UpdatedProperties.Velocity; } _velocity = entprop.Velocity; // MainConsole.Instance.DebugFormat("{0}: UpdateProperties: velocity = {1}", LogHeader, _velocity); } // if (_acceleration != entprop.Acceleration) if (!_acceleration.ApproxEquals(entprop.Acceleration, ACCELERATION_TOLERANCE)) { _acceleration = entprop.Acceleration; // MainConsole.Instance.DebugFormat("{0}: UpdateProperties: acceleration = {1}", LogHeader, _acceleration); //changed |= UpdatedProperties.Acceleration; } // if (_rotationalVelocity != entprop.RotationalVelocity) if (!_rotationalVelocity.ApproxEquals(entprop.RotationalVelocity, ROTATIONAL_VELOCITY_TOLERANCE)) { if (!_lastRotationalVelocity.ApproxEquals(entprop.RotationalVelocity, 0.1f)) { _lastRotationalVelocity = entprop.RotationalVelocity; changed |= UpdatedProperties.RotationalVel; } _rotationalVelocity = entprop.RotationalVelocity; // MainConsole.Instance.DebugFormat("{0}: UpdateProperties: rotationalVelocity = {1}", LogHeader, _rotationalVelocity); } if (changed != 0) { // MainConsole.Instance.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation); // Only update the position of single objects and linkset roots if (this._parentPrim == null && _limitedUpdatesCount > 7) { _limitedUpdatesCount = 0; // MainConsole.Instance.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation); base.RequestPhysicsterseUpdate(); } else _limitedUpdatesCount++; } } /*else { // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. if (this._parentPrim == null) { // Assign 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; // MainConsole.Instance.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation); base.RequestPhysicsterseUpdate(); } }*/ }
// The physics engine says that properties have updated. Update same and inform // the world that things have changed. public override void UpdateProperties(EntityProperties entprop) { // Don't change position if standing on a stationary object. if (!IsStationary) _position = entprop.Position; _orientation = entprop.Rotation; if (entprop.Velocity != OMV.Vector3.Zero && entprop.Velocity.ApproxEquals(OMV.Vector3.Zero, 0.01f) && Velocity != OMV.Vector3.Zero) { entprop.Velocity = OMV.Vector3.Zero; entprop.Acceleration = OMV.Vector3.Zero; entprop.RotationalVelocity = OMV.Vector3.Zero; Velocity = OMV.Vector3.Zero; TriggerSignificantMovement(); TriggerMovementUpdate(); } if (!entprop.Velocity.ApproxEquals(RawVelocity, 0.4f)) { RawVelocity = entprop.Velocity; TriggerSignificantMovement(); TriggerMovementUpdate(); } _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. if (PositionSanityCheck(true)) { DetailLog("{0},BSCharacter.UpdateProperties,updatePosForSanity,pos={1}", LocalID, _position); entprop.Position = _position; } // remember the current and last set values LastEntityProperties = CurrentEntityProperties; CurrentEntityProperties = entprop; // Tell the linkset about value changes // Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this); // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. // base.RequestPhysicsterseUpdate(); DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, _position, _orientation, RawVelocity, _acceleration, _rotationalVelocity); }
// The physics engine says that properties have updated. Update same and inform // the world that things have changed. public override void UpdateProperties(EntityProperties entprop) { // Don't change position if standing on a stationary object. if (!IsStationary) _position = entprop.Position; _orientation = entprop.Rotation; // Smooth velocity. OpenSimulator is VERY sensitive to changes in velocity of the avatar // and will send agent updates to the clients if velocity changes by more than // 0.001m/s. Bullet introduces a lot of jitter in the velocity which causes many // extra updates. if (!entprop.Velocity.ApproxEquals(RawVelocity, 0.1f)) RawVelocity = entprop.Velocity; _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. if (PositionSanityCheck(true)) { DetailLog("{0},BSCharacter.UpdateProperties,updatePosForSanity,pos={1}", LocalID, _position); entprop.Position = _position; } // remember the current and last set values LastEntityProperties = CurrentEntityProperties; CurrentEntityProperties = entprop; // Tell the linkset about value changes // Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this); // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. // base.RequestPhysicsterseUpdate(); DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, _position, _orientation, RawVelocity, _acceleration, _rotationalVelocity); }
// Simulate one timestep public override float Simulate(float timeStep) { // prevent simulation until we've been initialized if (!m_initialized) { return(5.0f); } LastTimeStep = timeStep; int updatedEntityCount = 0; int collidersCount = 0; int beforeTime = 0; int simTime = 0; // update the prim states while we know the physics engine is not busy int numTaints = _taintOperations.Count; InTaintTime = true; // Only used for debugging so locking is not necessary. ProcessTaints(); // Some of the physical objects requre individual, pre-step calls TriggerPreStepEvent(timeStep); // the prestep actions might have added taints numTaints += _taintOperations.Count; ProcessTaints(); InTaintTime = false; // Only used for debugging so locking is not necessary. // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world. // Only enable this in a limited test world with few objects. if (m_physicsPhysicalDumpEnabled) { PE.DumpAllInfo(World); } // step the physical world one interval m_simulationStep++; int numSubSteps = 0; try { if (PhysicsLogging.Enabled) { beforeTime = Util.EnvironmentTickCount(); } numSubSteps = PE.PhysicsStep(World, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out collidersCount); if (PhysicsLogging.Enabled) { simTime = Util.EnvironmentTickCountSubtract(beforeTime); DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}, objWColl={7}", DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount, ObjectsWithCollisions.Count); } } catch (Exception e) { m_log.WarnFormat("{0},PhysicsStep Exception: nTaints={1}, substeps={2}, updates={3}, colliders={4}, e={5}", LogHeader, numTaints, numSubSteps, updatedEntityCount, collidersCount, e); DetailLog("{0},PhysicsStepException,call, nTaints={1}, substeps={2}, updates={3}, colliders={4}", DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount); updatedEntityCount = 0; collidersCount = 0; } if ((m_simulationStep % PhysicsMetricDumpFrames) == 0) { PE.DumpPhysicsStatistics(World); } // Get a value for 'now' so all the collision and update routines don't have to get their own. SimulationNowTime = Util.EnvironmentTickCount(); // If there were collisions, process them by sending the event to the prim. // Collisions must be processed before updates. if (collidersCount > 0) { for (int ii = 0; ii < collidersCount; ii++) { uint cA = m_collisionArray[ii].aID; uint cB = m_collisionArray[ii].bID; Vector3 point = m_collisionArray[ii].point; Vector3 normal = m_collisionArray[ii].normal; SendCollision(cA, cB, point, normal, 0.01f); SendCollision(cB, cA, point, -normal, 0.01f); } } // The above SendCollision's batch up the collisions on the objects. // Now push the collisions into the simulator. if (ObjectsWithCollisions.Count > 0) { foreach (BSPhysObject bsp in ObjectsWithCollisions) { if (!bsp.SendCollisions()) { // If the object is done colliding, see that it's removed from the colliding list ObjectsWithNoMoreCollisions.Add(bsp); } } } // This is a kludge to get avatar movement updates. // The simulator expects collisions for avatars even if there are have been no collisions. // The event updates avatar animations and stuff. // If you fix avatar animation updates, remove this overhead and let normal collision processing happen. foreach (BSPhysObject bsp in m_avatars) { if (!ObjectsWithCollisions.Contains(bsp)) // don't call avatars twice { bsp.SendCollisions(); } } // Objects that are done colliding are removed from the ObjectsWithCollisions list. // Not done above because it is inside an iteration of ObjectWithCollisions. // This complex collision processing is required to create an empty collision // event call after all real collisions have happened on an object. This enables // the simulator to generate the 'collision end' event. if (ObjectsWithNoMoreCollisions.Count > 0) { foreach (BSPhysObject po in ObjectsWithNoMoreCollisions) { ObjectsWithCollisions.Remove(po); } ObjectsWithNoMoreCollisions.Clear(); } // Done with collisions. // If any of the objects had updated properties, tell the object it has been changed by the physics engine if (updatedEntityCount > 0) { for (int ii = 0; ii < updatedEntityCount; ii++) { EntityProperties entprop = m_updateArray[ii]; BSPhysObject pobj; if (PhysObjects.TryGetValue(entprop.ID, out pobj)) { pobj.UpdateProperties(entprop); } } } TriggerPostStepEvent(timeStep); // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world. // Only enable this in a limited test world with few objects. if (m_physicsPhysicalDumpEnabled) { PE.DumpAllInfo(World); } // The physics engine returns the number of milliseconds it simulated this call. // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. // Multiply by a fixed nominal frame rate to give a rate similar to the simulator (usually 55). return((float)numSubSteps * m_fixedTimeStep * 1000f * NominalFrameRate); }
private void PreUpdateProperty(ref EntityProperties entprop) { // A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet // TODO: handle physics introduced by Bullet with computed vehicle physics. if (IsActive) { entprop.RotationalVelocity = Vector3.Zero; } }
public void UpdateProperties(EntityProperties entprop) { UpdatedProperties changed = 0; if (SHOULD_DAMP_UPDATES) { // assign to the local variables so the normal set action does not happen // if (_position != entprop.Position) if (!_position.ApproxEquals(entprop.Position, POSITION_TOLERANCE)) { _position = entprop.Position; // m_log.DebugFormat("{0}: UpdateProperties: id={1}, pos = {2}", LogHeader, LocalID, _position); changed |= UpdatedProperties.Position; } // if (_orientation != entprop.Rotation) if (!_orientation.ApproxEquals(entprop.Rotation, ROTATION_TOLERANCE)) { _orientation = entprop.Rotation; // m_log.DebugFormat("{0}: UpdateProperties: id={1}, rot = {2}", LogHeader, LocalID, _orientation); changed |= UpdatedProperties.Rotation; } // if (_velocity != entprop.Velocity) if (!_velocity.ApproxEquals(entprop.Velocity, VELOCITY_TOLERANCE)) { _velocity = entprop.Velocity; // m_log.DebugFormat("{0}: UpdateProperties: velocity = {1}", LogHeader, _velocity); changed |= UpdatedProperties.Velocity; } // if (_acceleration != entprop.Acceleration) if (!_acceleration.ApproxEquals(entprop.Acceleration, ACCELERATION_TOLERANCE)) { _acceleration = entprop.Acceleration; // m_log.DebugFormat("{0}: UpdateProperties: acceleration = {1}", LogHeader, _acceleration); changed |= UpdatedProperties.Acceleration; } // if (_rotationalVelocity != entprop.RotationalVelocity) if (!_rotationalVelocity.ApproxEquals(entprop.RotationalVelocity, ROTATIONAL_VELOCITY_TOLERANCE)) { _rotationalVelocity = entprop.RotationalVelocity; // m_log.DebugFormat("{0}: UpdateProperties: rotationalVelocity = {1}", LogHeader, _rotationalVelocity); changed |= UpdatedProperties.RotationalVel; } if (changed != 0) { // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation); // Only update the position of single objects and linkset roots if (this._parentPrim == null) { // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation); base.RequestPhysicsterseUpdate(); } } } else { // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. // Only updates only for individual prims and for the root object of a linkset. if (this._parentPrim == null) { // Assign 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; // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation); base.RequestPhysicsterseUpdate(); } } }
public override void UpdateProperties(EntityProperties entprop) { // Updates only for individual prims and for the root object of a linkset. if (Linkset.IsRoot(this)) { // A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet // TODO: handle physics introduced by Bullet with computed vehicle physics. if (_vehicle.IsActive) { entprop.RotationalVelocity = OMV.Vector3.Zero; } // 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 (IsPhysical && PositionSanityCheck(true)) { entprop.Position = _position; entprop.Velocity = _velocity; } OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; // DEBUG DEBUG DEBUG DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}", LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity); // remember the current and last set values LastEntityProperties = CurrentEntityProperties; CurrentEntityProperties = entprop; base.RequestPhysicsterseUpdate(); } /* else { // For debugging, report the movement of children DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, entprop.Acceleration, entprop.RotationalVelocity); } */ // The linkset implimentation might want to know about this. Linkset.UpdateProperties(this, true); }