Beispiel #1
0
        // Keyboard callback
        static void command(int cmd)
        {
            IntPtr geom;

            d.Mass    mass;
            d.Vector3 sides = new d.Vector3(d.RandReal() * 0.5f + 0.1f, d.RandReal() * 0.5f + 0.1f, d.RandReal() * 0.5f + 0.1f);

            Char ch = Char.ToLower((Char)cmd);

            switch ((Char)ch)
            {
            case 'b':
                d.MassSetBox(out mass, DENSITY, sides.X, sides.Y, sides.Z);
                geom = d.CreateBox(space, sides.X, sides.Y, sides.Z);
                addObject(geom, mass);
                break;

            case 'c':
                sides.X *= 0.5f;
                d.MassSetCapsule(out mass, DENSITY, 3, sides.X, sides.Y);
                geom = d.CreateCapsule(space, sides.X, sides.Y);
                addObject(geom, mass);
                break;

            case 'v':
                d.MassSetBox(out mass, DENSITY, 0.25f, 0.25f, 0.25f);
                geom = d.CreateConvex(space, planes, planes.Length / 4, points, points.Length / 3, polygons);
                addObject(geom, mass);
                break;
            }
        }
Beispiel #2
0
 public void UpdatePosition()
 {
     d.Vector3 vec = d.BodyGetPosition(BoundingCapsule);
     this._position.X = vec.X;
     this._position.Y = vec.Y;
     this._position.Z = vec.Z;
 }
    // Keyboard callback
        public void command(int cmd)
        {
            IntPtr geom;
            d.Mass mass;
            d.Vector3 sides = new d.Vector3(d.RandReal() * 0.5f + 0.1f, d.RandReal() * 0.5f + 0.1f, d.RandReal() * 0.5f + 0.1f);

            

            Char ch = Char.ToLower((Char)cmd);
            switch ((Char)ch)
            {
                case 'w':
                    try
                    {
                        Vector3 rotate = (new Vector3(1, 0, 0) * Quaternion.CreateFromEulers(hpr.Z * Utils.DEG_TO_RAD, hpr.Y * Utils.DEG_TO_RAD, hpr.X * Utils.DEG_TO_RAD));

                        xyz.X += rotate.X; xyz.Y += rotate.Y; xyz.Z += rotate.Z;
                        ds.SetViewpoint(ref xyz, ref hpr);
                    }
                    catch (ArgumentException)
                    { hpr.X = 0; }
                    break;

                case 'a':
                    hpr.X++;
                    ds.SetViewpoint(ref xyz, ref hpr);
                    break;

                case 's':
                    try
                    {
                        Vector3 rotate2 = (new Vector3(-1, 0, 0) * Quaternion.CreateFromEulers(hpr.Z * Utils.DEG_TO_RAD, hpr.Y * Utils.DEG_TO_RAD, hpr.X * Utils.DEG_TO_RAD));

                        xyz.X += rotate2.X; xyz.Y += rotate2.Y; xyz.Z += rotate2.Z;
                        ds.SetViewpoint(ref xyz, ref hpr);
                    }
                    catch (ArgumentException)
                    { hpr.X = 0; }
                    break;
                case 'd':
                    hpr.X--;
                    ds.SetViewpoint(ref xyz, ref hpr);
                    break;
                case 'r':
                    xyz.Z++;
                    ds.SetViewpoint(ref xyz, ref hpr);
                    break;
                case 'f':
                    xyz.Z--;
                    ds.SetViewpoint(ref xyz, ref hpr);
                    break;
                case 'e':
                    xyz.Y++;
                    ds.SetViewpoint(ref xyz, ref hpr);
                    break;
                case 'q':
                    xyz.Y--;
                    ds.SetViewpoint(ref xyz, ref hpr);
                    break;
            }
        }
Beispiel #4
0
        internal void Step()
        {
            IntPtr Body = rootPrim.Body;

            d.Mass dmass;
            d.BodyGetMass(Body, out dmass);

            d.Quaternion rot     = d.BodyGetQuaternion(Body);
            Quaternion   objrotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object
            Quaternion   rotq    = objrotq;                                    // rotq = rotation of object

            rotq *= m_referenceFrame;                                          // rotq is now rotation in vehicle reference frame
            Quaternion irotq = Quaternion.Inverse(rotq);

            d.Vector3 dvtmp;
            Vector3   tmpV;
            Vector3   curVel;                // velocity in world
            Vector3   curAngVel;             // angular velocity in world
            Vector3   force  = Vector3.Zero; // actually linear aceleration until mult by mass in world frame
            Vector3   torque = Vector3.Zero; // actually angular aceleration until mult by Inertia in vehicle frame

            d.Vector3 dtorque = new d.Vector3();

            dvtmp    = d.BodyGetLinearVel(Body);
            curVel.X = dvtmp.X;
            curVel.Y = dvtmp.Y;
            curVel.Z = dvtmp.Z;
            Vector3 curLocalVel = curVel * irotq; // current velocity in  local

            dvtmp       = d.BodyGetAngularVel(Body);
            curAngVel.X = dvtmp.X;
            curAngVel.Y = dvtmp.Y;
            curAngVel.Z = dvtmp.Z;
            Vector3 curLocalAngVel = curAngVel * irotq; // current angular velocity in  local

            float ldampZ = 0;

            // linear motor
            if (m_lmEfect > 0.01 && m_linearMotorTimescale < 1000)
            {
                tmpV  = m_linearMotorDirection - curLocalVel; // velocity error
                tmpV *= m_lmEfect / m_linearMotorTimescale;   // error to correct in this timestep
                tmpV *= rotq;                                 // to world

                if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != 0)
                {
                    tmpV.Z = 0;
                }

                if (m_linearMotorOffset.X != 0 || m_linearMotorOffset.Y != 0 || m_linearMotorOffset.Z != 0)
                {
                    // have offset, do it now
                    tmpV *= dmass.mass;
                    d.BodyAddForceAtRelPos(Body, tmpV.X, tmpV.Y, tmpV.Z, m_linearMotorOffset.X, m_linearMotorOffset.Y, m_linearMotorOffset.Z);
                }
                else
                {
                    force.X += tmpV.X;
                    force.Y += tmpV.Y;
                    force.Z += tmpV.Z;
                }

                m_lmEfect *= m_lmDecay;
//                m_ffactor = 0.01f + 1e-4f * curVel.LengthSquared();
                m_ffactor = 0.0f;
            }
            else
            {
                m_lmEfect = 0;
                m_ffactor = 1f;
            }

            // hover
            if (m_VhoverTimescale < 300 && rootPrim.prim_geom != IntPtr.Zero)
            {
                //                d.Vector3 pos = d.BodyGetPosition(Body);
                d.Vector3 pos = d.GeomGetPosition(rootPrim.prim_geom);
                pos.Z -= 0.21f; // minor offset that seems to be always there in sl

                float t = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y);
                float perr;

                // default to global but don't go underground
                perr = m_VhoverHeight - pos.Z;

                if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) == 0)
                {
                    if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0)
                    {
                        perr += _pParentScene.GetWaterLevel();
                    }
                    else if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
                    {
                        perr += t;
                    }
                    else
                    {
                        float w = _pParentScene.GetWaterLevel();
                        if (t > w)
                        {
                            perr += t;
                        }
                        else
                        {
                            perr += w;
                        }
                    }
                }
                else if (t > m_VhoverHeight)
                {
                    perr = t - pos.Z;
                }
                ;

                if ((m_flags & VehicleFlag.HOVER_UP_ONLY) == 0 || perr > -0.1)
                {
                    ldampZ = m_VhoverEfficiency * m_invtimestep;

                    perr *= (1.0f + ldampZ) / m_VhoverTimescale;

                    //                    force.Z += perr - curVel.Z * tmp;
                    force.Z += perr;
                    ldampZ  *= -curVel.Z;

                    force.Z += _pParentScene.gravityz * m_gravmod * (1f - m_VehicleBuoyancy);
                }
                else // no buoyancy
                {
                    force.Z += _pParentScene.gravityz;
                }
            }
            else
            {
                // default gravity and Buoyancy
                force.Z += _pParentScene.gravityz * m_gravmod * (1f - m_VehicleBuoyancy);
            }

            // linear deflection
            if (m_linearDeflectionEfficiency > 0)
            {
                float len = curVel.Length();
                if (len > 0.01) // if moving
                {
                    Vector3 atAxis;
                    atAxis  = Xrot(rotq); // where are we pointing to
                    atAxis *= len;        // make it same size as world velocity vector

                    tmpV    = -atAxis;    // oposite direction
                    atAxis -= curVel;     // error to one direction
                    len     = atAxis.LengthSquared();

                    tmpV -= curVel; // error to oposite
                    float lens = tmpV.LengthSquared();

                    if (len > 0.01 || lens > 0.01) // do nothing if close enougth
                    {
                        if (len < lens)
                        {
                            tmpV = atAxis;
                        }

                        tmpV    *= (m_linearDeflectionEfficiency / m_linearDeflectionTimescale); // error to correct in this timestep
                        force.X += tmpV.X;
                        force.Y += tmpV.Y;
                        if ((m_flags & VehicleFlag.NO_DEFLECTION_UP) == 0)
                        {
                            force.Z += tmpV.Z;
                        }
                    }
                }
            }

            // linear friction/damping
            if (curLocalVel.X != 0 || curLocalVel.Y != 0 || curLocalVel.Z != 0)
            {
                tmpV.X = -curLocalVel.X / m_linearFrictionTimescale.X;
                tmpV.Y = -curLocalVel.Y / m_linearFrictionTimescale.Y;
                tmpV.Z = -curLocalVel.Z / m_linearFrictionTimescale.Z;
                tmpV  *= rotq; // to world

                if (ldampZ != 0 && Math.Abs(ldampZ) > Math.Abs(tmpV.Z))
                {
                    tmpV.Z = ldampZ;
                }
                force.X += tmpV.X;
                force.Y += tmpV.Y;
                force.Z += tmpV.Z;
            }

            // vertical atractor
            if (m_verticalAttractionTimescale < 300)
            {
                float roll;
                float pitch;



                float ftmp = m_invtimestep / m_verticalAttractionTimescale / m_verticalAttractionTimescale;

                float ftmp2;
                ftmp2     = 0.5f * m_verticalAttractionEfficiency * m_invtimestep;
                m_amdampX = ftmp2;

                m_ampwr = 1.0f - 0.8f * m_verticalAttractionEfficiency;

                GetRollPitch(irotq, out roll, out pitch);

                if (roll > halfpi)
                {
                    roll = pi - roll;
                }
                else if (roll < -halfpi)
                {
                    roll = -pi - roll;
                }

                float effroll = pitch / halfpi;
                effroll *= effroll;
                effroll  = 1 - effroll;
                effroll *= roll;


                torque.X += effroll * ftmp;

                if ((m_flags & VehicleFlag.LIMIT_ROLL_ONLY) == 0)
                {
                    float effpitch = roll / halfpi;
                    effpitch *= effpitch;
                    effpitch  = 1 - effpitch;
                    effpitch *= pitch;

                    torque.Y += effpitch * ftmp;
                }

                if (m_bankingEfficiency != 0 && Math.Abs(effroll) > 0.01)
                {
                    float broll = effroll;

                    /*
                     *                  if (broll > halfpi)
                     *                      broll = pi - broll;
                     *                  else if (broll < -halfpi)
                     *                      broll = -pi - broll;
                     */
                    broll *= m_bankingEfficiency;
                    if (m_bankingMix != 0)
                    {
                        float vfact = Math.Abs(curLocalVel.X) / 10.0f;
                        if (vfact > 1.0f)
                        {
                            vfact = 1.0f;
                        }

                        if (curLocalVel.X >= 0)
                        {
                            broll *= (1 + (vfact - 1) * m_bankingMix);
                        }
                        else
                        {
                            broll *= -(1 + (vfact - 1) * m_bankingMix);
                        }
                    }
                    // make z rot be in world Z not local as seems to be in sl

                    broll = broll / m_bankingTimescale;


                    tmpV  = Zrot(irotq);
                    tmpV *= broll;

                    torque.X += tmpV.X;
                    torque.Y += tmpV.Y;
                    torque.Z += tmpV.Z;

                    m_amdampZ = Math.Abs(m_bankingEfficiency) / m_bankingTimescale;
                    m_amdampY = m_amdampZ;
                }
                else
                {
                    m_amdampZ = 1 / m_angularFrictionTimescale.Z;
                    m_amdampY = m_amdampX;
                }
            }
            else
            {
                m_ampwr   = 1.0f;
                m_amdampX = 1 / m_angularFrictionTimescale.X;
                m_amdampY = 1 / m_angularFrictionTimescale.Y;
                m_amdampZ = 1 / m_angularFrictionTimescale.Z;
            }

            // angular motor
            if (m_amEfect > 0.01 && m_angularMotorTimescale < 1000)
            {
                tmpV      = m_angularMotorDirection - curLocalAngVel; // velocity error
                tmpV     *= m_amEfect / m_angularMotorTimescale;      // error to correct in this timestep
                torque.X += tmpV.X * m_ampwr;
                torque.Y += tmpV.Y * m_ampwr;
                torque.Z += tmpV.Z;

                m_amEfect *= m_amDecay;
            }
            else
            {
                m_amEfect = 0;
            }

            // angular deflection
            if (m_angularDeflectionEfficiency > 0)
            {
                Vector3 dirv;

                if (curLocalVel.X > 0.01f)
                {
                    dirv = curLocalVel;
                }
                else if (curLocalVel.X < -0.01f)
                {
                    // use oposite
                    dirv = -curLocalVel;
                }
                else
                {
                    // make it fall into small positive x case
                    dirv.X = 0.01f;
                    dirv.Y = curLocalVel.Y;
                    dirv.Z = curLocalVel.Z;
                }

                float ftmp = m_angularDeflectionEfficiency / m_angularDeflectionTimescale;

                if (Math.Abs(dirv.Z) > 0.01)
                {
                    torque.Y += -(float)Math.Atan2(dirv.Z, dirv.X) * ftmp;
                }

                if (Math.Abs(dirv.Y) > 0.01)
                {
                    torque.Z += (float)Math.Atan2(dirv.Y, dirv.X) * ftmp;
                }
            }

            // angular friction
            if (curLocalAngVel.X != 0 || curLocalAngVel.Y != 0 || curLocalAngVel.Z != 0)
            {
                torque.X -= curLocalAngVel.X * m_amdampX;
                torque.Y -= curLocalAngVel.Y * m_amdampY;
                torque.Z -= curLocalAngVel.Z * m_amdampZ;
            }


            if (force.X != 0 || force.Y != 0 || force.Z != 0)
            {
                force *= dmass.mass;
                d.BodyAddForce(Body, force.X, force.Y, force.Z);
            }

            if (torque.X != 0 || torque.Y != 0 || torque.Z != 0)
            {
                torque   *= m_referenceFrame; // to object frame
                dtorque.X = torque.X;
                dtorque.Y = torque.Y;
                dtorque.Z = torque.Z;

                d.MultiplyM3V3(out dvtmp, ref dmass.I, ref dtorque);
                d.BodyAddRelTorque(Body, dvtmp.X, dvtmp.Y, dvtmp.Z); // add torque in object frame
            }
        }
Beispiel #5
0
        }// end Step

        private void MoveAngular(float pTimestep)
        {
            /*
             * private Vector3 m_angularMotorDirection = Vector3.Zero;            // angular velocity requested by LSL motor
             * private int m_angularMotorApply = 0;                            // application frame counter
             * private float m_angularMotorVelocity = 0;                        // current angular motor velocity (ramps up and down)
             * private float m_angularMotorTimescale = 0;                        // motor angular velocity ramp up rate
             * private float m_angularMotorDecayTimescale = 0;                    // motor angular velocity decay rate
             * private Vector3 m_angularFrictionTimescale = Vector3.Zero;        // body angular velocity  decay rate
             * private Vector3 m_lastAngularVelocity = Vector3.Zero;            // what was last applied to body
             */

            // Get what the body is doing, this includes 'external' influences
            d.Vector3 angularVelocity = d.BodyGetAngularVel(Body);
            //         Vector3 angularVelocity = Vector3.Zero;

            if (m_angularMotorApply > 0)
            {
                // ramp up to new value
                //   current velocity  +=                         error                       /    (time to get there / step interval)
                //                               requested speed            -  last motor speed
                m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep);
                m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep);
                m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep);

                m_angularMotorApply--;        // This is done so that if script request rate is less than phys frame rate the expected
                // velocity may still be acheived.
            }
            else
            {
                // no motor recently applied, keep the body velocity

                /*        m_angularMotorVelocity.X = angularVelocity.X;
                 *      m_angularMotorVelocity.Y = angularVelocity.Y;
                 *      m_angularMotorVelocity.Z = angularVelocity.Z; */

                // and decay the velocity
                m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep);
            } // end motor section

            // Vertical attractor section
            Vector3 vertattr = Vector3.Zero;

            if (m_verticalAttractionTimescale < 300)
            {
                float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep);
                // get present body rotation
                d.Quaternion rot  = d.BodyGetQuaternion(Body);
                Quaternion   rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W);
                // make a vector pointing up
                Vector3 verterr = Vector3.Zero;
                verterr.Z = 1.0f;
                // rotate it to Body Angle
                verterr = verterr * rotq;
                // verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1.
                // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go
                // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body.
                if (verterr.Z < 0.0f)
                {
                    verterr.X = 2.0f - verterr.X;
                    verterr.Y = 2.0f - verterr.Y;
                }
                // Error is 0 (no error) to +/- 2 (max error)
                // scale it by VAservo
                verterr = verterr * VAservo;
                //if (frcount == 0) Console.WriteLine("VAerr=" + verterr);

                // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so
                // Change  Body angular velocity  X based on Y, and Y based on X. Z is not changed.
                vertattr.X = verterr.Y;
                vertattr.Y = -verterr.X;
                vertattr.Z = 0f;

                // scaling appears better usingsquare-law
                float bounce = 1.0f - (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency);
                vertattr.X += bounce * angularVelocity.X;
                vertattr.Y += bounce * angularVelocity.Y;
            } // else vertical attractor is off

            //        m_lastVertAttractor = vertattr;

            // Bank section tba
            // Deflection section tba

            // Sum velocities
            m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // + bank + deflection

            if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0)
            {
                m_lastAngularVelocity.X = 0;
                m_lastAngularVelocity.Y = 0;
            }

            if (!m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f))
            {
                if (!d.BodyIsEnabled(Body))
                {
                    d.BodyEnable(Body);
                }
            }
            else
            {
                m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero.
            }

            // apply friction
            Vector3 decayamount = Vector3.One / (m_angularFrictionTimescale / pTimestep);

            m_lastAngularVelocity -= m_lastAngularVelocity * decayamount;

            // Apply to the body
            d.BodySetAngularVel(Body, m_lastAngularVelocity.X, m_lastAngularVelocity.Y, m_lastAngularVelocity.Z);
        }
