예제 #1
0
        /// <summary>
        /// Register a static scene element for getting hit.
        /// </summary>
        /// <param name="owner"></param>
        public static void RegisterBlocker(GameActor owner)
        {
            CollisionPrimitive prim = owner.SRO.CollisionPrim(owner);

            if (prim != null)
            {
                Sys.Register(prim);
            }
            else
            {
                // We're looking for collision prims here but haven't found any.
                // What should happen here?
            }
        }
예제 #2
0
        private void AddChildClone(GameActor owner, CollisionPrimitive src)
        {
            CollisionPrimitive child = src.Clone(owner);

            if (children.Count > 0)
            {
                /// The world sphere for a primitive with no owner is
                /// the sphere when the root is at the origin. That is,
                /// the local sphere with any bone transforms folded in.
                /// That is our local space.
                LocalSphere = UnionBounds(LocalSphere, src.WorldSphere);
            }
            else
            {
                LocalSphere = src.WorldSphere;
            }
            children.Add(child);
        }
예제 #3
0
 private void Register(CollisionPrimitive prim)
 {
     things.Add(prim);
 }
예제 #4
0
        /// <summary>
        /// Start, end and radii are passed in from a mover.  This method tests
        /// this mover's swept ellipsoid against all the non-moving things as
        /// well as all the other movers which appear after it in the list.
        /// The "first" param is the index of the next item in the list.
        ///
        /// The listAll param seems to determine whether we just keep the nearest hit
        /// or keep them all.  It appears that listAll=false is used for physics collision
        /// testing while listAll=true is used for WHEN Bumped testing.  But, of course,
        /// this is just a guess on my part since it's not documented.  Argh.
        /// </summary>
        /// <param name="startPos0">start position of swept sphere</param>
        /// <param name="endPos0">end position of swept sphere</param>
        /// <param name="radii0">Radii of swept ellipsoid.</param>
        /// <param name="first">This is the index of the first mover to check for collisions with.  Start, end, and radii come from the previous mover.  TODO (****) Change numbering so this is more clear.</param>
        /// <param name="listAll">When true, all hits are listed.  When false, only the nearest hit is listed.</param>
        /// <param name="hits"></param>
        /// <returns></returns>
        private bool CollisionCheck(Vector3 startPos0, Vector3 endPos0, Vector3 radii0, int first, bool listAll, List <HitInfo> hits)
        {
            /// These are structs, no real allocation done here.
            CollInfo curCollPrim = new CollInfo();

            curCollPrim.DistSq = Single.MaxValue;

            CollInfo best = new CollInfo();

            best.DistSq = Single.MaxValue;
            bool hit = false;

            // Test the current swept ellipsoid against all the non-moving things.
            List <CollisionPrimitive> relevants = things;

            for (int ithing = 0; ithing < relevants.Count; ++ithing)
            {
                CollisionPrimitive thing = relevants[ithing];

                if (thing.Owner.Ignored)
                {
                    continue;
                }

                // Note we used the Z part of the radii.  So, on squashed movers we
                // might get some intersection.
                // TODO (****) Actually figure out how to test a swept ellipsoid against
                // the Primitive based collision shapes.
                if (thing.Collide(startPos0, endPos0, radii0.Z, ref curCollPrim))
                {
                    if (listAll)
                    {
                        HitInfo hitScratch = MakeHitScratch(curCollPrim, radii0.X);
                        hits.Add(hitScratch);
                        curCollPrim.DistSq = Single.MaxValue;
                    }
                    else
                    if (curCollPrim.DistSq <= best.DistSq)
                    {
                        hit     = true;
                        best    = curCollPrim;
                        endPos0 = best.Center;

                        if (best.Touching)
                        {
                            HitInfo hitScratch = MakeHitScratch(best, radii0.X);
                            hits.Add(hitScratch);
                        }
                    }
                }
            }

            // Test the current mover against the remaining movers in the list.
            // Note that in the case of hit testing blips this index may be -1.
            int curMoverIndex = first - 1;

            // If listAll is true, then we're testing for bump so test the full
            // list since we have to worry about TouchCushions.
            if (listAll)
            {
                first = 0;
            }
            for (int second = first; second < movers.Count; ++second)
            {
                Mover sphere = movers[second];

                // Don't test against self.
                if (second == curMoverIndex)
                {
                    continue;
                }

                if (sphere.Owner.Ignored)
                {
                    continue;
                }

                // Don't collide missiles with their launcher.  Note that this assumes
                // that the launcher is always in the list _ahead_ of the missile.
                MissileChassis mc = movers[second].Owner.Chassis as MissileChassis;
                if (mc != null && curMoverIndex >= 0 && mc.Launcher == movers[curMoverIndex].Owner)
                {
                    continue;
                }

                Vector3 radii1 = sphere.Radius * sphere.Owner.SquashScale;

                Vector3 hitContactPosition = Vector3.Zero;
                Vector3 hitNormal          = Vector3.UnitZ;
                float   hitT    = -1;
                bool    hitTest = SweptPrims.SweptEllipsoidSweptEllipsoid(startPos0, endPos0, radii0, sphere.Center, sphere.Center + sphere.Delta, sphere.Radius * sphere.Owner.SquashScale, ref hitContactPosition, ref hitNormal, ref hitT);

                if (hitTest)
                {
                    Vector3 posAtCollision = MyMath.Lerp(startPos0, endPos0, hitT);
                    // Already touching?
                    if (hitT <= 0)
                    {
                        sphere.SetCollPrimTouching(startPos0, posAtCollision, hitContactPosition, -hitNormal, sphere.Center + hitT * sphere.Delta, ref curCollPrim);
                    }
                    else
                    {
                        sphere.SetCollPrim(startPos0, posAtCollision, hitContactPosition, -hitNormal, sphere.Center + hitT * sphere.Delta, ref curCollPrim);
                    }

                    if (listAll)
                    {
                        HitInfo hitScratch = MakeHitScratch(curCollPrim, radii0.X);
                        hits.Add(hitScratch);
                        curCollPrim.DistSq = Single.MaxValue;
                    }
                    else
                    if (curCollPrim.DistSq <= best.DistSq)
                    {
                        best = curCollPrim;
                        hit  = true;

                        if (best.Touching)
                        {
                            HitInfo hitScratch = MakeHitScratch(best, radii0.X);
                            hits.Add(hitScratch);
                        }
                    }
                } // end if hitTest
            }     // end of loop over other movers.

            if (hit)
            {
                Debug.Assert(!listAll, "Hit shouldn't get set when listing all hits");
                /// If it's touching, we've already applied, otherwise
                /// do it here.
                if (!best.Touching)
                {
                    HitInfo hitScratch = MakeHitScratch(best, radii0.X);
                    hits.Add(hitScratch);
                }
            }
            if (listAll && (hits.Count > 1))
            {
                hits.Sort(comparer);
            }
            return(hits.Count > 0);
        }