Пример #1
0
        protected void TriggerPreUpdatePropertyAction(ref EntityProperties entprop)
        {
            PreUpdatePropertyAction actions = OnPreUpdateProperty;

            if (actions != null)
            {
                actions(ref entprop);
            }
        }
Пример #2
0
 // 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);
     }
 }
Пример #3
0
        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);
        }
Пример #5
0
 // 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)
        {
            // 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);
        }
        // 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);
            }

        }
Пример #8
0
 // Initialization and simulation
 public abstract BulletWorld Initialize(Vector3 maxPosition, ConfigurationParameters parms,
     int maxCollisions, ref CollisionDesc[] collisionArray,
     int maxUpdates, ref EntityProperties[] updateArray
     );
Пример #9
0
        // 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);
        }
Пример #10
0
        // 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);
            }
            */
        }
Пример #11
0
 // Update the physical location and motion of the object. Called with data from Bullet.
 public abstract void UpdateProperties(EntityProperties entprop);
        // 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 (MainConsole.Instance.IsDebugEnabled)
            {
                MainConsole.Instance.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 = "2.82";

            // 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));
        }
Пример #13
0
        // 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);
        }
Пример #14
0
        // 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);
            }
        }
Пример #15
0
 protected void TriggerPreUpdatePropertyAction(ref EntityProperties entprop)
 {
     PreUpdatePropertyAction actions = OnPreUpdateProperty;
     if (actions != null)
         actions(ref entprop);
 }
Пример #16
0
 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 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);
 }