Beispiel #6
0
        /// <summary>
        /// Called from Simulate
        /// This is the avatar's movement control + PID Controller
        /// </summary>
        /// <param name="timeStep"></param>
        public void Move (float timeStep, ref List<AuroraODECharacter> defects)
        {
            //  no lock; for now it's only called from within Simulate()

            // If the PID Controller isn't active then we set our force
            // calculating base velocity to the current position

            if (Body == IntPtr.Zero)
                return;

            if (!m_shouldBePhysical)
                return;

            // replace amotor
            d.Quaternion dtmp;
            dtmp.W = 1;
            dtmp.X = 0;
            dtmp.Y = 0;
            dtmp.Z = 0;
            d.BodySetQuaternion (Body, ref dtmp);
            d.BodySetAngularVel(Body, 0, 0, 0);

            Vector3 vec = Vector3.Zero;
            d.Vector3 vel = d.BodyGetLinearVel(Body);

            #region Flight Ceiling

            // rex, added height check

            d.Vector3 tempPos = d.BodyGetPosition (Body);

            if (m_pidControllerActive == false)
            {
                _zeroPosition = d.BodyGetPosition (Body);
            }

            if (_parent_scene.m_useFlightCeilingHeight && tempPos.Z > _parent_scene.m_flightCeilingHeight)
            {
                tempPos.Z = _parent_scene.m_flightCeilingHeight;
                d.BodySetPosition (Body, tempPos.X, tempPos.Y, tempPos.Z);
                d.Vector3 tempVel = d.BodyGetLinearVel (Body);
                if (tempVel.Z > 0.0f)
                {
                    tempVel.Z = 0.0f;
                    d.BodySetLinearVel (Body, tempVel.X, tempVel.Y, tempVel.Z);
                }
                if (_target_velocity.Z > 0.0f)
                    _target_velocity.Z = 0.0f;
            }

            // endrex

            #endregion

            #region NonFinite Pos

            Vector3 localPos = new Vector3 ((float)tempPos.X, (float)tempPos.Y, (float)tempPos.Z);

            if (!localPos.IsFinite ())
            {
                m_log.Warn ("[PHYSICS]: Avatar Position is non-finite!");
                defects.Add (this);
                // _parent_scene.RemoveCharacter(this);

                // destroy avatar capsule and related ODE data
                /*
                                if (Amotor != IntPtr.Zero)
                                    {
                                    // Kill the Amotor
                                    d.JointDestroy(Amotor);
                                    Amotor = IntPtr.Zero;
                                    }
                */
                //kill the Geometry
                _parent_scene.waitForSpaceUnlock (_parent_scene.space);

                if (Body != IntPtr.Zero)
                {
                    //kill the body
                    d.BodyDestroy (Body);

                    Body = IntPtr.Zero;
                }

                if (Shell != IntPtr.Zero)
                {
                    d.GeomDestroy (Shell);
                    _parent_scene.geom_name_map.Remove (Shell);
                    Shell = IntPtr.Zero;
                }
                return;
            }

            #endregion

            #region Check for out of region

            if (Position.X < 0.25f || Position.Y < 0.25f ||
                Position.X > _parent_scene.Region.RegionSizeX - .25f ||
                Position.Y > _parent_scene.Region.RegionSizeY - .25f)
            {
                if (!CheckForRegionCrossing())
                {
                    Vector3 newPos = Position;
                    newPos.X = Util.Clip(Position.X, 0.75f, _parent_scene.Region.RegionSizeX - 0.75f);
                    newPos.Y = Util.Clip(Position.Y, 0.75f, _parent_scene.Region.RegionSizeY - 0.75f);
                    Position = newPos;
                    d.BodySetPosition(Body, newPos.X, newPos.Y, newPos.Z);
                }
            }

            #endregion

            #region Movement Multiplier

            float movementmult = 1f;
            if (!m_alwaysRun)
                movementmult /= _parent_scene.avMovementDivisorWalk;
            else
                movementmult /= _parent_scene.avMovementDivisorRun;

            movementmult *= 10;
            movementmult *= SpeedModifier;
            if (flying)
                movementmult *= _parent_scene.m_AvFlySpeed;

            #endregion

            #region Check for underground

            if (!(Position.X < 0.25f || Position.Y < 0.25f ||
                Position.X > _parent_scene.Region.RegionSizeX - .25f ||
                Position.Y > _parent_scene.Region.RegionSizeY - .25f))
            {
                float groundHeight = _parent_scene.GetTerrainHeightAtXY (
                           tempPos.X + (tempPos.X == 0 ? tempPos.X : timeStep * 0.75f * vel.X),
                           tempPos.Y + (tempPos.Y == 0 ? tempPos.Y : timeStep * 0.75f * vel.Y));

                if ((tempPos.Z - AvatarHalfsize) < groundHeight)
                {
                    if (!flying)
                    {
                        //if (_target_velocity.Z < 0)
                        _target_velocity.Z = 0;
                        vec.Z = -vel.Z * PID_D * 2f + ((groundHeight - (tempPos.Z - AvatarHalfsize)) * PID_P * 100.0f);
                    }
                    else
                        vec.Z = ((groundHeight - (tempPos.Z - AvatarHalfsize)) * PID_P);
                }
                if (tempPos.Z - AvatarHalfsize - groundHeight < 0.12f)
                {
                    m_iscolliding = true;
                    m_iscollidingGround = true;
                    flying = false; // ground the avatar
                    ContactPoint point = new ContactPoint ();
                    point.PenetrationDepth = vel.Z;
                    point.Position = Position;
                    point.SurfaceNormal = Vector3.Zero;

                    //0 is the ground localID
                    this.AddCollisionEvent (0, point);
                }
                else
                    m_iscollidingGround = false;
            }
            else
                m_iscollidingGround = true;//Assume that they are crossing, and keep them from falling down

            #endregion

            #region Movement

            #region Jump code

            if (IsJumping && (IsColliding && m_preJumpCounter > _parent_scene.m_preJumpTime + 10) || m_preJumpCounter > 50)
            {
                m_isJumping = false;
                m_preJumpCounter = 0;
            }
            if (IsJumping)
                m_preJumpCounter++;

            if (m_ispreJumping && m_preJumpCounter == _parent_scene.m_preJumpTime)
            {
                m_ispreJumping = false;
                _target_velocity += m_preJumpForce * _parent_scene.m_preJumpForceMultiplier;
                m_preJumpCounter = 0;
                m_isJumping = true;
            }
            if (m_ispreJumping)
            {
                m_preJumpCounter++;
                TriggerMovementUpdate();
                return;
            }

            #endregion

            //  if velocity is zero, use position control; otherwise, velocity control
            if (_target_velocity == Vector3.Zero &&
                Math.Abs (vel.X) < 0.05 && Math.Abs (vel.Y) < 0.05 && Math.Abs (vel.Z) < 0.05 && (this.m_iscollidingGround || this.m_iscollidingObj || this.flying))
            //This is so that if we get moved by something else, it will update us in the client
            {
                m_isJumping = false;
                //  keep track of where we stopped.  No more slippin' & slidin'
                if (!_zeroFlag)
                {
                    _zeroFlag = true;
                    _zeroPosition = tempPos;
                }

                if (m_pidControllerActive)
                {
                    // We only want to deactivate the PID Controller if we think we want to have our surrogate
                    // react to the physics scene by moving it's position.
                    // Avatar to Avatar collisions
                    // Prim to avatar collisions
                    // if target vel is zero why was it here ?
                    vec.X = -vel.X * PID_D + (_zeroPosition.X - tempPos.X) * PID_P;
                    vec.Y = -vel.Y * PID_D + (_zeroPosition.Y - tempPos.Y) * PID_P;
                }
            }
            else
            {
                m_pidControllerActive = true;
                _zeroFlag = false;

                if (m_iscolliding)
                {
                    if (!flying)
                    {
                        if (_target_velocity.Z != 0.0f)
                            vec.Z = (_target_velocity.Z * movementmult - vel.Z) * PID_D;// + (_zeroPosition.Z - tempPos.Z) * PID_P)) _zeropos maybe bad here
                        // We're standing or walking on something
                        vec.X = (_target_velocity.X * movementmult - vel.X) * PID_D * 2;
                        vec.Y = (_target_velocity.Y * movementmult - vel.Y) * PID_D * 2;
                    }
                    else
                    {
                        // We're flying and colliding with something
                        vec.X = (_target_velocity.X * movementmult - vel.X) * PID_D * 0.5f;
                        vec.Y = (_target_velocity.Y * movementmult - vel.Y) * PID_D * 0.5f;
                    }
                }
                else
                {
                    if (flying)
                    {
                        // we're flying
                        vec.X = (_target_velocity.X * movementmult - vel.X) * PID_D * 0.75f;
                        vec.Y = (_target_velocity.Y * movementmult - vel.Y) * PID_D * 0.75f;
                    }
                    else
                    {
                        // we're not colliding and we're not flying so that means we're falling!
                        // m_iscolliding includes collisions with the ground.
                        vec.X = (_target_velocity.X - vel.X) * PID_D * 0.85f;
                        vec.Y = (_target_velocity.Y - vel.Y) * PID_D * 0.85f;
                    }
                }
                if (flying)
                {
                    #region Av gravity

                    if (_parent_scene.AllowAvGravity &&
                        tempPos.Z > _parent_scene.AvGravityHeight) //Should be stop avies from flying upwards
                    {
                        //Decay going up 
                        if (_target_velocity.Z > 0)
                        {
                            //How much should we force them down?
                            float Multiplier = (_parent_scene.AllowAvsToEscapeGravity ? .03f : .1f);
                            //How much should we force them down?
                            float fudgeHeight = (_parent_scene.AllowAvsToEscapeGravity ? 80 : 30);
                            //We add the 30 so that gravity is resonably strong once they pass the min height
                            Multiplier *= tempPos.Z + fudgeHeight - _parent_scene.AvGravityHeight;

                            //Limit these so that things don't go wrong
                            if (Multiplier < 1)
                                Multiplier = 1;

                            float maxpower = (_parent_scene.AllowAvsToEscapeGravity ? 1.5f : 3f);

                            if (Multiplier > maxpower)
                                Multiplier = maxpower;

                            _target_velocity.Z /= Multiplier;
                            vel.Z /= Multiplier;
                        }
                    }

                    #endregion

                    vec.Z = (_target_velocity.Z * movementmult - vel.Z) * PID_D * 0.5f;
                    if (_parent_scene.AllowAvGravity && tempPos.Z > _parent_scene.AvGravityHeight)
                        //Add extra gravity
                        vec.Z += ((10 * _parent_scene.gravityz) * Mass);
                }
            }

            if (flying)
            {
                #region Auto Fly Height

                //Added for auto fly height. Kitto Flora
                //Changed to only check if the avatar is flying around,

                // Revolution: If the avatar is going down, they are trying to land (probably), so don't push them up to make it harder
                //   Only if they are moving around sideways do we need to push them up
                if (_target_velocity.X != 0 || _target_velocity.Y != 0)
                {
                    Vector3 forwardVel = new Vector3 (_target_velocity.X > 0 ? 2 : (_target_velocity.X < 0 ? -2 : 0),
                        _target_velocity.Y > 0 ? 2 : (_target_velocity.Y < 0 ? -2 : 0),
                        0);
                    float target_altitude = _parent_scene.GetTerrainHeightAtXY (tempPos.X, tempPos.Y) + MinimumGroundFlightOffset;

                    //We cheat a bit and do a bit lower than normal
                    if ((tempPos.Z - CAPSULE_LENGTH) < target_altitude ||
                            (tempPos.Z - CAPSULE_LENGTH) < _parent_scene.GetTerrainHeightAtXY (tempPos.X + forwardVel.X, tempPos.Y + forwardVel.Y)
                            + MinimumGroundFlightOffset)
                        vec.Z += (target_altitude - tempPos.Z) * PID_P * 0.5f;
                }
                else
                {
                    //Straight up and down, only apply when they are very close to the ground
                    float target_altitude = _parent_scene.GetTerrainHeightAtXY (tempPos.X, tempPos.Y);

                    if ((tempPos.Z - CAPSULE_LENGTH + (MinimumGroundFlightOffset / 1.5)) < target_altitude + MinimumGroundFlightOffset)
                    {
                        if ((tempPos.Z - CAPSULE_LENGTH) < target_altitude + 1)
                        {
                            vec.Z += ((target_altitude + 4) - (tempPos.Z - CAPSULE_LENGTH)) * PID_P;
                        }
                        else
                            vec.Z += ((target_altitude + MinimumGroundFlightOffset) - (tempPos.Z - CAPSULE_LENGTH)) * PID_P * 0.5f;
                    }
                }

                #endregion
            }

            #region Gravity

            if (!flying && _parent_scene.AllowAvGravity)
            {
                if (!_parent_scene.UsePointGravity)
                {
                    //Add normal gravity
                    vec.X += _parent_scene.gravityx * m_mass;
                    vec.Y += _parent_scene.gravityy * m_mass;
                    vec.Z += _parent_scene.gravityz * m_mass;
                }
                else
                {
                    Vector3 cog = _parent_scene.PointOfGravity;
                    if (cog.X != 0)
                        vec.X += (cog.X - tempPos.X) * m_mass;
                    if (cog.Y != 0)
                        vec.Y += (cog.Y - tempPos.Y) * m_mass;
                    if (cog.Z != 0)
                        vec.Z += (cog.Z - tempPos.Z) * m_mass;
                }
            }

            #endregion

            #region Under water physics

            if (_parent_scene.AllowUnderwaterPhysics && (float)tempPos.X < _parent_scene.Region.RegionSizeX &&
                (float)tempPos.Y < _parent_scene.Region.RegionSizeY)
            {
                //Position plus height to av's shoulder (aprox) is just above water
                if ((tempPos.Z + (CAPSULE_LENGTH / 3) - .25f) < _parent_scene.GetWaterLevel ((float)tempPos.X, (float)tempPos.Y))
                {
                    if (StartingUnderWater)
                        ShouldBeWalking = Flying == false;
                    StartingUnderWater = false;
                    WasUnderWater = true;
                    Flying = true;
                    lastUnderwaterPush = 0;
                    if (ShouldBeWalking)
                    {
                        lastUnderwaterPush += (float)(_parent_scene.GetWaterLevel ((float)tempPos.X, (float)tempPos.Y) - tempPos.Z) * 33 + 3;
                        vec.Z += lastUnderwaterPush;
                    }
                    else
                    {
                        lastUnderwaterPush += 3500;
                        lastUnderwaterPush += (float)(_parent_scene.GetWaterLevel ((float)tempPos.X, (float)tempPos.Y) - tempPos.Z) * 8;
                        vec.Z += lastUnderwaterPush;
                    }
                }
                else
                {
                    StartingUnderWater = true;
                    if (WasUnderWater)
                    {
                        WasUnderWater = false;
                        Flying = true;
                    }
                }
            }

            #endregion

            #endregion

            #region Apply the force

            if (vec.IsFinite ())
            {
                if (vec.X < 100000000 && vec.Y < 10000000 && vec.Z < 10000000) //Checks for crazy, going to NaN us values
                {
                    // round small values to zero. those possible are just errors
                    if (Math.Abs (vec.X) < 0.001)
                        vec.X = 0;
                    if (Math.Abs (vec.Y) < 0.001)
                        vec.Y = 0;
                    if (Math.Abs (vec.Z) < 0.001)
                        vec.Z = 0;

                    if (vec == Vector3.Zero) //if we arn't moving, STOP
                        d.BodySetLinearVel(Body, vec.X, vec.Y, vec.Z);
                    else
                        doForce (vec);

                    //When falling, we keep going faster and faster, and eventually, the client blue screens (blue is all you see).
                    // The speed that does this is slightly higher than -30, so we cap it here so we never do that during falling.
                    if (vel.Z < -30)
                    {
                        vel.Z = -30;
                        d.BodySetLinearVel (Body, vel.X, vel.Y, vel.Z);
                    }

                    //Decay out the target velocity
                    _target_velocity *= _parent_scene.m_avDecayTime;
                    if (!_zeroFlag && _target_velocity.ApproxEquals (Vector3.Zero, _parent_scene.m_avStopDecaying))
                        _target_velocity = Vector3.Zero;
                }
                else
                {
                    //This is a safe guard from going NaN, but it isn't very smooth... which is ok
                    d.BodySetForce (Body, 0, 0, 0);
                    d.BodySetLinearVel (Body, 0, 0, 0);
                }
            }
            else
            {
                m_log.Warn ("[PHYSICS]: Got a NaN force vector in Move()");
                m_log.Warn ("[PHYSICS]: Avatar Position is non-finite!");
                defects.Add (this);
                //kill the Geometry
                _parent_scene.waitForSpaceUnlock (_parent_scene.space);

                if (Body != IntPtr.Zero)
                {
                    //kill the body
                    d.BodyDestroy (Body);

                    Body = IntPtr.Zero;
                }

                if (Shell != IntPtr.Zero)
                {
                    d.GeomDestroy (Shell);
                    _parent_scene.geom_name_map.Remove (Shell);
                    Shell = IntPtr.Zero;
                }
            }

            #endregion
        }
        // normally called from within OnJointMoved, which is called from within a lock (OdeLock)
        // WARNING: ODE sometimes returns <0,0,0> as the joint axis! Therefore this function
        // appears to be unreliable. Fortunately we can compute the joint axis ourselves by
        // keeping track of the joint's original orientation relative to one of the involved bodies.
        public override Vector3 GetJointAxis(PhysicsJoint joint)
        {
            Debug.Assert(joint.IsInPhysicsEngine);
            d.Vector3 axis = new d.Vector3();

            if (!(joint is AuroraODEPhysicsJoint))
            {
                DoJointErrorMessage(joint, "warning: non-ODE joint requesting anchor: " + joint.ObjectNameInScene);
            }
            else
            {
                AuroraODEPhysicsJoint odeJoint = (AuroraODEPhysicsJoint)joint;
                switch (odeJoint.Type)
                {
                    case PhysicsJointType.Ball:
                        DoJointErrorMessage(joint, "warning - axis requested for ball joint: " + joint.ObjectNameInScene);
                        break;
                    case PhysicsJointType.Hinge:
                        d.JointGetHingeAxis(odeJoint.jointID, out axis);
                        break;
                }
            }
            return new Vector3((float)axis.X, (float)axis.Y, (float)axis.Z);
        }
Beispiel #8
0
        /// <summary>
        /// Updates the reported position and velocity.  This essentially sends the data up to ScenePresence.
        /// </summary>
        /// <param name="defects">The character will be added to this list if there is something wrong (non-finite
        /// position or velocity).
        /// </param>
        internal void UpdatePositionAndVelocity(List<OdeCharacter> defects)
        {
            //  no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
            d.Vector3 newPos;
            try
            {
                newPos = d.BodyGetPosition(Body);
            }
            catch (NullReferenceException)
            {
                bad = true;
                defects.Add(this);
                newPos = new d.Vector3(_position.X, _position.Y, _position.Z);
                base.RaiseOutOfBounds(_position); // Tells ScenePresence that there's a problem!
                m_log.WarnFormat("[ODE CHARACTER]: Avatar Null reference for Avatar {0}, physical actor {1}", Name, m_uuid);

                return;
            }

            //  kluge to keep things in bounds.  ODE lets dead avatars drift away (they should be removed!)
            if (newPos.X < 0.0f) newPos.X = 0.0f;
            if (newPos.Y < 0.0f) newPos.Y = 0.0f;
            if (newPos.X > (int)_parent_scene.WorldExtents.X - 0.05f) newPos.X = (int)_parent_scene.WorldExtents.X - 0.05f;
            if (newPos.Y > (int)_parent_scene.WorldExtents.Y - 0.05f) newPos.Y = (int)_parent_scene.WorldExtents.Y - 0.05f;

            _position.X = newPos.X;
            _position.Y = newPos.Y;
            _position.Z = newPos.Z;

            // I think we need to update the taintPosition too -- Diva 12/24/10
            m_taintPosition = _position;

            // Did we move last? = zeroflag
            // This helps keep us from sliding all over

            if (_zeroFlag)
            {
                _velocity = Vector3.Zero;

                // Did we send out the 'stopped' message?
                if (!m_lastUpdateSent)
                {
                    m_lastUpdateSent = true;
                    //base.RequestPhysicsterseUpdate();
                }
            }
            else
            {
                m_lastUpdateSent = false;
                d.Vector3 newVelocity;

                try
                {
                    newVelocity = d.BodyGetLinearVel(Body);
                }
                catch (NullReferenceException)
                {
                    newVelocity.X = _velocity.X;
                    newVelocity.Y = _velocity.Y;
                    newVelocity.Z = _velocity.Z;
                }

                _velocity.X = newVelocity.X;
                _velocity.Y = newVelocity.Y;
                _velocity.Z = newVelocity.Z;

                if (_velocity.Z < -6 && !m_hackSentFall)
                {
                    m_hackSentFall = true;
                    m_pidControllerActive = false;
                }
                else if (flying && !m_hackSentFly)
                {
                    //m_hackSentFly = true;
                    //base.SendCollisionUpdate(new CollisionEventUpdate());
                }
                else
                {
                    m_hackSentFly = false;
                    m_hackSentFall = false;
                }
            }
        }
