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. 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; entprop.Velocity = OMV.Vector3.Zero; m_physicsScene.PE.SetTranslation(m_controllingPrim.PhysBody, entprop.Position, entprop.Rotation); } }
public override void UpdateProperties(EntityProperties entprop) { // TODO!!! Linkset.ShouldReportPropertyUpdates 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); }
public override void UpdateProperties(EntityProperties entprop) { // Undo any center-of-mass displacement that might have been done. if (PositionDisplacement != Vector3.Zero || OrientationDisplacement != Quaternion.Identity) { // Correct for any rotation around the center-of-mass // TODO!!! //entprop.Position = entprop.Position + (PositionDisplacement * entprop.Rotation); // entprop.Rotation = something; // 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. Vector3 displacement = PositionDisplacement * entprop.Rotation; 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); }
// Update the physical location and motion of the object. Called with data from Bullet. public abstract void UpdateProperties(EntityProperties 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) { bool needSendUpdate = false; // 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; m_ZeroUpdateSent = 3; needSendUpdate = true; } if (!entprop.Velocity.ApproxEquals(RawVelocity, 0.4f)) { RawVelocity = entprop.Velocity; needSendUpdate = true; } // 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; } // animation checks const float POSITION_TOLERANCE = 5.0f; float VELOCITY_TOLERANCE = 0.025f * 0.025f; if (PhysicsScene.TimeDilation < 0.5) { float percent = (1f - PhysicsScene.TimeDilation) * 100; VELOCITY_TOLERANCE *= percent*2; } bool VelIsZero = false; OMV.Vector3 _velocity = Velocity; int vcntr = 0; if (Math.Abs(_velocity.X) < 0.01) { vcntr++; _velocity.X = 0; } if (Math.Abs(_velocity.Y) < 0.01) { vcntr++; _velocity.Y = 0; } if (Math.Abs(_velocity.Z) < 0.01) { vcntr++; _velocity.Z = 0; } if (vcntr == 3) { Velocity = _velocity; VelIsZero = true; } float vlength = (Velocity - m_lastVelocity).LengthSquared(); float plength = (_position - m_lastPosition).LengthSquared(); if ( vlength > VELOCITY_TOLERANCE || plength > POSITION_TOLERANCE ) { needSendUpdate = true; m_ZeroUpdateSent = 3; } else if (VelIsZero) { if (m_ZeroUpdateSent > 0) { needSendUpdate = true; m_ZeroUpdateSent--; } } if (needSendUpdate) { m_lastPosition = _position; m_lastVelocity = Velocity; TriggerSignificantMovement(); TriggerMovementUpdate(); // remember the current and last set values _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; 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 void Simulate(float timeStep) { // prevent simulation until we've been initialized if (!m_initialized) { return; } LastTimeStep = timeStep; int updatedEntityCount = 0; int collidersCount = 0; int beforeTime = 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. beforeTime = Util.EnvironmentTickCount(); 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(); StatPhysicsTaintTime = Util.EnvironmentTickCountSubtract(beforeTime); 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 { beforeTime = Util.EnvironmentTickCount(); numSubSteps = PE.PhysicsStep(World, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out collidersCount); //if (PhysicsLogging.Enabled) //{ StatContactLoopTime = 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, StatContactLoopTime, numSubSteps, updatedEntityCount, collidersCount, ObjectsWithCollisions.Count); //} } catch (Exception e) { MainConsole.Instance.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 (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(); beforeTime = 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; float penetration = m_collisionArray[ii].penetration; SendCollision(cA, cB, point, normal, penetration); SendCollision(cB, cA, point, -normal, penetration); } } // 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); } } } StatPhysicsMoveTime = Util.EnvironmentTickCountSubtract(beforeTime); 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); } }
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; } }
// Initialization and simulation public abstract BulletWorld Initialize(Vector3 maxPosition, ConfigurationParameters parms, int maxCollisions, ref CollisionDesc[] collisionArray, int maxUpdates, ref EntityProperties[] updateArray );
// The physics engine says that properties have updated. Update same and inform // the world that things have changed. public override void UpdateProperties(EntityProperties entprop) { bool needSendUpdate = false; // 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; m_ZeroUpdateSent = 3; needSendUpdate = true; } if (!entprop.Velocity.ApproxEquals(RawVelocity, 0.4f)) { RawVelocity = entprop.Velocity; needSendUpdate = true; } // 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; } // animation checks const float POSITION_TOLERANCE = 5.0f; float VELOCITY_TOLERANCE = 0.025f * 0.025f; if (PhysicsScene.TimeDilation < 0.5) { float percent = (1f - PhysicsScene.TimeDilation) * 100; VELOCITY_TOLERANCE *= percent * 2; } bool VelIsZero = false; OMV.Vector3 _velocity = Velocity; int vcntr = 0; if (Math.Abs(_velocity.X) < 0.01) { vcntr++; _velocity.X = 0; } if (Math.Abs(_velocity.Y) < 0.01) { vcntr++; _velocity.Y = 0; } if (Math.Abs(_velocity.Z) < 0.01) { vcntr++; _velocity.Z = 0; } if (vcntr == 3) { Velocity = _velocity; VelIsZero = true; } float vlength = (Velocity - m_lastVelocity).LengthSquared(); float plength = (_position - m_lastPosition).LengthSquared(); if (vlength > VELOCITY_TOLERANCE || plength > POSITION_TOLERANCE) { needSendUpdate = true; m_ZeroUpdateSent = 3; } else if (VelIsZero) { if (m_ZeroUpdateSent > 0) { needSendUpdate = true; m_ZeroUpdateSent--; } } if (needSendUpdate) { m_lastPosition = _position; m_lastVelocity = Velocity; TriggerSignificantMovement(); TriggerMovementUpdate(); // remember the current and last set values _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; 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); }
protected void TriggerPreUpdatePropertyAction(ref EntityProperties entprop) { PreUpdatePropertyAction actions = OnPreUpdateProperty; if (actions != null) actions(ref 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 _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; } // 20131224 not used 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) 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); } */ }
public override void UpdateProperties(EntityProperties entprop) { // TODO!!! Linkset.ShouldReportPropertyUpdates 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); }