예제 #1
0
        public virtual bool sphere_intersects_solid(Sphere checkPos, bool centerCheck)
        {
            if (!Sphere.Intersects(checkPos))
            {
                return(false);
            }

            var dist  = Vector3.Dot(SplittingPlane.Normal, checkPos.Center) + SplittingPlane.D;
            var reach = checkPos.Radius - PhysicsGlobals.EPSILON;

            if (dist >= reach)
            {
                return(PosNode.sphere_intersects_solid(checkPos, centerCheck));
            }

            if (dist <= -reach)
            {
                return(NegNode.sphere_intersects_solid(checkPos, centerCheck));
            }

            if (dist < 0.0f)
            {
                if (PosNode.sphere_intersects_solid(checkPos, false))
                {
                    return(true);
                }

                return(NegNode.sphere_intersects_solid(checkPos, centerCheck));
            }
            else
            {
                if (PosNode.sphere_intersects_solid(checkPos, centerCheck))
                {
                    return(true);
                }

                return(NegNode.sphere_intersects_solid(checkPos, false));
            }
        }
예제 #2
0
        public TransitionState find_collisions(Transition transition, float scale)
        {
            var path       = transition.SpherePath;
            var collisions = transition.CollisionInfo;

            var center      = path.LocalSpaceCurrCenter[0].Center;
            var localSphere = path.LocalSpaceSphere[0];

            var movement = localSphere.Center - center;

            if (path.InsertType == InsertType.Placement || path.ObstructionEthereal)
            {
                var clearCell = true;
                if (path.BuildingCheck)
                {
                    clearCell = !path.HitsInteriorCell;
                }

                if (RootNode.sphere_intersects_solid(localSphere, clearCell))
                {
                    return(TransitionState.Collided);
                }
                else
                {
                    return(TransitionState.OK);
                }
            }

            if (path.CheckWalkable)
            {
                return(check_walkable(path, localSphere, scale));
            }

            if (path.StepDown)
            {
                return(step_sphere_down(transition, localSphere, scale));
            }

            Polygon hitPoly = null;

            if (path.Collide)
            {
                var changed  = false;
                var validPos = new Sphere(localSphere);

                RootNode.find_walkable(path, validPos, ref hitPoly, movement, path.LocalSpaceZ, ref changed);

                if (changed)
                {
                    var offset          = validPos.Center - localSphere.Center;
                    var collisionNormal = path.LocalSpacePos.LocalToGlobalVec(offset) * scale;
                    path.AddOffsetToCheckPos(collisionNormal);

                    var contactPlane = hitPoly.Plane.LocalToGlobal(path.CheckPos, path.LocalSpacePos, hitPoly.Plane);
                    contactPlane.D *= scale;

                    collisions.SetContactPlane(contactPlane, false);
                    collisions.ContactPlaneCellID = path.CheckPos.ObjCellID;
                    path.SetWalkable(validPos, hitPoly, path.LocalSpaceZ, path.LocalSpacePos, scale);

                    return(TransitionState.Adjusted);
                }
                else
                {
                    return(TransitionState.OK);
                }
            }

            var contactPoint = Vector3.Zero;
            var obj          = transition.ObjectInfo;

            if (obj.State.HasFlag(ObjectInfoState.Contact))
            {
                if (RootNode.sphere_intersects_poly(localSphere, movement, ref hitPoly, ref contactPoint))
                {
                    return(step_sphere_up(transition, hitPoly.Plane.Normal));
                }

                if (path.NumSphere > 1)
                {
                    Polygon hitPoly_     = null;
                    var     localSphere_ = path.LocalSpaceSphere[1];

                    if (RootNode.sphere_intersects_poly(localSphere_, movement, ref hitPoly_, ref contactPoint))
                    {
                        return(slide_sphere(transition, hitPoly_.Plane.Normal));
                    }

                    if (hitPoly_ != null)
                    {
                        return(NegPolyHit(path, hitPoly_, false));
                    }
                    if (hitPoly != null)
                    {
                        return(NegPolyHit(path, hitPoly, true));
                    }
                }
                return(TransitionState.OK);
            }

            if (RootNode.sphere_intersects_poly(localSphere, movement, ref hitPoly, ref contactPoint) || hitPoly != null)
            {
                if (obj.State.HasFlag(ObjectInfoState.PathClipped))
                {
                    return(collide_with_pt(transition, localSphere, center, hitPoly, contactPoint, scale));
                }

                var collisionNormal = path.LocalSpacePos.LocalToGlobalVec(hitPoly.Plane.Normal);
                path.WalkableAllowance = PhysicsGlobals.LandingZ;
                path.SetCollide(collisionNormal);

                return(TransitionState.Adjusted);
            }
            else if (path.NumSphere > 1)
            {
                var localSphere_ = path.LocalSpaceSphere[1];
                if (RootNode.sphere_intersects_poly(localSphere_, movement, ref hitPoly, ref contactPoint) || hitPoly != null)
                {
                    var collisionNormal = path.LocalSpacePos.LocalToGlobalVec(hitPoly.Plane.Normal);
                    collisions.SetCollisionNormal(collisionNormal);

                    return(TransitionState.Collided);
                }
            }
            return(TransitionState.OK);
        }