Beispiel #9
0
        }   // end Step

        private void MoveLinear(float pTimestep, AuroraODEPhysicsScene _pParentScene)
        {
            d.Vector3 pos = d.BodyGetPosition (Body);
            d.Vector3 oldPos = pos;

            if (m_lastPositionVector.X != pos.X ||
                m_lastPositionVector.Y != pos.Y ||
                m_lastPositionVector.Z != pos.Z)
            {
                m_lastPositionVector = d.BodyGetPosition (Body);
                m_lastAngularVelocity = new Vector3 ((float)d.BodyGetAngularVel (Body).X, (float)d.BodyGetAngularVel (Body).Y, (float)d.BodyGetAngularVel (Body).Z);
            }
            if (!m_linearMotorDirection.ApproxEquals (Vector3.Zero, 0.01f))  // requested m_linearMotorDirection is significant
            {
                if (!d.BodyIsEnabled (Body))
                    d.BodyEnable (Body);

                // add drive to body
                Vector3 addAmount = m_linearMotorDirection / (m_linearMotorTimescale * m_linearMotorDecayTimescale / (pTimestep));
                
                m_lastLinearVelocityVector += (addAmount * 10);  // lastLinearVelocityVector is the current body velocity vector?

                // This will work temporarily, but we really need to compare speed on an axis
                // KF: Limit body velocity to applied velocity?
                if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X))
                    m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X;
                if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y))
                    m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y;
                if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z))
                    m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z;
            }
            else
            {        // requested is not significant
                // if what remains of applied is small, zero it.
                if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f))
                    m_lastLinearVelocityVector = Vector3.Zero;
            }
            m_linearMotorDirection = Vector3.Zero;
            // convert requested object velocity to world-referenced vector
            m_dir = m_lastLinearVelocityVector;
            d.Quaternion rot = d.BodyGetQuaternion (Body);
            Quaternion rotq = new Quaternion (rot.X, rot.Y, rot.Z, rot.W);    // rotq = rotation of object
            m_dir *= rotq;

            // Preserve the current Z velocity
            d.Vector3 vel_now = d.BodyGetLinearVel(Body);
            m_dir.Z += (float)vel_now.Z;        // Preserve the accumulated falling velocity

            #region Blocking End Points

            //This makes sure that the vehicle doesn't leave the defined limits of position
            if (m_BlockingEndPoint != Vector3.Zero)
            {
                Vector3 posChange = new Vector3();
                posChange.X = (float)(pos.X - m_lastPositionVector.X);
                posChange.Y = (float)(pos.Y - m_lastPositionVector.Y);
                posChange.Z = (float)(pos.Z - m_lastPositionVector.Z);

                if (pos.X >= (m_BlockingEndPoint.X - (float)1))
                    pos.X -= posChange.X + 1;

                if (pos.Y >= (m_BlockingEndPoint.Y - (float)1))
                    pos.Y -= posChange.Y + 1;

                if (pos.Z >= (m_BlockingEndPoint.Z - (float)1))
                    pos.Z -= posChange.Z + 1;

                if (pos.X <= 0)
                    pos.X += posChange.X + 1;

                if (pos.Y <= 0)
                    pos.Y += posChange.Y + 1;
            }

            #endregion

            // Check if hovering
            if ((m_Hoverflags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
            {
                // We should hover, get the target height
                if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != 0)
                {
                    m_VhoverTargetHeight = (float)_pParentScene.GetWaterLevel((float)pos.X, (float)pos.Y) + m_VhoverHeight;
                }
                if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
                {
                    m_VhoverTargetHeight = _pParentScene.GetTerrainHeightAtXY((float)pos.X, (float)pos.Y) + m_VhoverHeight;
                }
                if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
                {
                    m_VhoverTargetHeight = m_VhoverHeight;
                }

                if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != 0)
                {
                    // If body is already heigher, use its height as target height
                    if (pos.Z > m_VhoverTargetHeight)
                        m_VhoverTargetHeight = (float)pos.Z;
                }

                if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
                {
                    if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2)
                    {
                        if ((pos.Z - (pos.Z - m_VhoverTargetHeight)) >= _pParentScene.GetTerrainHeightAtXY((float)pos.X, (float)pos.Y))
                            pos.Z = m_VhoverTargetHeight;
                    }
                }
                else
                {
                    // m_VhoverEfficiency - 0=boucy, 1=Crit.damped
                    // m_VhoverTimescale - time to acheive height
                    float herr0 = (float)pos.Z - m_VhoverTargetHeight;
                    // Replace Vertical speed with correction figure if significant
                    if (Math.Abs(herr0) > 0.01f)
                    {
                        //Note: we use 1.05 because it doesn't disappear completely, only very critically damped
                        m_dir.Z = (float)((-((herr0 * pTimestep * 50.0f) / m_VhoverTimescale)) * (1.05 - m_VhoverEfficiency));
                    }
                    else
                        //Too small, zero it.
                        m_dir.Z = 0f;
                }
            }

            //Do this here, because it shouldn't clear out gravity or the tainted forces (not part of vehicle physics)
            if ((m_flags & (VehicleFlag.NO_X)) != 0)
                m_dir.X = 0;
            if ((m_flags & (VehicleFlag.NO_Y)) != 0)
                m_dir.Y = 0;
            if ((m_flags & (VehicleFlag.NO_Z)) != 0)
                m_dir.Z = 0;

            m_lastPositionVector = d.BodyGetPosition(Body);

            #region Deal with tainted forces

            // KF: So far I have found no good method to combine a script-requested
            // .Z velocity and gravity. Therefore only 0g will used script-requested
            // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only.
            // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
            Vector3 TaintedForce = new Vector3();
            if (m_forcelist.Count != 0)
            {
                try
                {
                    for (int i = 0; i < m_forcelist.Count; i++)
                    {
                        TaintedForce = TaintedForce + (m_forcelist[i] * 100);
                    }
                }
                catch (IndexOutOfRangeException)
                {
                    TaintedForce = Vector3.Zero;
                }
                catch (ArgumentOutOfRangeException)
                {
                    TaintedForce = Vector3.Zero;
                }
                m_forcelist = new List<Vector3>();
            }

            #endregion

            #region Deflection

            //Forward is the prefered direction
            Vector3 PreferredAxisOfMotion = new Vector3 (1 + 1 * (m_linearDeflectionEfficiency / m_linearDeflectionTimescale) * pTimestep * pTimestep * pTimestep, 1, 1);
            PreferredAxisOfMotion *= m_referenceFrame;

            //Multiply it so that it scales linearly
            m_dir *= PreferredAxisOfMotion;

            #endregion

            if (Mass == 0)
            {
                d.Mass mass;
                d.BodyGetMass(m_body, out mass);

                Mass = mass.mass;
                Mass *= 2;
            }
            //No Setting forces, only velocity! Forces are NOT recommended to be used by the ODE manual
            //d.BodySetForce(Body, _pParentScene.gravityx + TaintedForce.X,
            //    _pParentScene.gravityy + TaintedForce.Y,
            //    (_pParentScene.gravityz * Mass * (1f - m_VehicleBuoyancy)) + TaintedForce.Z);

            //d.BodySetForce(Body, _pParentScene.gravityx + TaintedForce.X + (m_dir.X * 10000),
            //    _pParentScene.gravityy + TaintedForce.Y + (m_dir.Y * 10000),
            //    (_pParentScene.gravityz * Mass * (1f - m_VehicleBuoyancy)) + TaintedForce.Z + (m_dir.Z * 10000));

            m_dir += TaintedForce;
            //Uses the square to make bouyancy more effective as in SL, as it seems to effect gravity more the higher the value is
            //This check helps keep things from being pushed into the ground and the consequence of being shoved back out
            m_dir.Z += ((_pParentScene.gravityz * (float)Mass) * ((((1 - m_VehicleBuoyancy) * (1 - m_VehicleBuoyancy))) * pTimestep));

            d.BodySetLinearVel(Body, m_dir.X, m_dir.Y, m_dir.Z);

            //Check for changes and only set it once
            if (pos.X != oldPos.X || pos.Y != oldPos.Y || pos.Z != oldPos.Z)
                d.BodySetPosition(Body, pos.X, pos.Y, pos.Z);

            // apply friction
            // note: seems more effective with how SL does this with the square
            Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / (pTimestep * pTimestep));
            m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount;
        } // end MoveLinear()
Beispiel #10
0
 public static extern void DrawConvex(ref d.Vector3 pos, ref d.Matrix3 R, dReal[] planes, int planeCount, dReal[] points, int pointCount, int[] polygons);
Beispiel #11
0
 public static extern void DrawCapsule(ref d.Vector3 pos, ref d.Matrix3 R, dReal length, dReal radius);
Beispiel #12
0
 public static extern void DrawBox(ref d.Vector3 pos, ref d.Matrix3 R, ref d.Vector3 sides);
Beispiel #13
0
        /// <summary>
        ///   Called from Simulate
        ///   This is the avatar's movement control + PID Controller
        /// </summary>
        /// <param name = "timeStep"></param>
        public void Move(float timeStep, ref List<AuroraODECharacter> defects)
        {
            //  no lock; for now it's only called from within Simulate()

            // If the PID Controller isn't active then we set our force
            // calculating base velocity to the current position

            if (Body == IntPtr.Zero)
                return;

            if (!m_shouldBePhysical)
                return;

            Vector3 vec = Vector3.Zero;
            d.Vector3 vel = d.BodyGetLinearVel(Body);
            d.Vector3 tempPos;
            d.BodyCopyPosition(Body, out tempPos);

            #region Flight Ceiling

            // rex, added height check

            if (m_pidControllerActive == false)
            {
                _zeroPosition = tempPos;
            }

            if (_parent_scene.m_useFlightCeilingHeight && tempPos.Z > _parent_scene.m_flightCeilingHeight)
            {
                tempPos.Z = _parent_scene.m_flightCeilingHeight;
                d.BodySetPosition(Body, tempPos.X, tempPos.Y, tempPos.Z);
                if (vel.Z > 0.0f)
                {
                    vel.Z = 0.0f;
                    d.BodySetLinearVel(Body, vel.X, vel.Y, vel.Z);
                }
                if (_target_velocity.Z > 0.0f)
                    _target_velocity.Z = 0.0f;
            }

            // endrex

            #endregion

            #region NonFinite Pos

            Vector3 localPos = new Vector3(tempPos.X, tempPos.Y, tempPos.Z);

            if (!IsFinite(localPos))
            {
                MainConsole.Instance.Warn("[PHYSICS]: Avatar Position is non-finite!");
                defects.Add(this);
                // _parent_scene.RemoveCharacter(this);

                // destroy avatar capsule and related ODE data

                if (Amotor != IntPtr.Zero)
                {
                    // Kill the Amotor
                    d.JointDestroy(Amotor);
                    Amotor = IntPtr.Zero;
                }

                //kill the Geometry
                _parent_scene.waitForSpaceUnlock(_parent_scene.space);

                if (Body != IntPtr.Zero)
                {
                    //kill the body
                    d.BodyDestroy(Body);

                    Body = IntPtr.Zero;
                }

                if (Shell != IntPtr.Zero)
                {
                    d.GeomDestroy(Shell);
                    Shell = IntPtr.Zero;
                }
                return;
            }

            #endregion

            #region Check for out of region

            if (Position.X < 0.25f || Position.Y < 0.25f ||
                Position.X > _parent_scene.Region.RegionSizeX - .25f ||
                Position.Y > _parent_scene.Region.RegionSizeY - .25f)
            {
                if (!CheckForRegionCrossing())
                {
                    Vector3 newPos = Position;
                    newPos.X = Util.Clip(Position.X, 0.75f, _parent_scene.Region.RegionSizeX - 0.75f);
                    newPos.Y = Util.Clip(Position.Y, 0.75f, _parent_scene.Region.RegionSizeY - 0.75f);
                    Position = newPos;
                    d.BodySetPosition(Body, newPos.X, newPos.Y, newPos.Z);
                }
            }

            #endregion

            #region Movement Multiplier

            float movementmult = 1f;
            if (!m_alwaysRun)
                movementmult /= _parent_scene.avMovementDivisorWalk;
            else
                movementmult /= _parent_scene.avMovementDivisorRun;

            movementmult *= 10;
            movementmult *= SpeedModifier;
//            movementmult *= 1 / _parent_scene.TimeDilation;
            if (flying)
                movementmult *= _parent_scene.m_AvFlySpeed;

            #endregion

            #region Check for underground

            d.AABB aabb;
            d.GeomGetAABB(Shell, out aabb);
            float chrminZ = aabb.MinZ;

            Vector3 posch = localPos;

            float ftmp;

            if (flying)
            {
                ftmp = 0.75f*timeStep;
                posch.X += vel.X*ftmp;
                posch.Y += vel.Y*ftmp;
            }

            float groundHeight = _parent_scene.GetTerrainHeightAtXY(posch.X, posch.Y);

            if (chrminZ < groundHeight)
            {
                float depth = groundHeight - chrminZ;

                if (_target_velocity.Z < 0)
                    _target_velocity.Z = 0;

                if (!flying)
                {
                    if (vel.Z < -10f)
                        vel.Z = -10f;
                    vec.Z = -vel.Z*PID_D*1.5f + depth*PID_P*50.0f;
                }
                else
                {
                    vec.Z = depth*PID_P*50.0f;
                }

                if (depth < 0.12f)
                {
                    m_iscolliding = true;
                    m_colliderfilter = 2;
                    m_iscollidingGround = true;

                    ContactPoint point = new ContactPoint
                                             {
                                                 Type = ActorTypes.Ground,
                                                 PenetrationDepth = depth,
                                                 Position = {X = localPos.X, Y = localPos.Y, Z = chrminZ},
                                                 SurfaceNormal = new Vector3(0, 0, -1f)
                                             };

                    //0 is the ground localID
                    AddCollisionEvent(0, point);
                    vec.Z *= 0.5f;
                }
                else
                    m_iscollidingGround = false;
            }
            else
                m_iscollidingGround = false;
/*
            if(Flying && _target_velocity == Vector3.Zero &&
                Math.Abs(vel.Z) < 0.1)
                notMoving = true;
*/

            #endregion

            #region Movement

            #region Jump code

            if (IsJumping)
            {
//                if ((IsColliding) && m_preJumpCounter > _parent_scene.m_preJumpTime || m_preJumpCounter > 150)
                if ((IsColliding) && m_preJumpCounter > _parent_scene.m_preJumpTime || m_preJumpCounter > 150)
                {
                    m_isJumping = false;
                    m_preJumpCounter = 0;
                    _target_velocity.Z = 0;
                }
                else
                    m_preJumpCounter++;
            }

            else if (m_ispreJumping)
            {
                if (m_preJumpCounter == _parent_scene.m_preJumpTime)
                {
                    m_ispreJumping = false;
                    _target_velocity.X = m_preJumpForce.X*_parent_scene.m_preJumpForceMultiplierX;
                    _target_velocity.Y = m_preJumpForce.Y*_parent_scene.m_preJumpForceMultiplierY;
                    _target_velocity.Z = m_preJumpForce.Z*_parent_scene.m_preJumpForceMultiplierZ;

                    m_preJumpCounter = 0;
                    m_isJumping = true;
                }
                else
                {
                    m_preJumpCounter++;
                    TriggerMovementUpdate();
                    return;
                }
            }


            //This is for jumping on prims, since otherwise, you don't get off the ground sometimes
//            if (m_iscolliding && m_isJumping && _target_velocity.Z < 1 && !Flying)
//                _target_velocity.Z += m_preJumpForce.Z * _parent_scene.m_preJumpForceMultiplier;

            #endregion

            Vector3 gravForce = new Vector3();

            //  if velocity is zero, use position control; otherwise, velocity control
            if (_target_velocity == Vector3.Zero &&
                Math.Abs(vel.X) < 0.1 && Math.Abs(vel.Y) < 0.1 && Math.Abs(vel.Z) < 0.1 &&
                (this.m_iscolliding || this.flying || (this._zeroFlag && _wasZeroFlagFlying == flying)))
                //This is so that if we get moved by something else, it will update us in the client
            {
                m_isJumping = false;
                //  keep track of where we stopped.  No more slippin' & slidin'
                if (!_zeroFlag)
                {
                    _zeroFlag = true;
                    _wasZeroFlagFlying = flying;
                    _zeroPosition = tempPos;
                }

                if (m_pidControllerActive)
                {
                    // We only want to deactivate the PID Controller if we think we want to have our surrogate
                    // react to the physics scene by moving it's position.
                    // Avatar to Avatar collisions
                    // Prim to avatar collisions
                    // if target vel is zero why was it here ?
                    vec.X = -vel.X*PID_D + (_zeroPosition.X - tempPos.X)*PID_P;
                    vec.Y = -vel.Y*PID_D + (_zeroPosition.Y - tempPos.Y)*PID_P;
//                    if (!realFlying)
//                        vec.Z +=  - vel.Z * PID_D * 5;
//                    else
                    if (flying)
                        vec.Z += -vel.Z*PID_D*0.5f + (_zeroPosition.Z - tempPos.Z)*PID_P;

//                    _parent_scene.CalculateGravity(m_mass, tempPos, true, 0.15f, ref gravForce);
//                    vec += gravForce;
                }
            }
            else
            {
                m_pidControllerActive = true;
                _zeroFlag = false;

                if (m_iscolliding)
                {
                    if (!flying) //If there is a ground collision, it sets flying to false, so check against real flying
                    {
                        // We're standing or walking on something
                        if (_target_velocity.X != 0.0f)
                            vec.X += (_target_velocity.X * movementmult - vel.X) * PID_D * 2;
                        if (_target_velocity.Y != 0.0f)
                            vec.Y += (_target_velocity.Y * movementmult - vel.Y) * PID_D * 2;
                        if (_target_velocity.Z != 0.0f)
                            vec.Z += (_target_velocity.Z * movementmult - vel.Z) * PID_D;
                        /*// We're standing or walking on something
                        vec.X += (_target_velocity.X*movementmult - vel.X)*PID_D*2;
                        vec.Y += (_target_velocity.Y*movementmult - vel.Y)*PID_D*2;
                        if (_target_velocity.Z > 0.0f)
                            vec.Z += (_target_velocity.Z*movementmult - vel.Z)*PID_D;
                                // + (_zeroPosition.Z - tempPos.Z) * PID_P)) _zeropos maybe bad here*/
                    }
                    else
                    {
                        // We're flying and colliding with something
                        vec.X += (_target_velocity.X*movementmult - vel.X)*PID_D*0.5f;
                        vec.Y += (_target_velocity.Y*movementmult - vel.Y)*PID_D*0.5f;
                        //if(_target_velocity.Z > 0)
                        vec.Z += (_target_velocity.Z*movementmult - vel.Z)*PID_D*0.5f;
                    }
                }
                else
                {
                    if (flying)
                    {
                        // we're flying
                        vec.X += (_target_velocity.X * movementmult - vel.X) * PID_D * 0.75f;
                        vec.Y += (_target_velocity.Y * movementmult - vel.Y) * PID_D * 0.75f;
                    }
                    else
                    {
                        // we're not colliding and we're not flying so that means we're falling!
                        // m_iscolliding includes collisions with the ground.
                        vec.X += (_target_velocity.X - vel.X) * PID_D * 0.85f;
                        vec.Y += (_target_velocity.Y - vel.Y) * PID_D * 0.85f;
                    }
                }


                if (flying)
                {
                    #region Av gravity

                    if (_parent_scene.AllowAvGravity &&
                        tempPos.Z > _parent_scene.AvGravityHeight) //Should be stop avies from flying upwards
                    {
                        //Decay going up 
                        if (_target_velocity.Z > 0)
                        {
                            //How much should we force them down?
                            float Multiplier = (_parent_scene.AllowAvsToEscapeGravity ? .03f : .1f);
                            //How much should we force them down?
                            float fudgeHeight = (_parent_scene.AllowAvsToEscapeGravity ? 80 : 30);
                            //We add the 30 so that gravity is resonably strong once they pass the min height
                            Multiplier *= tempPos.Z + fudgeHeight - _parent_scene.AvGravityHeight;

                            //Limit these so that things don't go wrong
                            if (Multiplier < 1)
                                Multiplier = 1;

                            float maxpower = (_parent_scene.AllowAvsToEscapeGravity ? 1.5f : 3f);

                            if (Multiplier > maxpower)
                                Multiplier = maxpower;

                            _target_velocity.Z /= Multiplier;
                            vel.Z /= Multiplier;
                        }
                    }

                    #endregion

                    vec.Z = (_target_velocity.Z*movementmult - vel.Z)*PID_D*0.5f;
                    if (_parent_scene.AllowAvGravity && tempPos.Z > _parent_scene.AvGravityHeight)
                        //Add extra gravity
                        vec.Z += ((10*_parent_scene.gravityz)*Mass);
                }
            }

            if (realFlying)
            {
                #region Auto Fly Height

                //Added for auto fly height. Kitto Flora
                //Changed to only check if the avatar is flying around,

                // Revolution: If the avatar is going down, they are trying to land (probably), so don't push them up to make it harder
                //   Only if they are moving around sideways do we need to push them up
                if (_target_velocity.X != 0 || _target_velocity.Y != 0)
                {
                    Vector3 forwardVel = new Vector3(_target_velocity.X > 0 ? 2 : (_target_velocity.X < 0 ? -2 : 0),
                                                     _target_velocity.Y > 0 ? 2 : (_target_velocity.Y < 0 ? -2 : 0),
                                                     0);
                    float target_altitude = _parent_scene.GetTerrainHeightAtXY(tempPos.X, tempPos.Y) +
                                            MinimumGroundFlightOffset;

                    //We cheat a bit and do a bit lower than normal
                    if ((tempPos.Z - CAPSULE_LENGTH) < target_altitude ||
                        (tempPos.Z - CAPSULE_LENGTH) <
                        _parent_scene.GetTerrainHeightAtXY(tempPos.X + forwardVel.X, tempPos.Y + forwardVel.Y)
                        + MinimumGroundFlightOffset)
                        if (_target_velocity.Z < 0)
                            vec.Z += (target_altitude - tempPos.Z)*PID_P*0.5f; //Don't apply so much
                        else
                            vec.Z += (target_altitude - tempPos.Z)*PID_P*1.05f;
                }
                else
                {
                    //Straight up and down, only apply when they are very close to the ground
                    float target_altitude = _parent_scene.GetTerrainHeightAtXY(tempPos.X, tempPos.Y);

                    if ((tempPos.Z - CAPSULE_LENGTH + (MinimumGroundFlightOffset/1.5)) <
                        target_altitude + MinimumGroundFlightOffset)
                    {
                        if ((tempPos.Z - CAPSULE_LENGTH) < target_altitude + 1)
                        {
                            vec.Z += ((target_altitude + 4) - (tempPos.Z - CAPSULE_LENGTH))*PID_P;
                        }
                        else
                            vec.Z += ((target_altitude + MinimumGroundFlightOffset) - (tempPos.Z - CAPSULE_LENGTH))*
                                     PID_P*0.5f;
                    }
                }

                #endregion
            }

            #region Gravity

            if (!flying)
                _parent_scene.CalculateGravity(m_mass, tempPos, true, 1.0f, ref gravForce);
            else
                _parent_scene.CalculateGravity(m_mass, tempPos, false, 0.65f, ref gravForce);
                    //Allow point gravity and repulsors affect us a bit

            vec += gravForce;

            #endregion

            #region Under water physics

            if (_parent_scene.AllowUnderwaterPhysics && tempPos.X < _parent_scene.Region.RegionSizeX &&
                tempPos.Y < _parent_scene.Region.RegionSizeY)
            {
                //Position plus height to av's shoulder (aprox) is just above water
                if ((tempPos.Z + (CAPSULE_LENGTH/3) - .25f) < _parent_scene.GetWaterLevel(tempPos.X, tempPos.Y))
                {
                    if (StartingUnderWater)
                        ShouldBeWalking = Flying = false;
                    StartingUnderWater = false;
                    WasUnderWater = true;
                    Flying = true;
                    lastUnderwaterPush = 0;
                    if (ShouldBeWalking)
                    {
                        lastUnderwaterPush += (float) (_parent_scene.GetWaterLevel(tempPos.X, tempPos.Y) - tempPos.Z)*33 +
                                              3;
                        vec.Z += lastUnderwaterPush;
                    }
                    else
                    {
                        lastUnderwaterPush += 3500;
                        lastUnderwaterPush += (float) (_parent_scene.GetWaterLevel(tempPos.X, tempPos.Y) - tempPos.Z)*8;
                        vec.Z += lastUnderwaterPush;
                    }
                }
                else
                {
                    StartingUnderWater = true;
                    if (WasUnderWater)
                    {
                        WasUnderWater = false;
                        Flying = true;
                    }
                }
            }

            #endregion

            #endregion

            #region Apply the force

            if (IsFinite(vec))
            {
                if (vec.X < 100000000 && vec.Y < 10000000 && vec.Z < 10000000)
                    //Checks for crazy, going to NaN us values
                {
                    // round small values to zero. those possible are just errors
                    if (Math.Abs(vec.X) < 0.001)
                        vec.X = 0;
                    if (Math.Abs(vec.Y) < 0.001)
                        vec.Y = 0;
                    if (Math.Abs(vec.Z) < 0.001)
                        vec.Z = 0;

                    //ODE autodisables not moving prims, accept it and reenable when we need to
                    if (!d.BodyIsEnabled(Body))
                        d.BodyEnable(Body);

                    if (vec == Vector3.Zero) //if we arn't moving, STOP
                    {
                        if (m_lastForceApplied != -1)
                        {
                            m_lastForceApplied = -1;
                            d.BodySetLinearVel(Body, vec.X, vec.Y, vec.Z);
                        }
                    }
                    else
                    {
                        if (m_lastForceApplied < 5)
                            vec *= m_lastForceApplied / 5;
                        doForce(vec);
                        m_lastForceApplied++;
                    }

//                    if (!_zeroFlag && (!flying || m_iscolliding))
//                        AlignAvatarTiltWithCurrentDirectionOfMovement (vec, gravForce);

                    // the Amotor still lets avatar rotation to drift during colisions
                    // so force it back to identity

                    d.Quaternion qtmp;
                    qtmp.W = 1;
                    qtmp.X = 0;
                    qtmp.Y = 0;
                    qtmp.Z = 0;
                    d.BodySetQuaternion(Body, ref qtmp);
                    d.BodySetAngularVel(Body, 0, 0, 0);

                    //When falling, we keep going faster and faster, and eventually, the client blue screens (blue is all you see).
                    // The speed that does this is slightly higher than -30, so we cap it here so we never do that during falling.
                    if (vel.Z < -30)
                    {
                        vel.Z = -30;
                        d.BodySetLinearVel(Body, vel.X, vel.Y, vel.Z);
                    }

                    //Decay out the target velocity DON'T it forces tons of updates

                    _target_velocity *= _parent_scene.m_avDecayTime;
                    if (!_zeroFlag && _target_velocity.ApproxEquals (Vector3.Zero, _parent_scene.m_avStopDecaying))
                        _target_velocity = Vector3.Zero;

                }
                else
                {
                    //This is a safe guard from going NaN, but it isn't very smooth... which is ok
                    d.BodySetForce(Body, 0, 0, 0);
                    d.BodySetLinearVel(Body, 0, 0, 0);
                }
            }
            else
            {
                MainConsole.Instance.Warn("[PHYSICS]: Got a NaN force vector in Move()");
                MainConsole.Instance.Warn("[PHYSICS]: Avatar Position is non-finite!");
                defects.Add(this);
                //kill the Geometry
                _parent_scene.waitForSpaceUnlock(_parent_scene.space);

                if (Body != IntPtr.Zero)
                {
                    //kill the body
                    d.BodyDestroy(Body);

                    Body = IntPtr.Zero;
                }

                if (Shell != IntPtr.Zero)
                {
                    d.GeomDestroy(Shell);
                    Shell = IntPtr.Zero;
                }
            }

            #endregion
        }
