// Initialization and simulation
 public abstract BulletWorld Initialize(Vector3 maxPosition, ConfigurationParameters parms,
                                             int maxCollisions, ref CollisionDesc[] collisionArray,
                                             int maxUpdates, ref EntityProperties[] updateArray
                                             );
 protected void TriggerPreUpdatePropertyAction(ref EntityProperties entprop)
 {
     PreUpdatePropertyAction actions = OnPreUpdateProperty;
     if (actions != null)
     actions(ref 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 = "";

            // 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));
        }
 // 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
            _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);
            }
             */
        }
 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 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 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);
        }