示例#1
0
 public virtual void getContactData(ref ContactData cdata)
 {
     cdata.mu = 0;
     cdata.bounce = 0;
 }
示例#2
0
 public virtual void getContactData(ref ContactData cdata)
 {
     cdata.mu     = 0;
     cdata.bounce = 0;
 }
示例#3
0
        /// <summary>
        /// This is our near callback.  A geometry is near a body
        /// </summary>
        /// <param name="space">The space that contains the geoms.  Remember, spaces are also geoms</param>
        /// <param name="g1">a geometry or space</param>
        /// <param name="g2">another geometry or space</param>
        /// 

        private void near(IntPtr space, IntPtr g1, IntPtr g2)
        {
            //  no lock here!  It's invoked from within Simulate(), which is thread-locked

            if (m_global_contactcount >= maxContactsbeforedeath)
                return;

            // Test if we're colliding a geom with a space.
            // If so we have to drill down into the space recursively

            if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
                return;

            if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2))
            {
                // We'll be calling near recursivly if one
                // of them is a space to find all of the
                // contact points in the space
                try
                {
                    d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
                }
                catch (AccessViolationException)
                {
                    m_log.Warn("[PHYSICS]: Unable to collide test a space");
                    return;
                }
                //here one should check collisions of geoms inside a space
                // but on each space we only should have geoms that not colide amoung each other
                // so we don't dig inside spaces
                return;
            }

            // get geom bodies to check if we already a joint contact
            // guess this shouldn't happen now
            IntPtr b1 = d.GeomGetBody(g1);
            IntPtr b2 = d.GeomGetBody(g2);

            // d.GeomClassID id = d.GeomGetClass(g1);

            // Figure out how many contact points we have
            int count = 0;
            try
            {
                // Colliding Geom To Geom
                // This portion of the function 'was' blatantly ripped off from BoxStack.cs

                if (g1 == g2)
                    return; // Can't collide with yourself

                if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
                    return;
                /*
                // debug
                                PhysicsActor dp2;
                                if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass)
                                {
                                    d.AABB aabb;
                                    d.GeomGetAABB(g2, out aabb);
                                    float x = aabb.MaxX - aabb.MinX;
                                    float y = aabb.MaxY - aabb.MinY;
                                    float z = aabb.MaxZ - aabb.MinZ;
                                    if (x > 60.0f || y > 60.0f || z > 60.0f)
                                    {
                                        if (!actor_name_map.TryGetValue(g2, out dp2))
                                            m_log.WarnFormat("[PHYSICS]: failed actor mapping for geom 2");
                                        else
                                            m_log.WarnFormat("[PHYSICS]: land versus large prim geo {0},size {1}, AABBsize <{2},{3},{4}>, at {5} ori {6},({7})",
                                                dp2.Name, dp2.Size, x, y, z,
                                                dp2.Position.ToString(),
                                                dp2.Orientation.ToString(),
                                                dp2.Orientation.Length());
                                        return;
                                    }
                                }
                //
                */


                if (d.GeomGetCategoryBits(g1) == (uint)CollisionCategories.VolumeDtc ||
                    d.GeomGetCategoryBits(g2) == (uint)CollisionCategories.VolumeDtc)
                {
                    int cflags;
                    unchecked
                    {
                        cflags = (int)(1 | d.CONTACTS_UNIMPORTANT);
                    }
                    count = d.CollidePtr(g1, g2, cflags, ContactgeomsArray, d.ContactGeom.unmanagedSizeOf);
                }
                else
                    count = d.CollidePtr(g1, g2, (contactsPerCollision & 0xffff), ContactgeomsArray, d.ContactGeom.unmanagedSizeOf);
            }
            catch (SEHException)
            {
                m_log.Error("[PHYSICS]: The Operating system shut down ODE because of corrupt memory.  This could be a result of really irregular terrain.  If this repeats continuously, restart using Basic Physics and terrain fill your terrain.  Restarting the sim.");
                //                ode.drelease(world);
                base.TriggerPhysicsBasedRestart();
            }
            catch (Exception e)
            {
                m_log.WarnFormat("[PHYSICS]: Unable to collide test an object: {0}", e.Message);
                return;
            }

            // contacts done
            if (count == 0)
                return;

            // try get physical actors 
            PhysicsActor p1;
            PhysicsActor p2;

            if (!actor_name_map.TryGetValue(g1, out p1))
            {
                m_log.WarnFormat("[PHYSICS]: failed actor mapping for geom 1");
                return;
            }

            if (!actor_name_map.TryGetValue(g2, out p2))
            {
                m_log.WarnFormat("[PHYSICS]: failed actor mapping for geom 2");
                return;
            }

            // update actors collision score
            if (p1.CollisionScore >= float.MaxValue - count)
                p1.CollisionScore = 0;
            p1.CollisionScore += count;

            if (p2.CollisionScore >= float.MaxValue - count)
                p2.CollisionScore = 0;
            p2.CollisionScore += count;

            // get first contact
            d.ContactGeom curContact = new d.ContactGeom();

            if (!GetCurContactGeom(0, ref curContact))
                return;

            ContactPoint maxDepthContact = new ContactPoint();

            // do volume detection case
            if ((p1.IsVolumeDtc || p2.IsVolumeDtc))
            {
                maxDepthContact = new ContactPoint(
                    new Vector3(curContact.pos.X, curContact.pos.Y, curContact.pos.Z),
                    new Vector3(curContact.normal.X, curContact.normal.Y, curContact.normal.Z),
                    curContact.depth, false
                    );

                collision_accounting_events(p1, p2, maxDepthContact);
                return;
            }

            // big messy collision analises

            float mu = 0;
            float bounce = 0;