Beispiel #14
0
        /// <summary>
        ///   Updates the reported position and velocity.  This essentially sends the data up to ScenePresence.
        /// </summary>
        public void UpdatePositionAndVelocity(float timestep)
        {
            if (!m_shouldBePhysical)
                return;

            //  no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
            d.Vector3 vec;
            try
            {
                vec = d.BodyGetPosition(Body);
            }
            catch (NullReferenceException)
            {
                bad = true;
                _parent_scene.BadCharacter(this);
                vec = new d.Vector3(_position.X, _position.Y, _position.Z);
                base.RaiseOutOfBounds(_position); // Tells ScenePresence that there's a problem!
                MainConsole.Instance.WarnFormat("[ODEPLUGIN]: Avatar Null reference for Avatar {0}, physical actor {1}", m_name, m_uuid);
            }

            // vec is a ptr into internal ode data better not mess with it

            _position.X = vec.X;
            _position.Y = vec.Y;
            _position.Z = vec.Z;

            if (!IsFinite(_position))
            {
                _parent_scene.BadCharacter(this);
                base.RaiseOutOfBounds(_position); // Tells ScenePresence that there's a problem!
                return;
            }

            try
            {
                vec = d.BodyGetLinearVel(Body);
            }
            catch (NullReferenceException)
            {
                vec.X = _velocity.X;
                vec.Y = _velocity.Y;
                vec.Z = _velocity.Z;
            }

            d.Vector3 rvec;
            try
            {
                rvec = d.BodyGetAngularVel(Body);
            }
            catch (NullReferenceException)
            {
                rvec.X = m_rotationalVelocity.X;
                rvec.Y = m_rotationalVelocity.Y;
                rvec.Z = m_rotationalVelocity.Z;
            }

            m_rotationalVelocity.X = rvec.X;
            m_rotationalVelocity.Y = rvec.Y;
            m_rotationalVelocity.Z = rvec.Z;

            // vec is a ptr into internal ode data better not mess with it

            _velocity.X = vec.X;
            _velocity.Y = vec.Y;
            _velocity.Z = vec.Z;

            if (!IsFinite(_velocity))
            {
                _parent_scene.BadCharacter(this);
                base.RaiseOutOfBounds(_position); // Tells ScenePresence that there's a problem!
                return;
            }

            bool VelIsZero = false;
            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)
                VelIsZero = true;

            // slow down updates, changed y mind: updates should go at physics fps, acording to movement conditions
/*
            m_UpdateTimecntr += timestep;
            m_UpdateFPScntr = 2.5f * _parent_scene.StepTime;
            if(m_UpdateTimecntr < m_UpdateFPScntr)
                return;

            m_UpdateTimecntr = 0;
*/
            const float VELOCITY_TOLERANCE = 0.025f*0.025f;
            //const float ANG_VELOCITY_TOLERANCE = 0.05f;
            const float POSITION_TOLERANCE = 5f*5f;
            bool needSendUpdate = false;

            float vlength = (_velocity - m_lastVelocity).LengthSquared();
            float plength = (_position - m_lastPosition).LengthSquared();

            if ( //!VelIsZero &&
                (
                    vlength > VELOCITY_TOLERANCE ||
                    plength > POSITION_TOLERANCE
                //(anglength > ANG_VELOCITY_TOLERANCE) ||
                //true
                //                    (Math.Abs(_lastorientation.X - _orientation.X) > 0.001) ||
                //                    (Math.Abs(_lastorientation.Y - _orientation.Y) > 0.001) ||
                //                    (Math.Abs(_lastorientation.Z - _orientation.Z) > 0.001) ||
                //                    (Math.Abs(_lastorientation.W - _orientation.W) > 0.001)
                ))
            {
                needSendUpdate = true;
                m_ZeroUpdateSent = 3;
                //                            _lastorientation = Orientation;
                //                        base.RequestPhysicsterseUpdate();
                //                        base.TriggerSignificantMovement();
            }
            else if (VelIsZero)
            {
                if (m_ZeroUpdateSent > 0)
                {
                    needSendUpdate = true;
                    m_ZeroUpdateSent--;
                }
            }

            if (needSendUpdate)
            {
                m_lastPosition = _position;
                //                        m_lastRotationalVelocity = RotationalVelocity;
                m_lastVelocity = _velocity;
                m_lastAngVelocity = RotationalVelocity;

                base.TriggerSignificantMovement();
                //Tell any listeners about the new info
                // This is for animations
                base.TriggerMovementUpdate();
            }
        }
