Esempio n. 1
0
        private bool GetCurContactGeom(int index, ref SafeNativeMethods.ContactGeom newcontactgeom)
        {
            IntPtr ContactgeomsArray = m_scene.ContactgeomsArray;

            if (ContactgeomsArray == IntPtr.Zero || index >= CollisionContactGeomsPerTest)
            {
                return(false);
            }

            IntPtr contactptr = new IntPtr(ContactgeomsArray.ToInt64() + (Int64)(index * SafeNativeMethods.ContactGeom.unmanagedSizeOf));

            newcontactgeom = (SafeNativeMethods.ContactGeom)Marshal.PtrToStructure(contactptr, typeof(SafeNativeMethods.ContactGeom));
            return(true);
        }
Esempio n. 2
0
        // This is the standard Near. g1 is the ray
        private void near(IntPtr space, IntPtr g1, IntPtr g2)
        {
            if (g2 == IntPtr.Zero || g1 == g2)
            {
                return;
            }

            if (m_contactResults.Count >= CurrentMaxCount)
            {
                return;
            }

            if (SafeNativeMethods.GeomIsSpace(g2))
            {
                try
                {
                    SafeNativeMethods.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
                }
                catch (Exception e)
                {
                    m_log.WarnFormat("[PHYSICS Ray]: Unable to Space collide test an object: {0}", e.Message);
                }
                return;
            }

            int count = 0;

            try
            {
                count = SafeNativeMethods.CollidePtr(g1, g2, CollisionContactGeomsPerTest, m_scene.ContactgeomsArray, SafeNativeMethods.ContactGeom.unmanagedSizeOf);
            }
            catch (Exception e)
            {
                m_log.WarnFormat("[PHYSICS Ray]: Unable to collide test an object: {0}", e.Message);
                return;
            }

            if (count == 0)
            {
                return;
            }

            /*
             *          uint cat1 = d.GeomGetCategoryBits(g1);
             *          uint cat2 = d.GeomGetCategoryBits(g2);
             *          uint col1 = d.GeomGetCollideBits(g1);
             *          uint col2 = d.GeomGetCollideBits(g2);
             */

            uint         ID = 0;
            PhysicsActor p2 = null;

            m_scene.actor_name_map.TryGetValue(g2, out p2);

            if (p2 == null)
            {
                return;
            }

            switch (p2.PhysicsActorType)
            {
            case (int)ActorTypes.Prim:

                RayFilterFlags thisFlags;

                if (p2.IsPhysical)
                {
                    thisFlags = RayFilterFlags.physical;
                }
                else
                {
                    thisFlags = RayFilterFlags.nonphysical;
                }

                if (p2.Phantom)
                {
                    thisFlags |= RayFilterFlags.phantom;
                }

                if (p2.IsVolumeDtc)
                {
                    thisFlags |= RayFilterFlags.volumedtc;
                }

                if ((thisFlags & CurrentRayFilter) == 0)
                {
                    return;
                }

                ID = ((OdePrim)p2).LocalID;
                break;

            case (int)ActorTypes.Agent:

                if ((CurrentRayFilter & RayFilterFlags.agent) == 0)
                {
                    return;
                }
                else
                {
                    ID = ((OdeCharacter)p2).LocalID;
                }
                break;

            case (int)ActorTypes.Ground:

                if ((CurrentRayFilter & RayFilterFlags.land) == 0)
                {
                    return;
                }
                break;

            case (int)ActorTypes.Water:

                if ((CurrentRayFilter & RayFilterFlags.water) == 0)
                {
                    return;
                }
                break;

            default:
                break;
            }

            SafeNativeMethods.ContactGeom curcontact = new SafeNativeMethods.ContactGeom();

            // closestHit for now only works for meshs, so must do it for others
            if ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0)
            {
                // Loop all contacts, build results.
                for (int i = 0; i < count; i++)
                {
                    if (!GetCurContactGeom(i, ref curcontact))
                    {
                        break;
                    }

                    ContactResult collisionresult = new ContactResult();
                    collisionresult.ConsumerID = ID;
                    collisionresult.Pos.X      = curcontact.pos.X;
                    collisionresult.Pos.Y      = curcontact.pos.Y;
                    collisionresult.Pos.Z      = curcontact.pos.Z;
                    collisionresult.Depth      = curcontact.depth;
                    collisionresult.Normal.X   = curcontact.normal.X;
                    collisionresult.Normal.Y   = curcontact.normal.Y;
                    collisionresult.Normal.Z   = curcontact.normal.Z;
                    lock (m_contactResults)
                    {
                        m_contactResults.Add(collisionresult);
                        if (m_contactResults.Count >= CurrentMaxCount)
                        {
                            return;
                        }
                    }
                }
            }
            else
            {
                // keep only closest contact
                ContactResult collisionresult = new ContactResult();
                collisionresult.ConsumerID = ID;
                collisionresult.Depth      = float.MaxValue;

                for (int i = 0; i < count; i++)
                {
                    if (!GetCurContactGeom(i, ref curcontact))
                    {
                        break;
                    }

                    if (curcontact.depth < collisionresult.Depth)
                    {
                        collisionresult.Pos.X    = curcontact.pos.X;
                        collisionresult.Pos.Y    = curcontact.pos.Y;
                        collisionresult.Pos.Z    = curcontact.pos.Z;
                        collisionresult.Depth    = curcontact.depth;
                        collisionresult.Normal.X = curcontact.normal.X;
                        collisionresult.Normal.Y = curcontact.normal.Y;
                        collisionresult.Normal.Z = curcontact.normal.Z;
                    }
                }

                if (collisionresult.Depth != float.MaxValue)
                {
                    lock (m_contactResults)
                        m_contactResults.Add(collisionresult);
                }
            }
        }