コード例 #1
0
        // Call the physics engine to do one 'timeStep' and collect collisions and updates
        //    into ObjectsWithCollisions and ObjectsWithUpdates data structures.
        private void DoPhysicsStep(float timeStep)
        {
            // prevent simulation until we've been initialized
            if (!m_initialized)
            {
                return;
            }

            LastTimeStep = timeStep;

            int updatedEntityCount = 0;
            int collidersCount     = 0;

            int beforeTime = Util.EnvironmentTickCount();
            int simTime    = 0;

            int numTaints = _taintOperations.Count;

            InTaintTime = true; // Only used for debugging so locking is not necessary.

            // update the prim states while we know the physics engine is not busy
            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();

            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
            {
                numSubSteps = PE.PhysicsStep(World, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out collidersCount);
            }
            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;
            }

            // Make the physics engine dump useful statistics periodically
            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();

            // Send collision information to the colliding objects. The objects decide if the collision
            //     is 'real' (like linksets don't collide with themselves) and the individual objects
            //     know if the simulator has subscribed to collisions.
            lock (CollisionLock)
            {
                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);
                    }
                }
            }

            // If any of the objects had updated properties, tell the managed objects about the update
            //     and remember that there was a change so it will be passed to the simulator.
            lock (UpdateLock)
            {
                if (updatedEntityCount > 0)
                {
                    for (int ii = 0; ii < updatedEntityCount; ii++)
                    {
                        EntityProperties entprop = m_updateArray[ii];
                        BSPhysObject     pobj;
                        if (PhysObjects.TryGetValue(entprop.ID, out pobj))
                        {
                            if (pobj.IsInitialized)
                            {
                                pobj.UpdateProperties(entprop);
                            }
                        }
                    }
                }
            }

            // Some actors want to know when the simulation step is complete.
            TriggerPostStepEvent(timeStep);

            simTime = Util.EnvironmentTickCountSubtract(beforeTime);
            if (PhysicsLogging.Enabled)
            {
                DetailLog("{0},DoPhysicsStep,complete,frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}, objWColl={7}",
                          DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps,
                          updatedEntityCount, collidersCount, ObjectsWithCollisions.Count);
            }

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

            // 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 a fixed nominal frame rate to give a rate similar to the simulator (usually 55).
            m_simulatedTime += (float)numSubSteps * m_fixedTimeStep * 1000f * NominalFrameRate;
        }
コード例 #2
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;
            int collidersCount     = 0;

            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
            numTaints += _taintOperations.Count;
            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.
            if (m_physicsPhysicalDumpEnabled)
            {
                PE.DumpAllInfo(World);
            }

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

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

                numSubSteps = PE.PhysicsStep(World, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out collidersCount);

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

            if ((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();

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

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

            // 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 a fixed nominal frame rate to give a rate similar to the simulator (usually 55).
            return((float)numSubSteps * m_fixedTimeStep * 1000f * NominalFrameRate);
        }