Beispiel #15
0
        /// <summary>
        /// Called from Simulate
        /// This is the avatar's movement control + PID Controller
        /// </summary>
        /// <param name="timeStep"></param>
        public void Move(float timeStep, List<AuroraODECharacter> defects)
        {
            //  no lock; for now it's only called from within Simulate()

            // If the PID Controller isn't active then we set our force
            // calculating base velocity to the current position

            if (Body == IntPtr.Zero)
                return;

            if (m_pidControllerActive == false)
            {
                _zeroPosition = d.BodyGetPosition(Body);
            }
            //PidStatus = true;

            // rex, added height check
            d.Vector3 tempPos = d.BodyGetPosition(Body);
            if (_parent_scene.m_useFlightCeilingHeight && tempPos.Z > _parent_scene.m_flightCeilingHeight)
            {
                tempPos.Z = _parent_scene.m_flightCeilingHeight;
                d.BodySetPosition(Body, tempPos.X, tempPos.Y, tempPos.Z);
                d.Vector3 tempVel = d.BodyGetLinearVel(Body);
                if (tempVel.Z > 0.0f)
                {
                    tempVel.Z = 0.0f;
                    d.BodySetLinearVel(Body, tempVel.X, tempVel.Y, tempVel.Z);
                }
                if (_target_velocity.Z > 0.0f)
                    _target_velocity.Z = 0.0f;
            }

            // endrex

            d.Vector3 localpos = d.BodyGetPosition(Body);
            Vector3 localPos = new Vector3((float)localpos.X, (float)localpos.Y, (float)localpos.Z);
            
            if (!localPos.IsFinite())
            {
                m_log.Warn("[PHYSICS]: Avatar Position is non-finite!");
                defects.Add(this);
                // _parent_scene.RemoveCharacter(this);

                // destroy avatar capsule and related ODE data
                if (Amotor != IntPtr.Zero)
                {
                    // Kill the Amotor
                    d.JointDestroy(Amotor);
                    Amotor = IntPtr.Zero;
                }

                //kill the Geometry
                _parent_scene.waitForSpaceUnlock(_parent_scene.space);

                if (Body != IntPtr.Zero)
                {
                    //kill the body
                    d.BodyDestroy(Body);

                    Body = IntPtr.Zero;
                }

                if (Shell != IntPtr.Zero)
                {
                    d.GeomDestroy(Shell);
                    _parent_scene.geom_name_map.Remove(Shell);
                    Shell = IntPtr.Zero;
                }
                return;
            }

            Vector3 vec = Vector3.Zero;
            d.Vector3 vel = d.BodyGetLinearVel(Body);

            float movementdivisor = 1f;

            if (!m_alwaysRun)
                movementdivisor = walkDivisor * _parent_scene.TimeDilation; //Dynamically adjust it for slower sims
            else
                movementdivisor = runDivisor * _parent_scene.TimeDilation; //Dynamically adjust it for slower sims
            
            //  if velocity is zero, use position control; otherwise, velocity control
            if (_target_velocity.X == 0.0f && _target_velocity.Y == 0.0f && _target_velocity.Z == 0.0f && m_iscolliding &&
                Math.Abs(vel.X) < 0.5 && Math.Abs(vel.Y) < 0.5 && Math.Abs(vel.Z) < 0.5) //This is so that if we get moved by something else, it will update us in the client
            {
                //  keep track of where we stopped.  No more slippin' & slidin'
                if (!_zeroFlag)
                {
                    _zeroFlag = true;
                    _zeroPosition = d.BodyGetPosition(Body);
                }

                if (m_pidControllerActive)
                {
                    // We only want to deactivate the PID Controller if we think we want to have our surrogate
                    // react to the physics scene by moving it's position.
                    // Avatar to Avatar collisions
                    // Prim to avatar collisions

                    d.Vector3 pos = d.BodyGetPosition(Body);
                    Vector3 velocity = new Vector3((float)vel.X, (float)vel.Y, (float)vel.Z);

                    //NOTE: THIS WILL CAUSE BENDING KNEE
                    //if (!velocity.ApproxEquals(Vector3.Zero, 0.2f))
                    //{
                        vec.X = (float)((_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2));
                        vec.Y = (float)((_target_velocity.Y - vel.Y) * (PID_D) + (_zeroPosition.Y - pos.Y) * (PID_P * 2));
                        if(!Flying)
                            vec.Z += -(_parent_scene.gravityz * 3f * m_mass);
                        //if (flying)
                        //    vec.Z = (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P;
                    //}
                }
            }
            else
            {
                m_pidControllerActive = true;
                _zeroFlag = false;
                if (m_iscolliding && !flying)
                {
                    // We're standing or walking on something
                    vec.X = (float)((_target_velocity.X / movementdivisor) - vel.X) * (PID_D);
                    vec.Y = (float)((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D);
                    //Stop pushing down if we are just standing
                    //if (_target_velocity.Z < 0)
                    //    _target_velocity.Z = 0;
                }
                else if (m_iscolliding && flying)
                {
                    // We're flying and colliding with something
                    vec.X = (float)((_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 16);
                    vec.Y = (float)((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 16);
                }
                else if (!m_iscolliding && flying)
                {
                    // we're in mid air suspended
                    vec.X = (float)((_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 6);
                    vec.Y = (float)((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 6);
                }
                if (m_iscolliding && !flying && _target_velocity.Z > 0.0f)
                {
                    // We're colliding with something and we're not flying but we're moving
                    // This means we're walking or running.
                    d.Vector3 pos = d.BodyGetPosition(Body);
                    vec.Z = (float)((_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P);
                    if (_target_velocity.X > 0)
                        vec.X = (float)((_target_velocity.X - vel.X) / 1.2f) * PID_D;
                    if (_target_velocity.Y > 0)
                        vec.Y = (float)((_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
                }
                else if (!m_iscolliding && !flying)
                {
                    // we're not colliding and we're not flying so that means we're falling!
                    // m_iscolliding includes collisions with the ground.

                    // d.Vector3 pos = d.BodyGetPosition(Body);
                    if (_target_velocity.X > 0)
                        vec.X = (float)((_target_velocity.X - vel.X) / 1.2f) * PID_D;
                    if (_target_velocity.Y > 0)
                        vec.Y = (float)((_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
                }

                if (flying)
                {
                    #region Av gravity

                    float oldVelZ = (float)vel.Z;
                    if (_parent_scene.AllowAvGravity && 
                        tempPos.Z > _parent_scene.AvGravityHeight) //Should be stop avies from flying upwards
                    {
                        //Decay going up 
                        if (_target_velocity.Z > 0)
                        {
                            //How much should we force them down?
                            float divisor = (_parent_scene.AllowAvsToEscapeGravity ? 100 : 25);
                            //How much should we force them down?
                            float fudgeHeight = (_parent_scene.AllowAvsToEscapeGravity ? 80 : 30);
                            //We add the 30 so that gravity is resonably strong once they pass the min height
                            float Multiplier = (float)(((tempPos.Z + fudgeHeight) - _parent_scene.AvGravityHeight) / divisor);

                            //Limit these so that things don't go wrong
                            if (Multiplier < 1)
                                Multiplier = 1;

                            float maxpower = (_parent_scene.AllowAvsToEscapeGravity ? 1.5f : 3);

                            if (Multiplier > maxpower)
                                Multiplier = maxpower;
                            _target_velocity.Z /= Multiplier;
                            oldVelZ /= Multiplier;
                        }
                    }

                    vec.Z = (_target_velocity.Z - oldVelZ) * (PID_D);
                    if (_parent_scene.AllowAvGravity && tempPos.Z > _parent_scene.AvGravityHeight)
                        //Add extra gravity
                        vec.Z += ((25 * _parent_scene.gravityz) * Mass);

                    #endregion
                }
            }
            if (flying)
            {
                //Fix grav when flying
                if (!_parent_scene.AllowAvGravity ||
                    (_parent_scene.AllowAvGravity && tempPos.Z < _parent_scene.AvGravityHeight))
                {
                    //Cancel out gravity if we are flying
                    vec.X += _parent_scene.gravityx * -3f * m_mass;
                    vec.Y += _parent_scene.gravityy * -3f * m_mass;
                    vec.Z += _parent_scene.gravityz * -3f * m_mass;
                }

                #region Auto Fly Height

                //Added for auto fly height. Kitto Flora
                //Changed to only check if the avatar is flying around,

                // Revolution: If the avatar is going down, they are trying to land (probably), so don't push them up to make it harder
                //   Only if they are moving around sideways do we need to push them up
                if (_target_velocity.X != 0 || _target_velocity.Y != 0)
                {
                    Vector3 forwardVel = new Vector3(_target_velocity.X > 0 ? 2 : (_target_velocity.X < 0 ? -2 : 0),
                        _target_velocity.Y > 0 ? 2 : (_target_velocity.Y < 0 ? -2 : 0),
                        0);
                    float target_altitude = _parent_scene.GetTerrainHeightAtXY(_position.X, _position.Y) + MinimumGroundFlightOffset;

                    //We cheat a bit and do a bit lower than normal
                    if ((_position.Z - CAPSULE_LENGTH) < target_altitude)
                        vec.Z += (target_altitude - _position.Z) * PID_D;
                    //Check in the direction we are going as well
                    target_altitude = _parent_scene.GetTerrainHeightAtXY(_position.X + forwardVel.X, _position.Y + forwardVel.Y) + MinimumGroundFlightOffset;
                    if ((_position.Z - CAPSULE_LENGTH) < target_altitude)
                        vec.Z += (target_altitude - _position.Z) * PID_D / 2;
                }
                else
                {
                    //Straight up and down, only apply when they are very close to the ground
                    float target_altitude = _parent_scene.GetTerrainHeightAtXY(_position.X, _position.Y);

                    if ((_position.Z - CAPSULE_LENGTH + (MinimumGroundFlightOffset / 1.5)) < target_altitude + MinimumGroundFlightOffset)
                    {
                        if ((_position.Z - CAPSULE_LENGTH) < target_altitude + 1)
                        {
                            vec.Z += ((target_altitude+4) - (_position.Z - CAPSULE_LENGTH)) * PID_D;
                        }
                        else
                            vec.Z += ((target_altitude + MinimumGroundFlightOffset) - (_position.Z - CAPSULE_LENGTH)) * PID_D / 2;
                    }
                }

                #endregion
            }

            #region Gravity

            //The '3' is since the gravity isn't exactly what people would expect... maybe should be a config option someday
            if (!_parent_scene.UsePointGravity)
            {
                //Add normal gravity
                vec.X += _parent_scene.gravityx * 3f * m_mass;
                vec.Y += _parent_scene.gravityy * 3f * m_mass;
                vec.Z += _parent_scene.gravityz * 3f * m_mass;
            }
            else
            {
                Vector3 cog = _parent_scene.PointOfGravity;
                if (cog.X != 0)
                    vec.X += (cog.X - Position.X) * m_mass;
                if (cog.Y != 0)
                    vec.Y += (cog.Y - Position.Y) * m_mass;
                if (cog.Z != 0)
                    vec.Z += (cog.Z - Position.Z) * m_mass;
            }

            #endregion

            #region Under water physics

            if (_parent_scene.AllowUnderwaterPhysics)
            {
                //Position plus height to av's shoulder (aprox) is just above water
                if ((_position.Z + (CAPSULE_LENGTH / 3) - .25f) < _parent_scene.waterlevel)
                {
                    if (StartingUnderWater)
                        ShouldBeWalking = Flying == false;
                    StartingUnderWater = false;
                    WasUnderWater = true;
                    Flying = true;
                    lastUnderwaterPush = 0;
                    if (ShouldBeWalking)
                    {
                        lastUnderwaterPush += (_parent_scene.waterlevel - _position.Z) * 100 + 10;
                        vec.Z += lastUnderwaterPush;
                    }
                    else
                    {
                        lastUnderwaterPush += 8000;
                        lastUnderwaterPush += (_parent_scene.waterlevel - _position.Z) * 25;
                        vec.Z += lastUnderwaterPush;
                    }
                }
                else
                {
                    StartingUnderWater = true;
                    if (WasUnderWater)
                    {
                        WasUnderWater = false;
                        Flying = true;
                    }
                }
            }

            #endregion

            #region Check for underground

            if (!flying || (flying && _target_velocity.X == 0 || _target_velocity.Y == 0)) //Don't duplicate the ground check for flying from above, it will already have given us a good shove
            {
                if (m_WaitGroundCheck >= 10 && vel.Z != 0)
                {
                    float groundHeight = _parent_scene.GetTerrainHeightAtXY(_position.X, _position.Y);
                    if (_position.Z - (CAPSULE_LENGTH / 2) < groundHeight)
                        vec.Z += ((groundHeight - (_position.Z - (CAPSULE_LENGTH / 2))) * 100);
                    m_WaitGroundCheck = -1;
                }
                m_WaitGroundCheck++;
            }

            #endregion

            if (vec.IsFinite())
            {
                if (vec.X < 100000 && vec.Y < 100000 && vec.Z < 100000) //Checks for crazy, going to NaN us values
                {
                    //Stop us from fidgiting if we have a small velocity
                    if (Math.Abs(vec.X) < 0.05 && Math.Abs(vec.Y) < 0.05 && Math.Abs(vec.Z) < 0.05)
                    {
                        vec = new Vector3(0, 0, 0);
                        d.BodySetLinearVel(Body, 0, 0, 0);
                    }

                    //Reduce insanely small values to 0
                    if (Math.Abs(vec.Z) < 0.01)
                        vec.Z = 0;

                    doForce(vec);

                    //When falling, we keep going faster and faster, and eventually, the client blue screens (blue is all you see).
                    // The speed that does this is slightly higher than -30, so we cap it here so we never do that during falling.
                    if (vel.Z < -30)
                    {
                        vel.Z = -30;
                        d.BodySetLinearVel(Body, vel.X, vel.Y, vel.Z);
                    }

                    //Check if the capsule is tilted before changing it
                    if (!_zeroFlag && !_parent_scene.IsAvCapsuleTilted)
                        AlignAvatarTiltWithCurrentDirectionOfMovement(vec);
                }
                else
                {
                    //This is a safe guard from going NaN, but it isn't very smooth... which is ok
                    d.BodySetForce(Body, 0, 0, 0);
                    d.BodySetLinearVel(Body, 0, 0, 0);
                }
            }
            else
            {
                m_log.Warn("[PHYSICS]: Got a NaN force vector in Move()");
                m_log.Warn("[PHYSICS]: Avatar Position is non-finite!");
                defects.Add(this);
                // _parent_scene.RemoveCharacter(this);
                // destroy avatar capsule and related ODE data
                if (Amotor != IntPtr.Zero)
                {
                    // Kill the Amotor
                    d.JointDestroy(Amotor);
                    Amotor = IntPtr.Zero;
                }
                //kill the Geometry
                _parent_scene.waitForSpaceUnlock(_parent_scene.space);

                if (Body != IntPtr.Zero)
                {
                    //kill the body
                    d.BodyDestroy(Body);

                    Body = IntPtr.Zero;
                }

                if (Shell != IntPtr.Zero)
                {
                    d.GeomDestroy(Shell);
                    _parent_scene.geom_name_map.Remove(Shell);
                    Shell = IntPtr.Zero;
                }
            }
        }
Beispiel #16
0
        /// <summary>
        /// Called from Simulate
        /// This is the avatar's movement control + PID Controller
        /// </summary>
        /// <param name="timeStep"></param>
        public void Move(float timeStep)
        {
            //  no lock; for now it's only called from within Simulate()

            // If the PID Controller isn't active then we set our force
            // calculating base velocity to the current position

            if (Body == IntPtr.Zero)
            {
                return;
            }

            if (m_pidControllerActive == false)
            {
                _zeroPosition = d.BodyGetPosition(Body);
            }
            //PidStatus = true;

            d.Vector3     localpos = d.BodyGetPosition(Body);
            PhysicsVector localPos = new PhysicsVector(localpos.X, localpos.Y, localpos.Z);

            if (!PhysicsVector.isFinite(localPos))
            {
                m_log.Warn("[PHYSICS]: Avatar Position is non-finite!");
                _parent_scene.RemoveCharacter(this);
                // destroy avatar capsule and related ODE data
                if (Amotor != IntPtr.Zero)
                {
                    // Kill the Amotor
                    d.JointDestroy(Amotor);
                    Amotor = IntPtr.Zero;
                }
                //kill the Geometry
                _parent_scene.waitForSpaceUnlock(_parent_scene.space);

                if (Body != IntPtr.Zero)
                {
                    //kill the body
                    d.BodyDestroy(Body);

                    Body = IntPtr.Zero;
                }

                if (Shell != IntPtr.Zero)
                {
                    d.GeomDestroy(Shell);
                    _parent_scene.geom_name_map.Remove(Shell);
                    Shell = IntPtr.Zero;
                }

                return;
            }

            PhysicsVector vec = new PhysicsVector();

            d.Vector3 vel             = d.BodyGetLinearVel(Body);
            float     movementdivisor = 1f;

            if (!m_alwaysRun)
            {
                movementdivisor = walkDivisor;
            }
            else
            {
                movementdivisor = runDivisor;
            }

            //  if velocity is zero, use position control; otherwise, velocity control
            if (_target_velocity.X == 0.0f && _target_velocity.Y == 0.0f && _target_velocity.Z == 0.0f && m_iscolliding)
            {
                //  keep track of where we stopped.  No more slippin' & slidin'
                if (!_zeroFlag)
                {
                    _zeroFlag     = true;
                    _zeroPosition = d.BodyGetPosition(Body);
                }
                if (m_pidControllerActive)
                {
                    // We only want to deactivate the PID Controller if we think we want to have our surrogate
                    // react to the physics scene by moving it's position.
                    // Avatar to Avatar collisions
                    // Prim to avatar collisions

                    d.Vector3 pos = d.BodyGetPosition(Body);
                    vec.X = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2);
                    vec.Y = (_target_velocity.Y - vel.Y) * (PID_D) + (_zeroPosition.Y - pos.Y) * (PID_P * 2);
                    if (flying)
                    {
                        vec.Z = (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P;
                    }
                }
                //PidStatus = true;
            }
            else
            {
                m_pidControllerActive = true;
                _zeroFlag             = false;
                if (m_iscolliding && !flying)
                {
                    // We're standing on something
                    vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D);
                    vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D);
                }
                else if (m_iscolliding && flying)
                {
                    // We're flying and colliding with something
                    vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 16);
                    vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 16);
                }
                else if (!m_iscolliding && flying)
                {
                    // we're in mid air suspended
                    vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 6);
                    vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 6);
                }

                if (m_iscolliding && !flying && _target_velocity.Z > 0.0f)
                {
                    // We're colliding with something and we're not flying but we're moving
                    // This means we're walking or running.
                    d.Vector3 pos = d.BodyGetPosition(Body);
                    vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P;
                    if (_target_velocity.X > 0)
                    {
                        vec.X = ((_target_velocity.X - vel.X) / 1.2f) * PID_D;
                    }
                    if (_target_velocity.Y > 0)
                    {
                        vec.Y = ((_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
                    }
                }
                else if (!m_iscolliding && !flying)
                {
                    // we're not colliding and we're not flying so that means we're falling!
                    // m_iscolliding includes collisions with the ground.

                    // d.Vector3 pos = d.BodyGetPosition(Body);
                    if (_target_velocity.X > 0)
                    {
                        vec.X = ((_target_velocity.X - vel.X) / 1.2f) * PID_D;
                    }
                    if (_target_velocity.Y > 0)
                    {
                        vec.Y = ((_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
                    }
                }


                if (flying)
                {
                    vec.Z = (_target_velocity.Z - vel.Z) * (PID_D);
                }
            }
            if (flying)
            {
                vec.Z += ((-1 * _parent_scene.gravityz) * m_mass);

                //Added for auto fly height. Kitto Flora
                //d.Vector3 pos = d.BodyGetPosition(Body);
                float target_altitude = _parent_scene.GetTerrainHeightAtXY(_position.X, _position.Y) + MinimumGroundFlightOffset;

                if (_position.Z < target_altitude)
                {
                    vec.Z += (target_altitude - _position.Z) * PID_P * 5.0f;
                }
                // end add Kitto Flora
            }
            if (PhysicsVector.isFinite(vec))
            {
                doForce(vec);
            }
            else
            {
                m_log.Warn("[PHYSICS]: Got a NaN force vector in Move()");
                m_log.Warn("[PHYSICS]: Avatar Position is non-finite!");
                _parent_scene.RemoveCharacter(this);
                // destroy avatar capsule and related ODE data
                if (Amotor != IntPtr.Zero)
                {
                    // Kill the Amotor
                    d.JointDestroy(Amotor);
                    Amotor = IntPtr.Zero;
                }
                //kill the Geometry
                _parent_scene.waitForSpaceUnlock(_parent_scene.space);

                if (Body != IntPtr.Zero)
                {
                    //kill the body
                    d.BodyDestroy(Body);

                    Body = IntPtr.Zero;
                }

                if (Shell != IntPtr.Zero)
                {
                    d.GeomDestroy(Shell);
                    _parent_scene.geom_name_map.Remove(Shell);
                    Shell = IntPtr.Zero;
                }

                return;
            }
        }
Beispiel #17
0
        /// <summary>
        /// Updates the reported position and velocity.  This essentially sends the data up to ScenePresence.
        /// </summary>
        public void UpdatePositionAndVelocity()
        {
            //  no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
            d.Vector3 vec;
            try
            {
                vec = d.BodyGetPosition(Body);
            }
            catch (NullReferenceException)
            {
                bad = true;
                _parent_scene.BadCharacter(this);
                vec = new d.Vector3(_position.X, _position.Y, _position.Z);
                base.RaiseOutOfBounds(_position); // Tells ScenePresence that there's a problem!
                m_log.WarnFormat("[ODEPLUGIN]: Avatar Null reference for Avatar {0}, physical actor {1}", m_name, m_uuid);
            }
            

            //  kluge to keep things in bounds.  ODE lets dead avatars drift away (they should be removed!)
            if (vec.X < 0.0f) vec.X = 0.0f;
            if (vec.Y < 0.0f) vec.Y = 0.0f;
            if (vec.X > (int)_parent_scene.WorldExtents.X - 0.05f) vec.X = (int)_parent_scene.WorldExtents.X - 0.05f;
            if (vec.Y > (int)_parent_scene.WorldExtents.Y - 0.05f) vec.Y = (int)_parent_scene.WorldExtents.Y - 0.05f;

            _position.X = (float)vec.X;
            _position.Y = (float)vec.Y;
            _position.Z = (float)vec.Z;

            // Did we move last? = zeroflag
            // This helps keep us from sliding all over

            if (_zeroFlag)
            {
                /*if (CollisionEventsThisFrame != null)
                {
                    base.SendCollisionUpdate(CollisionEventsThisFrame);
                }
                CollisionEventsThisFrame = new CollisionEventUpdate();
                m_eventsubscription = 0;*/
                _velocity.X = 0.0f;
                _velocity.Y = 0.0f;
                _velocity.Z = 0.0f;

                // Did we send out the 'stopped' message?
                if (!m_lastUpdateSent)
                {
                    m_lastUpdateSent = true;
                    //base.RequestPhysicsterseUpdate();
                }
            }
            else
            {
                m_lastUpdateSent = false;
                try
                {
                    vec = d.BodyGetLinearVel(Body);
                }
                catch (NullReferenceException)
                {
                    vec.X = _velocity.X;
                    vec.Y = _velocity.Y;
                    vec.Z = _velocity.Z;
                }
                _velocity.X = (float)(vec.X);
                _velocity.Y = (float)(vec.Y);

                _velocity.Z = (float)(vec.Z);

                if (_velocity.Z < -6 && !m_hackSentFall)
                {
                    //m_hackSentFall = true;
                    //m_pidControllerActive = false;
                }
                else if (flying && !m_hackSentFly)
                {
                    //m_hackSentFly = true;
                    //base.SendCollisionUpdate(new CollisionEventUpdate());
                }
                else
                {
                    m_hackSentFly = false;
                    m_hackSentFall = false;
                }
            }
        }
Beispiel #18
0
 public static extern void SetViewpoint(ref d.Vector3 xyz, ref d.Vector3 hpr);
Beispiel #19
0
        /// <summary>
        /// Called from Simulate
        /// This is the avatar's movement control + PID Controller
        /// </summary>
        /// <param name="defects">The character will be added to this list if there is something wrong (non-finite
        /// position or velocity).
        /// </param>
        internal void Move(List<OdeCharacter> defects)
        {
            //  no lock; for now it's only called from within Simulate()
            
            // If the PID Controller isn't active then we set our force
            // calculating base velocity to the current position

            if (Body == IntPtr.Zero)
                return;

            if (m_pidControllerActive == false)
            {
                _zeroPosition = d.BodyGetPosition(Body);
            }
            //PidStatus = true;

            d.Vector3 localpos = d.BodyGetPosition(Body);
            Vector3 localPos = new Vector3(localpos.X, localpos.Y, localpos.Z);
            
            if (!localPos.IsFinite())
            {
                m_log.WarnFormat(
                    "[ODE CHARACTER]: Avatar position of {0} for {1} is non-finite!  Removing from physics scene.",
                    localPos, Name);

                defects.Add(this);

                return;
            }

            Vector3 vec = Vector3.Zero;
            d.Vector3 vel = d.BodyGetLinearVel(Body);

//            m_log.DebugFormat(
//                "[ODE CHARACTER]: Current velocity in Move() is <{0},{1},{2}>, target {3} for {4}",
//                vel.X, vel.Y, vel.Z, _target_velocity, Name);

            float movementdivisor = 1f;

            if (!m_alwaysRun)
            {
                movementdivisor = walkDivisor;
            }
            else
            {
                movementdivisor = runDivisor;
            }

            //  if velocity is zero, use position control; otherwise, velocity control
            if (_target_velocity.X == 0.0f && _target_velocity.Y == 0.0f && _target_velocity.Z == 0.0f && m_iscolliding)
            {
                //  keep track of where we stopped.  No more slippin' & slidin'
                if (!_zeroFlag)
                {
                    _zeroFlag = true;
                    _zeroPosition = d.BodyGetPosition(Body);
                }

                if (m_pidControllerActive)
                {
                    // We only want to deactivate the PID Controller if we think we want to have our surrogate
                    // react to the physics scene by moving it's position.
                    // Avatar to Avatar collisions
                    // Prim to avatar collisions

                    d.Vector3 pos = d.BodyGetPosition(Body);
                    vec.X = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2);
                    vec.Y = (_target_velocity.Y - vel.Y) * (PID_D) + (_zeroPosition.Y - pos.Y)* (PID_P * 2);
                    if (flying)
                    {
                        vec.Z = (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P;
                    }
                }
                //PidStatus = true;
            }
            else
            {
                m_pidControllerActive = true;
                _zeroFlag = false;
                if (m_iscolliding && !flying)
                {
                    // We're standing on something
                    vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D);
                    vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D);
                }
                else if (m_iscolliding && flying)
                {
                    // We're flying and colliding with something
                    vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 16);
                    vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 16);
                }
                else if (!m_iscolliding && flying)
                {
                    // we're in mid air suspended
                    vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 6);
                    vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 6);

//                    m_log.DebugFormat(
//                        "[ODE CHARACTER]: !m_iscolliding && flying, vec {0}, _target_velocity {1}, movementdivisor {2}, vel {3}",
//                        vec, _target_velocity, movementdivisor, vel);
                }

                if (flying)
                {
                    // This also acts as anti-gravity so that we hover when flying rather than fall.
                    vec.Z = (_target_velocity.Z - vel.Z) * (PID_D);
                }
                else
                {
                    if (m_iscolliding && _target_velocity.Z > 0.0f)
                    {
                        // We're colliding with something and we're not flying but we're moving
                        // This means we're walking or running.
                        d.Vector3 pos = d.BodyGetPosition(Body);
                        vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P;
                        vec.X = ((_target_velocity.X - vel.X) / 1.2f) * PID_D;
                        vec.Y = ((_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
                    }
                    else if (!m_iscolliding)
                    {
                        // we're not colliding and we're not flying so that means we're falling!
                        // m_iscolliding includes collisions with the ground.
                        vec.X = ((_target_velocity.X - vel.X) / 1.2f) * PID_D;
                        vec.Y = ((_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
                    }
                }
            }

            if (flying)
            {
                // Anti-gravity so that we hover when flying rather than fall.
                vec.Z += ((-1 * _parent_scene.gravityz) * m_mass);

                //Added for auto fly height. Kitto Flora
                //d.Vector3 pos = d.BodyGetPosition(Body);
                float target_altitude = _parent_scene.GetTerrainHeightAtXY(_position.X, _position.Y) + MinimumGroundFlightOffset;

                if (_position.Z < target_altitude)
                {
                    vec.Z += (target_altitude - _position.Z) * PID_P * 5.0f;
                }
                // end add Kitto Flora
            }

            if (vec.IsFinite())
            {
                // Apply the total force acting on this avatar
                d.BodyAddForce(Body, vec.X, vec.Y, vec.Z);

                if (!_zeroFlag)
                    AlignAvatarTiltWithCurrentDirectionOfMovement(vec);
            }
            else
            {
                m_log.WarnFormat(
                    "[ODE CHARACTER]: Got a NaN force vector {0} in Move() for {1}.  Removing character from physics scene.",
                    vec, Name);

                defects.Add(this);

                return;
            }

            d.Vector3 newVel = d.BodyGetLinearVel(Body);
            if (newVel.X >= 256 || newVel.X <= 256 || newVel.Y >= 256 || newVel.Y <= 256 || newVel.Z >= 256 || newVel.Z <= 256)
            {
//                m_log.DebugFormat(
//                    "[ODE CHARACTER]: Limiting falling velocity from {0} to {1} for {2}", newVel.Z, -9.8, Name);

                newVel.X = Util.Clamp<float>(newVel.X, -255f, 255f);
                newVel.Y = Util.Clamp<float>(newVel.Y, -255f, 255f);

                if (!flying)
                    newVel.Z
                        = Util.Clamp<float>(
                            newVel.Z, -_parent_scene.AvatarTerminalVelocity, _parent_scene.AvatarTerminalVelocity);
                else
                    newVel.Z = Util.Clamp<float>(newVel.Z, -255f, 255f);

                d.BodySetLinearVel(Body, newVel.X, newVel.Y, newVel.Z);
            }
        }
Beispiel #20
0
        /// <summary>
        /// Called from Simulate
        /// This is the avatar's movement control + PID Controller
        /// </summary>
        /// <param name="defects">The character will be added to this list if there is something wrong (non-finite
        /// position or velocity).
        /// </param>
        internal void Move(List <OdeCharacter> defects)
        {
            //  no lock; for now it's only called from within Simulate()

            // If the PID Controller isn't active then we set our force
            // calculating base velocity to the current position

            if (Body == IntPtr.Zero)
            {
                return;
            }

            if (m_pidControllerActive == false)
            {
                _zeroPosition = d.BodyGetPosition(Body);
            }
            //PidStatus = true;

            d.Vector3 localpos = d.BodyGetPosition(Body);
            Vector3   localPos = new Vector3(localpos.X, localpos.Y, localpos.Z);

            if (!localPos.IsFinite())
            {
                m_log.WarnFormat(
                    "[ODE CHARACTER]: Avatar position of {0} for {1} is non-finite!  Removing from physics scene.",
                    localPos, Name);

                defects.Add(this);

                return;
            }

            Vector3 vec = Vector3.Zero;

            d.Vector3 vel = d.BodyGetLinearVel(Body);

            float movementdivisor = 1f;

            if (!m_alwaysRun)
            {
                movementdivisor = walkDivisor;
            }
            else
            {
                movementdivisor = runDivisor;
            }

            //  if velocity is zero, use position control; otherwise, velocity control
            if (_target_velocity.X == 0.0f && _target_velocity.Y == 0.0f && _target_velocity.Z == 0.0f && m_iscolliding)
            {
                //  keep track of where we stopped.  No more slippin' & slidin'
                if (!_zeroFlag)
                {
                    _zeroFlag     = true;
                    _zeroPosition = d.BodyGetPosition(Body);
                }

                if (m_pidControllerActive)
                {
                    // We only want to deactivate the PID Controller if we think we want to have our surrogate
                    // react to the physics scene by moving it's position.
                    // Avatar to Avatar collisions
                    // Prim to avatar collisions

                    d.Vector3 pos = d.BodyGetPosition(Body);
                    vec.X = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2);
                    vec.Y = (_target_velocity.Y - vel.Y) * (PID_D) + (_zeroPosition.Y - pos.Y) * (PID_P * 2);
                    if (flying)
                    {
                        vec.Z = (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P;
                    }
                }
                //PidStatus = true;
            }
            else
            {
                m_pidControllerActive = true;
                _zeroFlag             = false;
                if (m_iscolliding && !flying)
                {
                    // We're standing on something
                    vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D);
                    vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D);
                }
                else if (m_iscolliding && flying)
                {
                    // We're flying and colliding with something
                    vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 16);
                    vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 16);
                }
                else if (!m_iscolliding && flying)
                {
                    // we're in mid air suspended
                    vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 6);
                    vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 6);

//                    m_log.DebugFormat(
//                        "[ODE CHARACTER]: !m_iscolliding && flying, vec {0}, _target_velocity {1}, movementdivisor {2}, vel {3}",
//                        vec, _target_velocity, movementdivisor, vel);
                }

                if (m_iscolliding && !flying && _target_velocity.Z > 0.0f)
                {
                    // We're colliding with something and we're not flying but we're moving
                    // This means we're walking or running.
                    d.Vector3 pos = d.BodyGetPosition(Body);
                    vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P;
                    if (_target_velocity.X > 0)
                    {
                        vec.X = ((_target_velocity.X - vel.X) / 1.2f) * PID_D;
                    }
                    if (_target_velocity.Y > 0)
                    {
                        vec.Y = ((_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
                    }
                }
                else if (!m_iscolliding && !flying)
                {
                    // we're not colliding and we're not flying so that means we're falling!
                    // m_iscolliding includes collisions with the ground.

                    // d.Vector3 pos = d.BodyGetPosition(Body);
                    if (_target_velocity.X > 0)
                    {
                        vec.X = ((_target_velocity.X - vel.X) / 1.2f) * PID_D;
                    }
                    if (_target_velocity.Y > 0)
                    {
                        vec.Y = ((_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
                    }
                }

                if (flying)
                {
                    vec.Z = (_target_velocity.Z - vel.Z) * (PID_D);
                }
            }

            if (flying)
            {
                vec.Z += ((-1 * _parent_scene.gravityz) * m_mass);

                //Added for auto fly height. Kitto Flora
                //d.Vector3 pos = d.BodyGetPosition(Body);
                float target_altitude = _parent_scene.GetTerrainHeightAtXY(_position.X, _position.Y) + MinimumGroundFlightOffset;

                if (_position.Z < target_altitude)
                {
                    vec.Z += (target_altitude - _position.Z) * PID_P * 5.0f;
                }
                // end add Kitto Flora
            }

            if (vec.IsFinite())
            {
                // Apply the total force acting on this avatar
                d.BodyAddForce(Body, vec.X, vec.Y, vec.Z);

                if (!_zeroFlag)
                {
                    AlignAvatarTiltWithCurrentDirectionOfMovement(vec);
                }
            }
            else
            {
                m_log.WarnFormat(
                    "[ODE CHARACTER]: Got a NaN force vector {0} in Move() for {1}.  Removing character from physics scene.",
                    vec, Name);

                defects.Add(this);

                return;
            }
        }
Beispiel #21
0
 internal void Stop()
 {
     m_lastLinearVelocityVector = Vector3.Zero;
     m_lastAngularVelocity      = Vector3.Zero;
     m_lastPositionVector       = d.BodyGetPosition(Body);
 }
Beispiel #22
0
        /// <summary>
        /// Updates the reported position and velocity.  This essentially sends the data up to ScenePresence.
        /// </summary>
        /// <param name="defects">The character will be added to this list if there is something wrong (non-finite
        /// position or velocity).
        /// </param>
        internal void UpdatePositionAndVelocity(List <OdeCharacter> defects)
        {
            //  no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
            d.Vector3 newPos;
            try
            {
                newPos = d.BodyGetPosition(Body);
            }
            catch (NullReferenceException)
            {
                bad = true;
                defects.Add(this);
                newPos = new d.Vector3(_position.X, _position.Y, _position.Z);
                base.RaiseOutOfBounds(_position); // Tells ScenePresence that there's a problem!
                m_log.WarnFormat("[ODE CHARACTER]: Avatar Null reference for Avatar {0}, physical actor {1}", Name, m_uuid);

                return;
            }

            //  kluge to keep things in bounds.  ODE lets dead avatars drift away (they should be removed!)
            if (newPos.X < 0.0f)
            {
                newPos.X = 0.0f;
            }
            if (newPos.Y < 0.0f)
            {
                newPos.Y = 0.0f;
            }
            if (newPos.X > (int)_parent_scene.WorldExtents.X - 0.05f)
            {
                newPos.X = (int)_parent_scene.WorldExtents.X - 0.05f;
            }
            if (newPos.Y > (int)_parent_scene.WorldExtents.Y - 0.05f)
            {
                newPos.Y = (int)_parent_scene.WorldExtents.Y - 0.05f;
            }

            _position.X = newPos.X;
            _position.Y = newPos.Y;
            _position.Z = newPos.Z;

            // I think we need to update the taintPosition too -- Diva 12/24/10
            m_taintPosition = _position;

            // Did we move last? = zeroflag
            // This helps keep us from sliding all over

            if (_zeroFlag)
            {
                _velocity = Vector3.Zero;

                // Did we send out the 'stopped' message?
                if (!m_lastUpdateSent)
                {
                    m_lastUpdateSent = true;
                    //base.RequestPhysicsterseUpdate();
                }
            }
            else
            {
                m_lastUpdateSent = false;
                d.Vector3 newVelocity;

                try
                {
                    newVelocity = d.BodyGetLinearVel(Body);
                }
                catch (NullReferenceException)
                {
                    newVelocity.X = _velocity.X;
                    newVelocity.Y = _velocity.Y;
                    newVelocity.Z = _velocity.Z;
                }

                _velocity.X = newVelocity.X;
                _velocity.Y = newVelocity.Y;
                _velocity.Z = newVelocity.Z;

                if (_velocity.Z < -6 && !m_hackSentFall)
                {
                    m_hackSentFall        = true;
                    m_pidControllerActive = false;
                }
                else if (flying && !m_hackSentFly)
                {
                    //m_hackSentFly = true;
                    //base.SendCollisionUpdate(new CollisionEventUpdate());
                }
                else
                {
                    m_hackSentFly  = false;
                    m_hackSentFall = false;
                }
            }
        }
Beispiel #23
0
        /// <summary>
        /// Updates the reported position and velocity.  This essentially sends the data up to ScenePresence.
        /// </summary>
        public void UpdatePositionAndVelocity(float timestep)
        {
            if (!m_shouldBePhysical)
                return;

            //  no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
            d.Vector3 vec;
            try
            {
                vec = d.BodyGetPosition(Body);
            }
            catch (NullReferenceException)
            {
                bad = true;
                _parent_scene.BadCharacter(this);
                vec = new d.Vector3(_position.X, _position.Y, _position.Z);
                base.RaiseOutOfBounds(_position); // Tells ScenePresence that there's a problem!
                m_log.WarnFormat("[ODEPLUGIN]: Avatar Null reference for Avatar {0}, physical actor {1}", m_name, m_uuid);
            }

            // vec is a ptr into internal ode data better not mess with it

            _position.X = (float)vec.X;
            _position.Y = (float)vec.Y;
            _position.Z = (float)vec.Z;

            //  kluge to keep things in bounds.  ODE lets dead avatars drift away (they should be removed!)

            bool needfixbody = false;

            /*if (_position.X < 0.0f)
            {
                needfixbody = true;
                _position.X = 0.1f;
            }
            else if (_position.X > (int)_parent_scene.Region.RegionSizeX - 0.1f)
            {
                needfixbody = true;
                _position.X = (int)_parent_scene.Region.RegionSizeX - 0.1f;
            }

            if (_position.Y < 0.0f)
            {
                needfixbody = true;
                _position.Y = 0.1f;
            }
            else if (_position.Y > (int)_parent_scene.Region.RegionSizeY - 0.1)
            {
                needfixbody = true;
                _position.Y = (int)_parent_scene.Region.RegionSizeY - 0.1f;
            }*/

            if (needfixbody)
                d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);

            try
            {
                vec = d.BodyGetLinearVel(Body);
            }
            catch (NullReferenceException)
            {
                vec.X = _velocity.X;
                vec.Y = _velocity.Y;
                vec.Z = _velocity.Z;
            }


            // vec is a ptr into internal ode data better not mess with it

            _velocity.X = vec.X;
            _velocity.Y = vec.Y;
            _velocity.Z = vec.Z;

            bool VelIsZero = false;
            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)
                VelIsZero = true;

            // slow down updates
            m_UpdateTimecntr += timestep;
            if (m_UpdateTimecntr < m_UpdateFPScntr)
                return;

            m_UpdateTimecntr = 0;

            const float VELOCITY_TOLERANCE = 0.01f;
            const float POSITION_TOLERANCE = 0.05f;
            bool needSendUpdate = false;

            //Check to see whether we need to trigger the significant movement method in the presence
            // avas don't rotate for now                if (!RotationalVelocity.ApproxEquals(m_lastRotationalVelocity, VELOCITY_TOLERANCE) ||
            // but simulator does not process rotation changes
            if (//!VelIsZero &&
                //                   (!Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) ||
                (
                (Math.Abs(Velocity.X - m_lastVelocity.X) > VELOCITY_TOLERANCE) ||
                (Math.Abs(Velocity.Y - m_lastVelocity.Y) > VELOCITY_TOLERANCE) ||
                (Math.Abs(Velocity.Z - m_lastVelocity.Z) > VELOCITY_TOLERANCE) ||
                (Math.Abs(_position.X - m_lastPosition.X) > POSITION_TOLERANCE) ||
                (Math.Abs(_position.Y - m_lastPosition.Y) > POSITION_TOLERANCE) ||
                (Math.Abs(_position.Z - m_lastPosition.Z) > POSITION_TOLERANCE)// ||
                //                    (Math.Abs(_lastorientation.X - _orientation.X) > 0.001) ||
                //                    (Math.Abs(_lastorientation.Y - _orientation.Y) > 0.001) ||
                //                    (Math.Abs(_lastorientation.Z - _orientation.Z) > 0.001) ||
                //                    (Math.Abs(_lastorientation.W - _orientation.W) > 0.001)
                ))
            {
                // Update the "last" values
                needSendUpdate = true;
                m_ZeroUpdateSent = false;
                m_lastPosition = _position;
                //                        m_lastRotationalVelocity = RotationalVelocity;
                m_lastVelocity = Velocity;
                //                            _lastorientation = Orientation;
                //                        base.RequestPhysicsterseUpdate();
                //                        base.TriggerSignificantMovement();
            }
            else if (VelIsZero)
            {
                if (!m_ZeroUpdateSent)
                {
                    needSendUpdate = true;
                    m_ZeroUpdateSent = true;
                }
            }

            if (needSendUpdate)
            {
                base.RequestPhysicsterseUpdate();
                base.TriggerSignificantMovement();
            }

            //Tell any listeners about the new info
            // This is for animations
            base.TriggerMovementUpdate ();
        }
Beispiel #24
0
        /// <summary>
        /// Updates the reported position and velocity.  This essentially sends the data up to ScenePresence.
        /// </summary>
        public void UpdatePositionAndVelocity (float timestep)
        {
            if(!m_shouldBePhysical)
                return;

            //  no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
            d.Vector3 vec;
            try
            {
                vec = d.BodyGetPosition(Body);
            }
            catch(NullReferenceException)
            {
                bad = true;
                _parent_scene.BadCharacter(this);
                vec = new d.Vector3(_position.X, _position.Y, _position.Z);
                base.RaiseOutOfBounds(_position); // Tells ScenePresence that there's a problem!
                m_log.WarnFormat("[ODEPLUGIN]: Avatar Null reference for Avatar {0}, physical actor {1}", m_name, m_uuid);
            }

            // vec is a ptr into internal ode data better not mess with it
            
            _position.X = (float)vec.X;
            _position.Y = (float)vec.Y;
            _position.Z = (float)vec.Z;

            if (!IsFinite(_position))
            {
                _parent_scene.BadCharacter(this);
                base.RaiseOutOfBounds(_position); // Tells ScenePresence that there's a problem!
                return;
            }

            try
            {
                vec = d.BodyGetLinearVel(Body);
            }
            catch(NullReferenceException)
            {
                vec.X = _velocity.X;
                vec.Y = _velocity.Y;
                vec.Z = _velocity.Z;
            }

            d.Vector3 rvec;
            try
            {
                rvec = d.BodyGetAngularVel(Body);
            }
            catch(NullReferenceException)
            {
                rvec.X = m_rotationalVelocity.X;
                rvec.Y = m_rotationalVelocity.Y;
                rvec.Z = m_rotationalVelocity.Z;
            }

            m_rotationalVelocity.X = rvec.X;
            m_rotationalVelocity.Y = rvec.Y;
            m_rotationalVelocity.Z = rvec.Z;

            // vec is a ptr into internal ode data better not mess with it

            _velocity.X = vec.X;
            _velocity.Y = vec.Y;
            _velocity.Z = vec.Z;
            if (!IsFinite(_velocity))
            {
                _parent_scene.BadCharacter(this);
                base.RaiseOutOfBounds(_position); // Tells ScenePresence that there's a problem!
                return;
            }

            bool VelIsZero = false;
            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)
                VelIsZero = true;

            // slow down updates
            m_UpdateTimecntr += timestep;
            m_UpdateFPScntr = 2.5f * _parent_scene.StepTime * 10 * (6 - (_parent_scene.TimeDilation * 5));
            if(m_UpdateTimecntr < m_UpdateFPScntr)
                return;

            m_UpdateTimecntr = 0;

            const float VELOCITY_TOLERANCE = 0.025f;
            //const float ANG_VELOCITY_TOLERANCE = 0.05f;
            const float POSITION_TOLERANCE = 5f;
            bool needSendUpdate = false;

            //Check to see whether we need to trigger the significant movement method in the presence
            // avas don't rotate for now                if (!RotationalVelocity.ApproxEquals(m_lastRotationalVelocity, VELOCITY_TOLERANCE) ||
            // but simulator does not process rotation changes
            float length = (Velocity - m_lastVelocity).LengthSquared();
            //The rotational velocity check... is odd and doesn't work right, so ignore it here
            // Velocity (when turning) will change enough to trigger the updates
            //float anglength = (m_rotationalVelocity - m_lastAngVelocity).LengthSquared();
            if(//!VelIsZero &&
                //                   (!Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) ||
                (
                (length > VELOCITY_TOLERANCE)// ||
                //(anglength > ANG_VELOCITY_TOLERANCE) ||
                //true
                //                    (Math.Abs(_lastorientation.X - _orientation.X) > 0.001) ||
                //                    (Math.Abs(_lastorientation.Y - _orientation.Y) > 0.001) ||
                //                    (Math.Abs(_lastorientation.Z - _orientation.Z) > 0.001) ||
                //                    (Math.Abs(_lastorientation.W - _orientation.W) > 0.001)
                ))
            {
                //m_log.Warn("Vel change - " + length);
                // Update the "last" values
                needSendUpdate = true;
                m_ZeroUpdateSent = 10;
                m_lastPosition = _position;
                //                        m_lastRotationalVelocity = RotationalVelocity;
                m_lastVelocity = Velocity;
                m_lastAngVelocity = RotationalVelocity;
                //                            _lastorientation = Orientation;
                //                        base.RequestPhysicsterseUpdate();
                //                        base.TriggerSignificantMovement();
            }
            else if(VelIsZero)
            {
                if(m_ZeroUpdateSent > 0)
                {
                    needSendUpdate = true;
                    m_ZeroUpdateSent--;
                }
            }
            if((Math.Abs(_position.X - m_lastPosition.X) > POSITION_TOLERANCE) ||
                (Math.Abs(_position.Y - m_lastPosition.Y) > POSITION_TOLERANCE) ||
                (Math.Abs(_position.Z - m_lastPosition.Z) > POSITION_TOLERANCE))
            {
                m_lastPosition = _position;
                needSendUpdate = true;
            }

            if(needSendUpdate)
            {
                base.TriggerSignificantMovement();
                //Tell any listeners about the new info
                // This is for animations
                base.TriggerMovementUpdate();
            }

        }
Beispiel #25
0
        }// end Step

        private void MoveLinear(float pTimestep, OdeScene _pParentScene)
        {
            if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f))  // requested m_linearMotorDirection is significant
            {
                 if (!d.BodyIsEnabled(Body))
                     d.BodyEnable(Body);

                // add drive to body
                Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep);
                m_lastLinearVelocityVector += (addAmount*10);  // lastLinearVelocityVector is the current body velocity vector?

                // This will work temporarily, but we really need to compare speed on an axis
                // KF: Limit body velocity to applied velocity?
                if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X))
                    m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X;
                if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y))
                    m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y;
                if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z))
                    m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z;

                // decay applied velocity
                Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep)));
                //Console.WriteLine("decay: " + decayfraction);
                m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f;
                //Console.WriteLine("actual: " + m_linearMotorDirection);
            }
            else
            {        // requested is not significant
                    // if what remains of applied is small, zero it.
                if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f))
                    m_lastLinearVelocityVector = Vector3.Zero;
            }

            // convert requested object velocity to world-referenced vector
            m_dir = m_lastLinearVelocityVector;
            d.Quaternion rot = d.BodyGetQuaternion(Body);
            Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W);    // rotq = rotation of object
            m_dir *= rotq;                            // apply obj rotation to velocity vector

            // add Gravity andBuoyancy
            // KF: So far I have found no good method to combine a script-requested
            // .Z velocity and gravity. Therefore only 0g will used script-requested
            // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only.
            Vector3 grav = Vector3.Zero;
            // There is some gravity, make a gravity force vector
            // that is applied after object velocity.
            d.Mass objMass;
            d.BodyGetMass(Body, out objMass);
            // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
            grav.Z = _pParentScene.gravityz * objMass.mass * (1f - m_VehicleBuoyancy);
            // Preserve the current Z velocity
            d.Vector3 vel_now = d.BodyGetLinearVel(Body);
            m_dir.Z = vel_now.Z;        // Preserve the accumulated falling velocity

            d.Vector3 pos = d.BodyGetPosition(Body);
