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.
        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);
        }
Example #3
0
        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);
        }
        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);
        }
 // Update the physical location and motion of the object. Called with data from Bullet.
 public abstract void UpdateProperties(EntityProperties entprop);
 // Initialization and simulation
 public abstract BulletWorld Initialize(Vector3 maxPosition, ConfigurationParameters parms,
     int maxCollisions, ref CollisionDesc[] collisionArray,
     int maxUpdates, ref EntityProperties[] updateArray
     );
        // 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 = "";

            // 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));
        }
 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);
 }
Example #9
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);
            }
        }
 protected void TriggerPreUpdatePropertyAction(ref EntityProperties entprop)
 {
     PreUpdatePropertyAction actions = OnPreUpdateProperty;
     if (actions != null)
         actions(ref 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)
        {
            // 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;

            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 = RawPosition;
                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)
                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);
            }
             */
        }
        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)
        {
            // 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);
        }