//            bool IgnoreNegSides = false;

            ContactData contactdata1 = new ContactData(0, 0, false);
            ContactData contactdata2 = new ContactData(0, 0, false);

            bool dop1ava = false;
            bool dop2ava = false;
            bool ignore = false;
            bool smoothMesh = false;

            switch (p1.PhysicsActorType)
            {
                case (int)ActorTypes.Agent:
                    {
                        dop1ava = true;
                        switch (p2.PhysicsActorType)
                        {
                            case (int)ActorTypes.Agent:
                            case (int)ActorTypes.Prim:
                                break;

                            default:
                                ignore = true; // avatar to terrain and water ignored
                                break;
                        }
                        break;
                    }

                case (int)ActorTypes.Prim:
                    {
                        switch (p2.PhysicsActorType)
                        {
                            case (int)ActorTypes.Agent:
                                dop2ava = true;
                                break;

                            case (int)ActorTypes.Prim:
                                Vector3 relV = p1.rootVelocity - p2.rootVelocity;
                                float relVlenSQ = relV.LengthSquared();
                                if (relVlenSQ > 0.0001f)
                                {
                                    p1.CollidingObj = true;
                                    p2.CollidingObj = true;
                                }
                                p1.getContactData(ref contactdata1);
                                p2.getContactData(ref contactdata2);
                                bounce = contactdata1.bounce * contactdata2.bounce;
                                mu = (float)Math.Sqrt(contactdata1.mu * contactdata2.mu);

                                if (relVlenSQ > 0.01f)
                                    mu *= frictionMovementMult;

                                if(d.GeomGetClass(g2) == d.GeomClassID.TriMeshClass &&
                                    d.GeomGetClass(g1) == d.GeomClassID.TriMeshClass)
                                    smoothMesh = true;
                                break;

                            case (int)ActorTypes.Ground:
                                p1.getContactData(ref contactdata1);
                                bounce = contactdata1.bounce * TerrainBounce;
                                mu = (float)Math.Sqrt(contactdata1.mu * TerrainFriction);

                                Vector3 v1 = p1.rootVelocity;
                                if (Math.Abs(v1.X) > 0.1f || Math.Abs(v1.Y) > 0.1f)
                                    mu *= frictionMovementMult;
                                p1.CollidingGround = true;

                                if(d.GeomGetClass(g1) == d.GeomClassID.TriMeshClass)
                                    smoothMesh = true;
                                break;

                            case (int)ActorTypes.Water:
                            default:
                                ignore = true;
                                break;
                        }
                    }
                    break;

                case (int)ActorTypes.Ground:
                    if (p2.PhysicsActorType == (int)ActorTypes.Prim)
                    {
                        p2.CollidingGround = true;
                        p2.getContactData(ref contactdata2);
                        bounce = contactdata2.bounce * TerrainBounce;
                        mu = (float)Math.Sqrt(contactdata2.mu * TerrainFriction);

//                        if (curContact.side1 > 0) // should be 2 ?
//                            IgnoreNegSides = true;
                        Vector3 v2 = p2.rootVelocity;
                        if (Math.Abs(v2.X) > 0.1f || Math.Abs(v2.Y) > 0.1f)
                            mu *= frictionMovementMult;

                        if(d.GeomGetClass(g2) == d.GeomClassID.TriMeshClass)
                            smoothMesh = true;
                    }
                    else
                        ignore = true;
                    break;

                case (int)ActorTypes.Water:
                default:
                    break;
            }

            if (ignore)
                return;

            IntPtr Joint;
            bool FeetCollision = false;
            int ncontacts = 0;

            int i = 0;

            maxDepthContact = new ContactPoint();
            maxDepthContact.PenetrationDepth = float.MinValue;
            ContactPoint minDepthContact = new ContactPoint();
            minDepthContact.PenetrationDepth = float.MaxValue;

            SharedTmpcontact.geom.depth = 0;
            SharedTmpcontact.surface.mu = mu;
            SharedTmpcontact.surface.bounce = bounce;

            d.ContactGeom altContact = new d.ContactGeom();
            bool useAltcontact = false;
            bool noskip = true;

            if(dop1ava || dop2ava)
                smoothMesh = false;

            while (true)
            {
                noskip = true;
                useAltcontact = false;

                if (dop1ava)
                {
                    if ((((OdeCharacter)p1).Collide(g1, g2, false, ref curContact, ref altContact , ref useAltcontact, ref FeetCollision)))
                    {
                        if (p2.PhysicsActorType == (int)ActorTypes.Agent)
                        {
                            p1.CollidingObj = true;
                            p2.CollidingObj = true;
                        }
                        else if (p2.rootVelocity.LengthSquared() > 0.0f)
                            p2.CollidingObj = true;
                    }
                    else
                        noskip = false;
                }
                else if (dop2ava)
                {
                if ((((OdeCharacter)p2).Collide(g2, g1, true, ref curContact, ref altContact , ref useAltcontact, ref FeetCollision)))
                    {
                    if (p1.PhysicsActorType == (int)ActorTypes.Agent)
                        {
                            p1.CollidingObj = true;
                            p2.CollidingObj = true;
                        }
                    else if (p1.rootVelocity.LengthSquared() > 0.0f)
                        p1.CollidingObj = true;
                    }
                else
                    noskip = false;
                }

                if (noskip)
                {
                    if(useAltcontact)
                        Joint = CreateContacJoint(ref altContact,smoothMesh);
                    else
                        Joint = CreateContacJoint(ref curContact,smoothMesh);

                    if (Joint == IntPtr.Zero)
                        break;

                    d.JointAttach(Joint, b1, b2);

                    ncontacts++;

                    if (curContact.depth > maxDepthContact.PenetrationDepth)
                    {
                        maxDepthContact.Position.X = curContact.pos.X;
                        maxDepthContact.Position.Y = curContact.pos.Y;
                        maxDepthContact.Position.Z = curContact.pos.Z;
                        maxDepthContact.PenetrationDepth = curContact.depth;
                        maxDepthContact.CharacterFeet = FeetCollision;
                    }

                    if (curContact.depth < minDepthContact.PenetrationDepth)
                    {
                        minDepthContact.PenetrationDepth = curContact.depth;
                        minDepthContact.SurfaceNormal.X = curContact.normal.X;
                        minDepthContact.SurfaceNormal.Y = curContact.normal.Y;
                        minDepthContact.SurfaceNormal.Z = curContact.normal.Z;
                    }
                }

                if (++i >= count)
                    break;

                if (!GetCurContactGeom(i, ref curContact))
                    break;
            }

            if (ncontacts > 0)
            {
                maxDepthContact.SurfaceNormal.X = minDepthContact.SurfaceNormal.X;
                maxDepthContact.SurfaceNormal.Y = minDepthContact.SurfaceNormal.Y;
                maxDepthContact.SurfaceNormal.Z = minDepthContact.SurfaceNormal.Z;

                collision_accounting_events(p1, p2, maxDepthContact);
            }
        }
示例#4
0
 public override void getContactData(ref ContactData cdata)
 {
     cdata.mu = mu;
     cdata.bounce = 0;
     cdata.softcolide = false;
 }