//            Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f);
            Vector3 posChange = new Vector3();
            posChange.X = pos.X - m_lastPositionVector.X;
            posChange.Y = pos.Y - m_lastPositionVector.Y;
            posChange.Z = pos.Z - m_lastPositionVector.Z;
            double Zchange = Math.Abs(posChange.Z);
            if (m_BlockingEndPoint != Vector3.Zero)
            {
                if (pos.X >= (m_BlockingEndPoint.X - (float)1))
                {
                    pos.X -= posChange.X + 1;
                    d.BodySetPosition(Body, pos.X, pos.Y, pos.Z);
                }
                if (pos.Y >= (m_BlockingEndPoint.Y - (float)1))
                {
                    pos.Y -= posChange.Y + 1;
                    d.BodySetPosition(Body, pos.X, pos.Y, pos.Z);
                }
                if (pos.Z >= (m_BlockingEndPoint.Z - (float)1))
                {
                    pos.Z -= posChange.Z + 1;
                    d.BodySetPosition(Body, pos.X, pos.Y, pos.Z);
                }
                if (pos.X <= 0)
                {
                    pos.X += posChange.X + 1;
                    d.BodySetPosition(Body, pos.X, pos.Y, pos.Z);
                }
                if (pos.Y <= 0)
                {
                    pos.Y += posChange.Y + 1;
                    d.BodySetPosition(Body, pos.X, pos.Y, pos.Z);
                }
            }
            if (pos.Z < _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y))
            {
                pos.Z = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + 2;
                d.BodySetPosition(Body, pos.X, pos.Y, pos.Z);
            }

            // Check if hovering
            if ((m_Hoverflags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
            {
                // We should hover, get the target height
                if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != 0)
                {
                    m_VhoverTargetHeight = _pParentScene.GetWaterLevel() + m_VhoverHeight;
                }
                if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
                {
                    m_VhoverTargetHeight = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
                }
                if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
                {
                    m_VhoverTargetHeight = m_VhoverHeight;
                }

                if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != 0)
                {
                    // If body is aready heigher, use its height as target height
                    if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z;
                }
                if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
                {
                    if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2)
                    {
                        d.BodySetPosition(Body, pos.X, pos.Y, m_VhoverTargetHeight);
                    }
                }
                else
                {
                    float herr0 = pos.Z - m_VhoverTargetHeight;
                    // Replace Vertical speed with correction figure if significant
                    if (Math.Abs(herr0) > 0.01f)
                    {
                        m_dir.Z = -((herr0 * pTimestep * 50.0f) / m_VhoverTimescale);
                        //KF: m_VhoverEfficiency is not yet implemented
                    }
                    else
                    {
                        m_dir.Z = 0f;
                    }
                }

//                m_VhoverEfficiency = 0f;    // 0=boucy, 1=Crit.damped
//                m_VhoverTimescale = 0f;        // time to acheive height
//                pTimestep  is time since last frame,in secs
            }

            if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
            {
                //Start Experimental Values
                if (Zchange > .3)
                {
                    grav.Z = (float)(grav.Z * 3);
                }
                if (Zchange > .15)
                {
                    grav.Z = (float)(grav.Z * 2);
                }
                if (Zchange > .75)
                {
                    grav.Z = (float)(grav.Z * 1.5);
                }
                if (Zchange > .05)
                {
                    grav.Z = (float)(grav.Z * 1.25);
                }
                if (Zchange > .025)
                {
                    grav.Z = (float)(grav.Z * 1.125);
                }
                float terraintemp = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y);
                float postemp = (pos.Z - terraintemp);
                if (postemp > 2.5f)
                {
                    grav.Z = (float)(grav.Z * 1.037125);
                }
                //End Experimental Values
            }
            if ((m_flags & (VehicleFlag.NO_X)) != 0)
            {
                m_dir.X = 0;
            }
            if ((m_flags & (VehicleFlag.NO_Y)) != 0)
            {
                m_dir.Y = 0;
            }
            if ((m_flags & (VehicleFlag.NO_Z)) != 0)
            {
                m_dir.Z = 0;
            }

            m_lastPositionVector = d.BodyGetPosition(Body);

            // Apply velocity
            d.BodySetLinearVel(Body, m_dir.X, m_dir.Y, m_dir.Z);
            // apply gravity force
            d.BodyAddForce(Body, grav.X, grav.Y, grav.Z);


            // apply friction
            Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep);
            m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount;
        } // end MoveLinear()
