Example #1
0
    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);
    }
Example #2
0
 // Update the physical location and motion of the object. Called with data from Bullet.
 public abstract void UpdateProperties(EntityProperties entprop);
Example #3
0
    // 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;
        //Object updatedEntitiesPtr;
        int collidersCount = 0;
        //Object collidersPtr;

        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
        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.
        // BulletSimAPI.DumpAllInfo2(World.ptr);    // DEBUG DEBUG DEBUG

        // step the physical world one interval
        m_simulationStep++;
        int numSubSteps = 0;

        try
        {
            if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount();

            numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep,
                        out updatedEntityCount, out m_updateArray, out collidersCount, out m_collisionArray);

            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;
        }

        // 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.
        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 = new Vector3(m_collisionArray[ii].point.X, m_collisionArray[ii].point.Y,
                                            m_collisionArray[ii].point.Z);
                Vector3 normal = new Vector3(m_collisionArray[ii].normal.X, m_collisionArray[ii].normal.Y,
                                            m_collisionArray[ii].normal.Z); 
                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 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++)
            {

                BulletXNA.EntityProperties entprop = m_updateArray[ii];
                BSPhysObject pobj;
                if (PhysObjects.TryGetValue(entprop.ID, out pobj))
                {
                    EntityProperties prop = new EntityProperties()
                                                {
                                                    Acceleration = new Vector3(entprop.Acceleration.X, entprop.Acceleration.Y, entprop.Acceleration.Z),
                                                    ID = entprop.ID,
                                                    Position = new Vector3(entprop.Position.X,entprop.Position.Y,entprop.Position.Z),
                                                    Rotation = new Quaternion(entprop.Rotation.X,entprop.Rotation.Y,entprop.Rotation.Z,entprop.Rotation.W),
                                                    RotationalVelocity = new Vector3(entprop.AngularVelocity.X,entprop.AngularVelocity.Y,entprop.AngularVelocity.Z),
                                                    Velocity = new Vector3(entprop.Velocity.X,entprop.Velocity.Y,entprop.Velocity.Z)
                                                };
                    //m_log.Debug(pobj.Name + ":" + prop.ToString() + "\n");
                    pobj.UpdateProperties(prop);
                }
            }
        }

        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.
        // BulletSimAPI.DumpAllInfo2(World.ptr);    // DEBUG DEBUG DEBUG

        // 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 55 to give a nominal frame rate of 55.
        return (float)numSubSteps * m_fixedTimeStep * 1000f * 55f;
    }
Example #4
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)
    {
        _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);

        if (_velocityMotor.Enabled)
        {
            // TODO: Decide if the step parameters should be changed depending on the avatar's
            //     state (flying, colliding, ...).

            OMV.Vector3 stepVelocity = _velocityMotor.Step(PhysicsScene.LastTimeStep);

            // If falling, we keep the world's downward vector no matter what the other axis specify.
            if (!Flying && !IsColliding)
            {
                stepVelocity.Z = entprop.Velocity.Z;
                DetailLog("{0},BSCharacter.UpdateProperties,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity);
            }

            // If the user has said stop and we've stopped applying velocity correction,
            //     the motor can be turned off. Set the velocity to zero so the zero motion is sent to the viewer.
            if (_velocityMotor.TargetValue.ApproxEquals(OMV.Vector3.Zero, 0.01f) && _velocityMotor.ErrorIsZero)
            {
                ZeroMotion(true);
                stepVelocity = OMV.Vector3.Zero;
                _velocityMotor.Enabled = false;
                DetailLog("{0},BSCharacter.UpdateProperties,taint,disableVelocityMotor,m={1}", LocalID, _velocityMotor);
            }

            _velocity = stepVelocity;
            entprop.Velocity = _velocity;
            BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity);
        }

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