Beispiel #26
0
        private int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex)
        {
//            String name1 = null;
//            String name2 = null;
//
//            if (!geom_name_map.TryGetValue(trimesh, out name1))
//            {
//                name1 = "null";
//            }
//
//            if (!geom_name_map.TryGetValue(refObject, out name2))
//            {
//                name2 = "null";
//            }

            //            m_log.InfoFormat("TriCallback: A collision was detected between {1} and {2}. Index was {3}", 0, name1, name2, triangleIndex);

            d.Vector3 v0 = new d.Vector3();
            d.Vector3 v1 = new d.Vector3();
            d.Vector3 v2 = new d.Vector3();

            d.GeomTriMeshGetTriangle(trimesh, 0, ref v0, ref v1, ref v2);
            //            m_log.DebugFormat("Triangle {0} is <{1},{2},{3}>, <{4},{5},{6}>, <{7},{8},{9}>", triangleIndex, v0.X, v0.Y, v0.Z, v1.X, v1.Y, v1.Z, v2.X, v2.Y, v2.Z);

            return 1;
        }
Beispiel #27
0
        private void MoveLinear(float pTimestep, OdeScene _pParentScene)
        {
            if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f))  // requested m_linearMotorDirection is significant
            {
                if (!d.BodyIsEnabled(Body))
                {
                    d.BodyEnable(Body);
                }

                // add drive to body
                Vector3 addAmount = m_linearMotorDirection / (m_linearMotorTimescale / pTimestep);
                m_lastLinearVelocityVector += (addAmount * 10);  // lastLinearVelocityVector is the current body velocity vector?

                // This will work temporarily, but we really need to compare speed on an axis
                // KF: Limit body velocity to applied velocity?
                if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X))
                {
                    m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X;
                }
                if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y))
                {
                    m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y;
                }
                if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z))
                {
                    m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z;
                }

                // decay applied velocity
                Vector3 decayfraction = ((Vector3.One / (m_linearMotorDecayTimescale / pTimestep)));
                //Console.WriteLine("decay: " + decayfraction);
                m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f;
                //Console.WriteLine("actual: " + m_linearMotorDirection);
            }
            else
            {        // requested is not significant
                // if what remains of applied is small, zero it.
                if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f))
                {
                    m_lastLinearVelocityVector = Vector3.Zero;
                }
            }

            // convert requested object velocity to world-referenced vector
            m_dir = m_lastLinearVelocityVector;
            d.Quaternion rot  = d.BodyGetQuaternion(Body);
            Quaternion   rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object

            m_dir *= rotq;                                                  // apply obj rotation to velocity vector

            // add Gravity andBuoyancy
            // KF: So far I have found no good method to combine a script-requested
            // .Z velocity and gravity. Therefore only 0g will used script-requested
            // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only.
            Vector3 grav = Vector3.Zero;

            // There is some gravity, make a gravity force vector
            // that is applied after object velocity.
            d.Mass objMass;
            d.BodyGetMass(Body, out objMass);
            // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
            grav.Z = _pParentScene.gravityz * objMass.mass * (1f - m_VehicleBuoyancy);
            // Preserve the current Z velocity
            d.Vector3 vel_now = d.BodyGetLinearVel(Body);
            m_dir.Z = vel_now.Z;        // Preserve the accumulated falling velocity

            d.Vector3 pos = d.BodyGetPosition(Body);
            //            Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f);
            Vector3 posChange = new Vector3();

            posChange.X = pos.X - m_lastPositionVector.X;
            posChange.Y = pos.Y - m_lastPositionVector.Y;
            posChange.Z = pos.Z - m_lastPositionVector.Z;
            double Zchange = Math.Abs(posChange.Z);

            if (m_BlockingEndPoint != Vector3.Zero)
            {
                if (pos.X >= (m_BlockingEndPoint.X - (float)1))
                {
                    pos.X -= posChange.X + 1;
                    d.BodySetPosition(Body, pos.X, pos.Y, pos.Z);
                }
                if (pos.Y >= (m_BlockingEndPoint.Y - (float)1))
                {
                    pos.Y -= posChange.Y + 1;
                    d.BodySetPosition(Body, pos.X, pos.Y, pos.Z);
                }
                if (pos.Z >= (m_BlockingEndPoint.Z - (float)1))
                {
                    pos.Z -= posChange.Z + 1;
                    d.BodySetPosition(Body, pos.X, pos.Y, pos.Z);
                }
                if (pos.X <= 0)
                {
                    pos.X += posChange.X + 1;
                    d.BodySetPosition(Body, pos.X, pos.Y, pos.Z);
                }
                if (pos.Y <= 0)
                {
                    pos.Y += posChange.Y + 1;
                    d.BodySetPosition(Body, pos.X, pos.Y, pos.Z);
                }
            }
            if (pos.Z < _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y))
            {
                pos.Z = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + 2;
                d.BodySetPosition(Body, pos.X, pos.Y, pos.Z);
            }

            // Check if hovering
            if ((m_Hoverflags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
            {
                // We should hover, get the target height
                if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != 0)
                {
                    m_VhoverTargetHeight = _pParentScene.GetWaterLevel() + m_VhoverHeight;
                }
                if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
                {
                    m_VhoverTargetHeight = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
                }
                if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
                {
                    m_VhoverTargetHeight = m_VhoverHeight;
                }

                if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != 0)
                {
                    // If body is aready heigher, use its height as target height
                    if (pos.Z > m_VhoverTargetHeight)
                    {
                        m_VhoverTargetHeight = pos.Z;
                    }
                }
                if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
                {
                    if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2)
                    {
                        d.BodySetPosition(Body, pos.X, pos.Y, m_VhoverTargetHeight);
                    }
                }
                else
                {
                    float herr0 = pos.Z - m_VhoverTargetHeight;
                    // Replace Vertical speed with correction figure if significant
                    if (Math.Abs(herr0) > 0.01f)
                    {
                        m_dir.Z = -((herr0 * pTimestep * 50.0f) / m_VhoverTimescale);
                        //KF: m_VhoverEfficiency is not yet implemented
                    }
                    else
                    {
                        m_dir.Z = 0f;
                    }
                }

                //                m_VhoverEfficiency = 0f;    // 0=boucy, 1=Crit.damped
                //                m_VhoverTimescale = 0f;        // time to acheive height
                //                pTimestep  is time since last frame,in secs
            }

            if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
            {
                //Start Experimental Values
                if (Zchange > .3)
                {
                    grav.Z = (float)(grav.Z * 3);
                }
                if (Zchange > .15)
                {
                    grav.Z = (float)(grav.Z * 2);
                }
                if (Zchange > .75)
                {
                    grav.Z = (float)(grav.Z * 1.5);
                }
                if (Zchange > .05)
                {
                    grav.Z = (float)(grav.Z * 1.25);
                }
                if (Zchange > .025)
                {
                    grav.Z = (float)(grav.Z * 1.125);
                }
                float terraintemp = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y);
                float postemp     = (pos.Z - terraintemp);
                if (postemp > 2.5f)
                {
                    grav.Z = (float)(grav.Z * 1.037125);
                }
                //End Experimental Values
            }
            if ((m_flags & (VehicleFlag.NO_X)) != 0)
            {
                m_dir.X = 0;
            }
            if ((m_flags & (VehicleFlag.NO_Y)) != 0)
            {
                m_dir.Y = 0;
            }
            if ((m_flags & (VehicleFlag.NO_Z)) != 0)
            {
                m_dir.Z = 0;
            }

            m_lastPositionVector = d.BodyGetPosition(Body);

            // Apply velocity
            d.BodySetLinearVel(Body, m_dir.X, m_dir.Y, m_dir.Z);
            // apply gravity force
            d.BodyAddForce(Body, grav.X, grav.Y, grav.Z);

            // apply friction
            Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep);

            m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount;
        } // end MoveLinear()
Beispiel #28
0
        // normally called from within OnJointMoved, which is called from within a lock (OdeLock)
        public override Vector3 GetJointAnchor(PhysicsJoint joint)
        {
            Debug.Assert(joint.IsInPhysicsEngine);
            d.Vector3 pos = new d.Vector3();

            if (!(joint is OdePhysicsJoint))
            {
                DoJointErrorMessage(joint, "warning: non-ODE joint requesting anchor: " + joint.ObjectNameInScene);
            }
            else
            {
                OdePhysicsJoint odeJoint = (OdePhysicsJoint)joint;
                switch (odeJoint.Type)
                {
                    case PhysicsJointType.Ball:
                        d.JointGetBallAnchor(odeJoint.jointID, out pos);
                        break;
                    case PhysicsJointType.Hinge:
                        d.JointGetHingeAnchor(odeJoint.jointID, out pos);
                        break;
                }
            }
            return new Vector3(pos.X, pos.Y, pos.Z);
        }
Beispiel #29
0
        public int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex)
        {
            d.Vector3 v0 = new d.Vector3();
            d.Vector3 v1 = new d.Vector3();
            d.Vector3 v2 = new d.Vector3();

            d.GeomTriMeshGetTriangle(trimesh, 0, ref v0, ref v1, ref v2);

            return 1;
        }
Beispiel #30
0
        /// <summary>
        /// Updates the reported position and velocity.  This essentially sends the data up to ScenePresence.
        /// </summary>
        public void UpdatePositionAndVelocity(float timestep)
        {
            //  no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
            d.Vector3 vec;
            try
            {
                vec = d.BodyGetPosition(Body);
            }
            catch (NullReferenceException)
            {
                bad = true;
                _parent_scene.BadCharacter(this);
                vec = new d.Vector3(_position.X, _position.Y, _position.Z);
                base.RaiseOutOfBounds(_position); // Tells ScenePresence that there's a problem!
                m_log.WarnFormat("[ODEPLUGIN]: Avatar Null reference for Avatar {0}, physical actor {1}", m_name, m_uuid);
            }


            //  kluge to keep things in bounds.  ODE lets dead avatars drift away (they should be removed!)
            bool needfixbody = false;

            if (vec.X < 0.0f)
                {
                needfixbody = true;
                vec.X = CAPSULE_RADIUS;
                }
            else if (vec.X > (int)_parent_scene.WorldExtents.X - CAPSULE_RADIUS)
                {
                needfixbody = true;
                vec.X = (int)_parent_scene.WorldExtents.X - CAPSULE_RADIUS;
                }

            if (vec.Y < 0.0f)
                {
                needfixbody = true;
                vec.Y = CAPSULE_RADIUS;
                }
            else if (vec.Y > (int)_parent_scene.WorldExtents.Y - CAPSULE_RADIUS)
                {
                needfixbody = true;
                vec.Y = (int)_parent_scene.WorldExtents.Y - CAPSULE_RADIUS;
                }

            if (needfixbody)
                d.BodySetPosition(Body, vec.X, vec.Y, vec.Z);

            _position.X = (float)vec.X;
            _position.Y = (float)vec.Y;
            _position.Z = (float)vec.Z;

            // Did we move last? = zeroflag
            // This helps keep us from sliding all over

            if (_zeroFlag)
            {
                /*if (CollisionEventsThisFrame != null)
                {
                    base.SendCollisionUpdate(CollisionEventsThisFrame);
                }
                CollisionEventsThisFrame = new CollisionEventUpdate();
                m_eventsubscription = 0;*/
                _velocity = Vector3.Zero;

                // Did we send out the 'stopped' message?
                if (!m_lastUpdateSent)
                {
                    m_lastUpdateSent = true;
                    base.RequestPhysicsterseUpdate();
                }

                //Tell any listeners that we've stopped
                base.TriggerMovementUpdate();
            }
            else
            {
                m_lastUpdateSent = false;
                try
                {
                    vec = d.BodyGetLinearVel(Body);
                }
                catch (NullReferenceException)
                {
                    vec.X = _velocity.X;
                    vec.Y = _velocity.Y;
                    vec.Z = _velocity.Z;
                }



                /*
                                if (vec.X == 0 && vec.Y == 0 && vec.Z == 0)
                                {
                                    m_log.Warn("[AODECharacter]: We have a malformed Velocity, ignoring...");
                                }
                                else
                */
                needfixbody = false;

                if (Math.Abs(vec.X) < 0.001 && vec.X != 0)
                    {
                    needfixbody = true;
                    vec.X = 0;
                    }
                if (Math.Abs(vec.Y) < 0.001 && vec.Y != 0)
                    {
                    needfixbody = true;
                    vec.Y = 0;
                    }
                if (Math.Abs(vec.Z) < 0.001 && vec.Z != 0)
                    {
                    needfixbody = true;
                    vec.Z = 0;
                    }

                if (needfixbody)
                    d.BodySetLinearVel(Body, vec.X, vec.Y, vec.Z);

                _velocity = new Vector3((float)(vec.X), (float)(vec.Y), (float)(vec.Z));

                const float VELOCITY_TOLERANCE = 0.001f;
                const float POSITION_TOLERANCE = 0.05f;

                //Check to see whether we need to trigger the significant movement method in the presence
                if (!RotationalVelocity.ApproxEquals(m_lastRotationalVelocity, VELOCITY_TOLERANCE) ||
                    !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) ||
                    !Position.ApproxEquals(m_lastPosition, POSITION_TOLERANCE))
                {
                    // Update the "last" values
                    m_lastPosition = Position;
                    m_lastRotationalVelocity = RotationalVelocity;
                    m_lastVelocity = Velocity;
                    base.RequestPhysicsterseUpdate();
                    base.TriggerSignificantMovement();
                }
                //Tell any listeners about the new info
                base.TriggerMovementUpdate();
            }
        }
        public void step(int pause)
        {
            
            ds.SetColor(1.0f, 1.0f, 0.0f);
            ds.SetTexture(ds.Texture.Wood);
            lock (_prims)
            {
                foreach (OdePrim prm in _prims)
                {
                    //IntPtr body = d.GeomGetBody(prm.prim_geom);
                    if (prm.prim_geom != IntPtr.Zero)
                    {
                        d.Vector3 pos;
                        d.GeomCopyPosition(prm.prim_geom, out pos);
                        //d.BodyCopyPosition(body, out pos);

                        d.Matrix3 R;
                        d.GeomCopyRotation(prm.prim_geom, out R);
                        //d.BodyCopyRotation(body, out R);


                        d.Vector3 sides = new d.Vector3();
                        sides.X = prm.Size.X;
                        sides.Y = prm.Size.Y;
                        sides.Z = prm.Size.Z;

                        ds.DrawBox(ref pos, ref R, ref sides);
                    }
                }
            }
            ds.SetColor(1.0f, 0.0f, 0.0f);
            lock (_characters)
            {
                foreach (OdeCharacter chr in _characters)
                {
                    if (chr.Shell != IntPtr.Zero)
                    {
                        IntPtr body = d.GeomGetBody(chr.Shell);

                        d.Vector3 pos;
                        d.GeomCopyPosition(chr.Shell, out pos);
                        //d.BodyCopyPosition(body, out pos);

                        d.Matrix3 R;
                        d.GeomCopyRotation(chr.Shell, out R);
                        //d.BodyCopyRotation(body, out R);

                        ds.DrawCapsule(ref pos, ref R, chr.Size.Z, 0.35f);
                        d.Vector3 sides = new d.Vector3();
                        sides.X = 0.5f;
                        sides.Y = 0.5f;
                        sides.Z = 0.5f;

                        ds.DrawBox(ref pos, ref R, ref sides);
                    }
                }
            }
        }
Beispiel #32
0
        /// <summary>
        /// Called from Simulate
        /// This is the avatar's movement control + PID Controller
        /// </summary>
        /// <param name="timeStep"></param>
        public void Move(float timeStep, List<AuroraODECharacter> defects)
            {
            //  no lock; for now it's only called from within Simulate()

            // If the PID Controller isn't active then we set our force
            // calculating base velocity to the current position

            if (Body == IntPtr.Zero)
                return;

            // replace amotor
            d.Quaternion dtmp;
            dtmp.W =1;
            dtmp.X=0;
            dtmp.Y=0;
            dtmp.Z=0;
            d.BodySetQuaternion(Body, ref dtmp);
            d.BodySetAngularVel(Body, 0, 0, 0);

            if (m_pidControllerActive == false)
                {
                _zeroPosition = d.BodyGetPosition(Body);
                }
            //PidStatus = true;

            // rex, added height check

            d.Vector3 tempPos = d.BodyGetPosition(Body);

            if (_parent_scene.m_useFlightCeilingHeight && tempPos.Z > _parent_scene.m_flightCeilingHeight)
                {
                tempPos.Z = _parent_scene.m_flightCeilingHeight;
                d.BodySetPosition(Body, tempPos.X, tempPos.Y, tempPos.Z);
                d.Vector3 tempVel = d.BodyGetLinearVel(Body);
                if (tempVel.Z > 0.0f)
                    {
                    tempVel.Z = 0.0f;
                    d.BodySetLinearVel(Body, tempVel.X, tempVel.Y, tempVel.Z);
                    }
                if (_target_velocity.Z > 0.0f)
                    _target_velocity.Z = 0.0f;
                }

            // endrex


            Vector3 localPos = new Vector3((float)tempPos.X, (float)tempPos.Y, (float)tempPos.Z);

            if (!localPos.IsFinite())
                {
                m_log.Warn("[PHYSICS]: Avatar Position is non-finite!");
                defects.Add(this);
                // _parent_scene.RemoveCharacter(this);

                // destroy avatar capsule and related ODE data
                if (Amotor != IntPtr.Zero)
                    {
                    // Kill the Amotor
                    d.JointDestroy(Amotor);
                    Amotor = IntPtr.Zero;
                    }

                //kill the Geometry
                _parent_scene.waitForSpaceUnlock(_parent_scene.space);

                if (Body != IntPtr.Zero)
                    {
                    //kill the body
                    d.BodyDestroy(Body);

                    Body = IntPtr.Zero;
                    }

                if (Shell != IntPtr.Zero)
                    {
                    d.GeomDestroy(Shell);
                    _parent_scene.geom_name_map.Remove(Shell);
                    Shell = IntPtr.Zero;
                    }
                return;
                }

            Vector3 vec = Vector3.Zero;
            d.Vector3 vel = d.BodyGetLinearVel(Body);

            #region Check for underground

//            _parent_scene.CheckTerrainColisionAABB(Shell);


            //            if (!flying || (flying && _target_velocity.X == 0 || _target_velocity.Y == 0))
            //            if (!m_iscollidingGround)
            //Don't duplicate the ground check for flying from above, it will already have given us a good shove
                {
                //                if (m_WaitGroundCheck >= 10 && vel.Z != 0)
                    {
                    float groundHeight = _parent_scene.GetTerrainHeightAtXY(tempPos.X, tempPos.Y);
                    if ((tempPos.Z - AvatarHalfsize) < groundHeight)
                        {
                        if (!flying)
                            {
                            if (_target_velocity.Z < 0)
                                _target_velocity.Z = 0;
                            vec.Z = -vel.Z * PID_D + ((groundHeight - (tempPos.Z - AvatarHalfsize)) * PID_P * 20.0f);
                            }
                        else
                            vec.Z = ((groundHeight - (tempPos.Z - AvatarHalfsize)) * PID_P);
                        }
                    if (tempPos.Z - AvatarHalfsize - groundHeight < 0.1)
                        {
                        m_iscolliding = true;
                        m_iscollidingGround = true;
                        flying = false; // gound the avatar
                        }
                    else
                        m_iscollidingGround = false;


                    //                    m_WaitGroundCheck = -1;
                    }
                //                m_WaitGroundCheck++;
                }

/*
            if (!m_alwaysRun)
                movementdivisor = _parent_scene.avMovementDivisorWalk * (_parent_scene.TimeDilation < 0.3 ? 0.6f : _parent_scene.TimeDilation); //Dynamically adjust it for slower sims
            else
                movementdivisor = _parent_scene.avMovementDivisorRun * (_parent_scene.TimeDilation < 0.3 ? 0.6f : _parent_scene.TimeDilation); //Dynamically adjust it for slower sims
*/
            // no dinamic messing here

            float movementmult = 1f;
            if (!m_alwaysRun)
                movementmult /= _parent_scene.avMovementDivisorWalk;
            else
                movementmult /= _parent_scene.avMovementDivisorRun;


            //  if velocity is zero, use position control; otherwise, velocity control
            if (_target_velocity == Vector3.Zero &&
                Math.Abs(vel.X) < 0.05 && Math.Abs(vel.Y) < 0.05 && Math.Abs(vel.Z) < 0.05 && (this.m_iscollidingGround || this.m_iscollidingObj || this.flying))
                //This is so that if we get moved by something else, it will update us in the client
                {
                //  keep track of where we stopped.  No more slippin' & slidin'
                if (!_zeroFlag)
                    {
                    _zeroFlag = true;
                    _zeroPosition = tempPos;
                    }

                if (m_pidControllerActive)
                    {
                    // We only want to deactivate the PID Controller if we think we want to have our surrogate
                    // react to the physics scene by moving it's position.
                    // Avatar to Avatar collisions
                    // Prim to avatar collisions
                    // if target vel is zero why was it here ?
                    //vec.X = -vel.X * PID_D + (_zeroPosition.X - tempPos.X) * PID_P * 2f;
                    //vec.Y = -vel.Y * PID_D + (_zeroPosition.Y - tempPos.Y) * PID_P * 2f;
                    }
                }
            else
                {
                m_pidControllerActive = true;
                _zeroFlag = false;

                if (m_iscolliding)
                    {
                    if(!flying)
                        {
                        if (_target_velocity.Z != 0.0f)
                            vec.Z = (_target_velocity.Z - vel.Z) * PID_D;// + (_zeroPosition.Z - tempPos.Z) * PID_P)) _zeropos maybe bad here
                        // We're standing or walking on something
                        vec.X = (_target_velocity.X * movementmult - vel.X) * PID_D*2;
                        vec.Y = (_target_velocity.Y * movementmult - vel.Y) * PID_D*2;
                        }
                    else 
                        {
                    // We're flying and colliding with something
                        vec.X = (_target_velocity.X * movementmult - vel.X) * PID_D * 0.5f;
                        vec.Y = (_target_velocity.Y * movementmult - vel.Y) * PID_D * 0.5f;
                        }
                    }               
                else
                    {
                    if (flying)
                        {
                        // we're flyind
                        vec.X = (_target_velocity.X * movementmult - vel.X) * PID_D * 0.75f;
                        vec.Y = (_target_velocity.Y * movementmult - vel.Y) * PID_D * 0.75f;
                        }

                    else 
                        {
                        // we're not colliding and we're not flying so that means we're falling!
                        // m_iscolliding includes collisions with the ground.
                        vec.X = (_target_velocity.X - vel.X) * PID_D * 0.85f;
                        vec.Y = (_target_velocity.Y - vel.Y) * PID_D * 0.85f;
                        }
                    }

                if (flying)
                    {
                    #region Av gravity

                    if (_parent_scene.AllowAvGravity &&
                        tempPos.Z > _parent_scene.AvGravityHeight) //Should be stop avies from flying upwards
                        {
                        //Decay going up 
                        if (_target_velocity.Z > 0)
                            {
                            //How much should we force them down?
                            float Multiplier = (_parent_scene.AllowAvsToEscapeGravity ? .03f : .1f);
                            //How much should we force them down?
                            float fudgeHeight = (_parent_scene.AllowAvsToEscapeGravity ? 80 : 30);
                            //We add the 30 so that gravity is resonably strong once they pass the min height
                            Multiplier *= tempPos.Z + fudgeHeight - _parent_scene.AvGravityHeight;

                            //Limit these so that things don't go wrong
                            if (Multiplier < 1)
                                Multiplier = 1;

                            float maxpower = (_parent_scene.AllowAvsToEscapeGravity ? 1.5f : 3f);

                            if (Multiplier > maxpower)
                                Multiplier = maxpower;

                            _target_velocity.Z /= Multiplier;
                            vel.Z /= Multiplier;
                            }
                        }

                    #endregion

                    vec.Z = (_target_velocity.Z - vel.Z) * PID_D * 0.5f;
                    if (_parent_scene.AllowAvGravity && tempPos.Z > _parent_scene.AvGravityHeight)
                        //Add extra gravity
                        vec.Z += ((10 * _parent_scene.gravityz) * Mass);
                    }
                }

            if (flying)
                {
                #region Auto Fly Height

                //Added for auto fly height. Kitto Flora
                //Changed to only check if the avatar is flying around,

                // Revolution: If the avatar is going down, they are trying to land (probably), so don't push them up to make it harder
                //   Only if they are moving around sideways do we need to push them up
                if (_target_velocity.X != 0 || _target_velocity.Y != 0)
                    {
                    Vector3 forwardVel = new Vector3(_target_velocity.X > 0 ? 2 : (_target_velocity.X < 0 ? -2 : 0),
                        _target_velocity.Y > 0 ? 2 : (_target_velocity.Y < 0 ? -2 : 0),
                        0);
                    float target_altitude = _parent_scene.GetTerrainHeightAtXY(tempPos.X, tempPos.Y) + MinimumGroundFlightOffset;

                    //We cheat a bit and do a bit lower than normal
                    if ((tempPos.Z - CAPSULE_LENGTH) < target_altitude ||
                            (tempPos.Z - CAPSULE_LENGTH) < _parent_scene.GetTerrainHeightAtXY(tempPos.X + forwardVel.X, tempPos.Y + forwardVel.Y)
                            + MinimumGroundFlightOffset)
                        vec.Z += (target_altitude - tempPos.Z) * PID_P * 0.5f;
                    }
                else
                    {
                    //Straight up and down, only apply when they are very close to the ground
                    float target_altitude = _parent_scene.GetTerrainHeightAtXY(tempPos.X, tempPos.Y);

                    if ((tempPos.Z - CAPSULE_LENGTH + (MinimumGroundFlightOffset / 1.5)) < target_altitude + MinimumGroundFlightOffset)
                        {
                        if ((tempPos.Z - CAPSULE_LENGTH) < target_altitude + 1)
                            {
                            vec.Z += ((target_altitude + 4) - (tempPos.Z - CAPSULE_LENGTH)) * PID_P;
                            }
                        else
                            vec.Z += ((target_altitude + MinimumGroundFlightOffset) - (tempPos.Z - CAPSULE_LENGTH)) * PID_P * 0.5f;
                        }
                    }

                #endregion
            }

            #region Gravity

            if (!flying && _parent_scene.AllowAvGravity)
                {
                if (!_parent_scene.UsePointGravity)
                    {
                    //Add normal gravity
                    vec.X += _parent_scene.gravityx * m_mass;
                    vec.Y += _parent_scene.gravityy * m_mass;
                    vec.Z += _parent_scene.gravityz * m_mass;
                    }
                else
                    {
                    Vector3 cog = _parent_scene.PointOfGravity;
                    if (cog.X != 0)
                        vec.X += (cog.X - tempPos.X) * m_mass;
                    if (cog.Y != 0)
                        vec.Y += (cog.Y - tempPos.Y) * m_mass;
                    if (cog.Z != 0)
                        vec.Z += (cog.Z - tempPos.Z) * m_mass;
                    }
                }

            #endregion

            #region Under water physics

            if (_parent_scene.AllowUnderwaterPhysics)
                {
                //Position plus height to av's shoulder (aprox) is just above water
                    if ((tempPos.Z + (CAPSULE_LENGTH / 3) - .25f) < _parent_scene.GetWaterLevel((float)tempPos.X, (float)tempPos.Y))
                    {
                    if (StartingUnderWater)
                        ShouldBeWalking = Flying == false;
                    StartingUnderWater = false;
                    WasUnderWater = true;
                    Flying = true;
                    lastUnderwaterPush = 0;
                    if (ShouldBeWalking)
                        {
                            lastUnderwaterPush += (float)(_parent_scene.GetWaterLevel((float)tempPos.X, (float)tempPos.Y) - tempPos.Z) * 33 + 3;
                        vec.Z += lastUnderwaterPush;
                        }
                    else
                        {
                        lastUnderwaterPush += 3500;
                        lastUnderwaterPush += (float)(_parent_scene.GetWaterLevel((float)tempPos.X, (float)tempPos.Y) - tempPos.Z) * 8;
                        vec.Z += lastUnderwaterPush;
                        }
                    }
                else
                    {
                    StartingUnderWater = true;
                    if (WasUnderWater)
                        {
                        WasUnderWater = false;
                        Flying = true;
                        }
                    }
                }

            #endregion


            #endregion

            if (vec.IsFinite())
            {
                if (vec.X < 100000000 && vec.Y < 10000000 && vec.Z < 10000000) //Checks for crazy, going to NaN us values
                {
                    d.Vector3 veloc = d.BodyGetLinearVel(Body);
                    //Stop us from fidgiting if we have a small velocity
                    /*
                                        if (_zeroFlag && ((Math.Abs(vec.X) < 0.09 && Math.Abs(vec.Y) < 0.09 && Math.Abs(vec.Z) < 0.03) && !flying && vec.Z != 0))
                                        {
                                            //m_log.Warn("Nulling Velo: " + vec.ToString());
                                            vec = new Vector3(0, 0, 0);
                                            d.BodySetLinearVel(Body, 0, 0, 0);
                                        }

                                        //Reduce insanely small values to 0 if the velocity isn't going up
                                        if (Math.Abs(vec.Z) < 0.01 && veloc.Z < 0.6 && _zeroFlag)
                                        {
                                            if (veloc.Z != 0)
                                            {
                                                if (-veloc.Z > 0)
                                                    vec.Z = 0;
                                                else
                                                    vec.Z = -veloc.Z * 5;
                                                d.BodySetLinearVel(Body, veloc.X, veloc.Y, vec.Z);
                                            }
                                        }

                    */
                    // round small values to zero. those possible are just errors
                    if (Math.Abs(vec.X) < 0.001)
                        vec.X = 0;
                    if (Math.Abs(vec.Y) < 0.001)
                        vec.Y = 0;
                    if (Math.Abs(vec.Z) < 0.001)
                        vec.Z = 0;


                    doForce(vec);

                    //When falling, we keep going faster and faster, and eventually, the client blue screens (blue is all you see).
                    // The speed that does this is slightly higher than -30, so we cap it here so we never do that during falling.
                    if (vel.Z < -30)
                    {
                        vel.Z = -30;
                        d.BodySetLinearVel(Body, vel.X, vel.Y, vel.Z);
                    }

                    //Decay out the target velocity
                    _target_velocity *= _parent_scene.m_avDecayTime;
                    if (!_zeroFlag && _target_velocity.ApproxEquals(Vector3.Zero, _parent_scene.m_avStopDecaying))
                        _target_velocity = Vector3.Zero;

                    //Check if the capsule is tilted before changing it
//                    if (!_zeroFlag && !_parent_scene.IsAvCapsuleTilted)
//                        AlignAvatarTiltWithCurrentDirectionOfMovement(vec);
                }
                else
                {
                    //This is a safe guard from going NaN, but it isn't very smooth... which is ok
                    d.BodySetForce(Body, 0, 0, 0);
                    d.BodySetLinearVel(Body, 0, 0, 0);
                }
            }
            else
            {
                m_log.Warn("[PHYSICS]: Got a NaN force vector in Move()");
                m_log.Warn("[PHYSICS]: Avatar Position is non-finite!");
                defects.Add(this);
                // _parent_scene.RemoveCharacter(this);
                // destroy avatar capsule and related ODE data
                if (Amotor != IntPtr.Zero)
                {
                    // Kill the Amotor
                    d.JointDestroy(Amotor);
                    Amotor = IntPtr.Zero;
                }
                //kill the Geometry
                _parent_scene.waitForSpaceUnlock(_parent_scene.space);

                if (Body != IntPtr.Zero)
                {
                    //kill the body
                    d.BodyDestroy(Body);

                    Body = IntPtr.Zero;
                }

                if (Shell != IntPtr.Zero)
                {
                    d.GeomDestroy(Shell);
                    _parent_scene.geom_name_map.Remove(Shell);
                    Shell = IntPtr.Zero;
                    }
                }
            }
Beispiel #33
0
        /// <summary>
        /// Updates the reported position and velocity.  This essentially sends the data up to ScenePresence.
        /// </summary>
        public void UpdatePositionAndVelocity()
        {
            //  no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
            d.Vector3 vec = d.BodyGetPosition(Body);

            //  kluge to keep things in bounds.  ODE lets dead avatars drift away (they should be removed!)
            if (vec.X < 0.0f)
            {
                vec.X = 0.0f;
            }
            if (vec.Y < 0.0f)
            {
                vec.Y = 0.0f;
            }
            if (vec.X > 255.95f)
            {
                vec.X = 255.95f;
            }
            if (vec.Y > 255.95f)
            {
                vec.Y = 255.95f;
            }

            _position.X = vec.X;
            _position.Y = vec.Y;
            _position.Z = vec.Z;

            // Did we move last? = zeroflag
            // This helps keep us from sliding all over

            if (_zeroFlag)
            {
                _velocity.X = 0.0f;
                _velocity.Y = 0.0f;
                _velocity.Z = 0.0f;

                // Did we send out the 'stopped' message?
                if (!m_lastUpdateSent)
                {
                    m_lastUpdateSent = true;
                    //base.RequestPhysicsterseUpdate();
                }
            }
            else
            {
                m_lastUpdateSent = false;
                vec         = d.BodyGetLinearVel(Body);
                _velocity.X = (vec.X);
                _velocity.Y = (vec.Y);

                _velocity.Z = (vec.Z);

                if (_velocity.Z < -6 && !m_hackSentFall)
                {
                    m_hackSentFall        = true;
                    m_pidControllerActive = false;
                }
                else if (flying && !m_hackSentFly)
                {
                    //m_hackSentFly = true;
                    //base.SendCollisionUpdate(new CollisionEventUpdate());
                }
                else
                {
                    m_hackSentFly  = false;
                    m_hackSentFall = false;
                }
            }
        }
        }   // end Step

        private void MoveLinear (float pTimestep, AuroraODEPhysicsScene _pParentScene, AuroraODEPrim parent)
        {
            if (!m_linearMotorDirection.ApproxEquals (Vector3.Zero, 0.01f))  // requested m_linearMotorDirection is significant
            {
                if (!d.BodyIsEnabled (Body))
                    d.BodyEnable (Body);

                // add drive to body
                Vector3 addAmount = m_linearMotorDirection / ((m_linearMotorTimescale) / pTimestep);
                m_lastLinearVelocityVector += (addAmount);  // lastLinearVelocityVector is the current body velocity vector?

                // This will work temporarily, but we really need to compare speed on an axis
                // KF: Limit body velocity to applied velocity?
                if (Math.Abs (m_lastLinearVelocityVector.X) > Math.Abs (m_linearMotorDirectionLASTSET.X))
                    m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X;
                if (Math.Abs (m_lastLinearVelocityVector.Y) > Math.Abs (m_linearMotorDirectionLASTSET.Y))
                    m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y;
                if (Math.Abs (m_lastLinearVelocityVector.Z) > Math.Abs (m_linearMotorDirectionLASTSET.Z))
                    m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z;

                // decay applied velocity
                Vector3 decayfraction = ((Vector3.One / (m_linearMotorDecayTimescale / (pTimestep))));
                decayfraction.Z = ((1 / (m_linearMotorDecayTimescale / (pTimestep * pTimestep))));
                //Console.WriteLine("decay: " + decayfraction);
                Vector3 decayAmt = (m_linearMotorDirection * decayfraction);
                m_linearMotorDirection -= decayAmt;
                //Console.WriteLine("actual: " + m_linearMotorDirection);
            }
            else
            {        // requested is not significant
                // if what remains of applied is small, zero it.
                if (m_lastLinearVelocityVector.ApproxEquals (Vector3.Zero, 0.01f))
                    m_lastLinearVelocityVector = Vector3.Zero;
            }

            // convert requested object velocity to world-referenced vector
            m_dir = m_lastLinearVelocityVector;
            d.Quaternion rot = d.BodyGetQuaternion (Body);
            Quaternion rotq = new Quaternion (rot.X, rot.Y, rot.Z, rot.W);    // rotq = rotation of object
            m_dir *= rotq;                            // apply obj rotation to velocity vector

            // add Gravity andBuoyancy
            // KF: So far I have found no good method to combine a script-requested
            // .Z velocity and gravity. Therefore only 0g will used script-requested
            // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only.
            Vector3 grav = Vector3.Zero;
            // There is some gravity, make a gravity force vector
            // that is applied after object velocity.
            // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
            grav.Z = _pParentScene.gravityz * Mass * (float)parent.ParentEntity.GravityMultiplier * (1f - m_VehicleBuoyancy);
            // Preserve the current Z velocity
            d.Vector3 vel_now = d.BodyGetLinearVel (Body);
            if(m_lastLinearVelocityVector.Z == 0 && m_verticalAttractionTimescale == 0)
                m_dir.Z = vel_now.Z;        // Preserve the accumulated falling velocity
            else if(Type != Vehicle.TYPE_AIRPLANE && Type != Vehicle.TYPE_BALLOON)
                m_dir.Z += vel_now.Z;

            d.Vector3 pos = d.BodyGetPosition (Body);
            //            Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f);
            Vector3 posChange = new Vector3 ();
            posChange.X = pos.X - m_lastPositionVector.X;
            posChange.Y = pos.Y - m_lastPositionVector.Y;
            posChange.Z = pos.Z - m_lastPositionVector.Z;
            double Zchange = Math.Abs (posChange.Z);
            if (m_BlockingEndPoint != Vector3.Zero)
            {
                if (pos.X >= (m_BlockingEndPoint.X - (float)1))
                {
                    pos.X -= posChange.X + 1;
                    d.BodySetPosition (Body, pos.X, pos.Y, pos.Z);
                }
                if (pos.Y >= (m_BlockingEndPoint.Y - (float)1))
                {
                    pos.Y -= posChange.Y + 1;
                    d.BodySetPosition (Body, pos.X, pos.Y, pos.Z);
                }
                if (pos.Z >= (m_BlockingEndPoint.Z - (float)1))
                {
                    pos.Z -= posChange.Z + 1;
                    d.BodySetPosition (Body, pos.X, pos.Y, pos.Z);
                }
                if (pos.X <= 0)
                {
                    pos.X += posChange.X + 1;
                    d.BodySetPosition (Body, pos.X, pos.Y, pos.Z);
                }
                if (pos.Y <= 0)
                {
                    pos.Y += posChange.Y + 1;
                    d.BodySetPosition (Body, pos.X, pos.Y, pos.Z);
                }
            }
            if (pos.Z < _pParentScene.GetTerrainHeightAtXY (pos.X, pos.Y))
            {
                pos.Z = _pParentScene.GetTerrainHeightAtXY (pos.X, pos.Y) + 2;
                d.BodySetPosition (Body, pos.X, pos.Y, pos.Z);
            }

            // Check if hovering
            if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
            {
                // We should hover, get the target height
                if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0)
                {
                    m_VhoverTargetHeight = (float)_pParentScene.GetWaterLevel (pos.X, pos.Y) + m_VhoverHeight;
                }
                if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
                {
                    m_VhoverTargetHeight = _pParentScene.GetTerrainHeightAtXY (pos.X, pos.Y) + m_VhoverHeight;
                }
                if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
                {
                    m_VhoverTargetHeight = m_VhoverHeight;
                }

                if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0)
                {
                    // If body is aready heigher, use its height as target height
                    if (pos.Z > m_VhoverTargetHeight)
                        m_VhoverTargetHeight = pos.Z;
                }
                if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
                {
                    if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2)
                    {
                        d.BodySetPosition (Body, pos.X, pos.Y, m_VhoverTargetHeight);
                    }
                }
                else
                {
                    float herr0 = pos.Z - m_VhoverTargetHeight;
                    // Replace Vertical speed with correction figure if significant
                    if (Math.Abs (herr0) > 0.01f)
                    {
                        m_dir.Z = -((herr0 * pTimestep * 50.0f) / m_VhoverTimescale);
                        //KF: m_VhoverEfficiency is not yet implemented
                    }
                    else
                    {
                        m_dir.Z = 0f;
                    }
                }

                //                m_VhoverEfficiency = 0f;    // 0=boucy, 1=Crit.damped
                //                m_VhoverTimescale = 0f;        // time to acheive height
                //                pTimestep  is time since last frame,in secs
            }

            if ((m_flags & (VehicleFlag.NO_X)) != 0)
                m_dir.X = 0;
            if ((m_flags & (VehicleFlag.NO_Y)) != 0)
                m_dir.Y = 0;
            if ((m_flags & (VehicleFlag.NO_Z)) != 0)
                m_dir.Z = 0;

            #region Limit Motor Up

            if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) //if it isn't going up, don't apply the limiting force
            {
                if (Zchange > -0.1f)
                {
                    //Requires idea of 'up', so use reference frame to rotate it
                    //Add to the X, because that will normally tilt the vehicle downward (if its rotated, it'll be rotated by the ref. frame
                    grav += (new Vector3 (0, 0, ((float)Math.Abs (Zchange) * (pTimestep * -_pParentScene.PID_D * _pParentScene.PID_D))));
                }
            }

            #endregion

            #region Deal with tainted forces

            // KF: So far I have found no good method to combine a script-requested
            // .Z velocity and gravity. Therefore only 0g will used script-requested
            // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only.
            // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
            Vector3 TaintedForce = new Vector3 ();
            if (m_forcelist.Count != 0)
            {
                try
                {
                    for (int i = 0; i < m_forcelist.Count; i++)
                    {
                        TaintedForce = TaintedForce + (m_forcelist[i] * 100);
                    }
                }
                catch (IndexOutOfRangeException)
                {
                    TaintedForce = Vector3.Zero;
                }
                catch (ArgumentOutOfRangeException)
                {
                    TaintedForce = Vector3.Zero;
                }
                m_forcelist = new List<Vector3> ();
            }

            #endregion

            #region Deflection

            //Forward is the prefered direction
            /*Vector3 deflectionamount = m_dir / (m_linearDeflectionTimescale / pTimestep);
            //deflectionamount *= m_linearDeflectionEfficiency;
            if (deflectionamount != Vector3.Zero)
            {
            }
            Vector3 deflection = Vector3.One / deflectionamount;
            m_dir /= deflection;*/

            #endregion

            m_lastPositionVector = d.BodyGetPosition (Body);
            #region limitations

            if (Math.Abs (m_dir.X) > 1000 ||
                Math.Abs (m_dir.Y) > 1000 ||
                Math.Abs (m_dir.Z) > 1000)
            {
                //This vehicle is f***ed
                parent.RaiseOutOfBounds (parent.Position);
                parent._zeroFlag = true;
                parent.m_disabled = true;
                parent.m_frozen = true;
                return;
            }

            #endregion

            // Apply velocity
            d.BodySetLinearVel (Body, m_dir.X, m_dir.Y, m_dir.Z);
            // apply gravity force
            d.BodyAddForce (Body, grav.X, grav.Y, grav.Z);


            // apply friction
            Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep);
            m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount;
        } // end MoveLinear()