protected void OnInit( )
        {
            var polyObj  = new GameObject();
            var polyView = polyObj.AddComponent <PolygonView>();

            polyObj.transform.parent = contextView.transform;
            polyObj.name             = "Drawing Path";

            polyView.glUtils = polyObj.AddComponent <_GLUtils>();


            var lineParentObj = new GameObject("LineGroup");

            lineParentObj.transform.parent = polyObj.transform;
            polyView.lineParent            = lineParentObj.transform;

            var pointParentObj = new GameObject("PointGroup");

            pointParentObj.transform.parent = polyObj.transform;
            polyView.pointParent            = pointParentObj.transform;

            polyView.points = new List <PointView> ( );
            polyView.lines  = new List <LineView> ( );

            pathView   = polyView;
            pathEntity = new PolygonEntity( );
        }
示例#2
0
    /// <summary>
    /// Given 2 PolygonEntitites, finds the edge with the least penetration
    /// </summary>
    /// <param name="A"></param>
    /// <param name="B"></param>
    /// <param name="PolygonIndex"> An out parameter giving the index where the Axis of least penetration was found </param>
    /// <returns>returns the value of the axis of least penetration </returns>
    public static float FindAxisLeastPenetration(PolygonEntity A, PolygonEntity B, ref int PolygonIndex)
    {
        float greatestProjection = -100000;
        int   faceIndex          = 0;

        for (int i = 0; i < A.GetVertices().Length; i++)
        {
            Vector Normal          = A.GetFaceNormal(i).Normalized();
            Vector verticePosition = A.GetVertices()[i];

            Vector verticeIndex = B.GetSupportPoint(Normal * -1);
            verticeIndex += B.position;

            Vector DistanceToVertice = verticeIndex - verticePosition;

            float projection = Vector.Dot(DistanceToVertice, Normal);

            if (projection > greatestProjection)
            {
                greatestProjection = projection;
                faceIndex          = i;
            }
        }
        PolygonIndex = faceIndex;
        return(greatestProjection);
    }
示例#3
0
    /// <summary>
    /// Given a CircleEntity and a PolygonEntity, checks if their bounding volumes overlap each other
    /// </summary>
    /// <returns></returns>
    public static bool DetectBoundingVolumeCollision(CircleEntity A, PolygonEntity B)
    {
        float CollisionDistance = A.Radius + B.GetVolumeRadius();

        float dx = A.x - B.x;
        float dy = A.y - B.y;

        return(CollisionDistance * CollisionDistance >= (dx * dx) + (dy * dy));
    }
示例#4
0
    /// <summary>
    /// Given 2 PolygonEntities, checks if their bounding volumes are colliding
    /// </summary>
    /// <returns></returns>
    public static bool DetectBoundingVolumeCollision(PolygonEntity A, PolygonEntity B)
    {
        if (Utils.IsNearEqual(A.GetInvMass(), 0, 0.0001f) && Utils.IsNearEqual(B.GetInvMass(), 0, 0.0001f))
        {
            return(false);
        }

        float CollisionDistance = A.GetVolumeRadius() + B.GetVolumeRadius();

        float dx = A.x - B.x;
        float dy = A.y - B.y;

        return(CollisionDistance * CollisionDistance >= (dx * dx) + (dy * dy));
    }
示例#5
0
        /// <summary>
        /// Returns trimmed polygon after trimming this polygon using the
        /// given array of planes as half spaces.
        /// </summary>
        /// <param name="halfSpaces">Trimming planes.</param>
        /// <returns>Trimmed Polygon</returns>
        public Polygon Trim(Plane[] halfSpaces)
        {
            IPlaneEntity[] hosts  = halfSpaces.ConvertAll(GeometryExtension.ToEntity <Plane, IPlaneEntity>);
            IPolygonEntity entity = PolygonEntity.Trim(hosts);

            if (null == entity)
            {
                return(null);
            }

            Hide(this);
            Hide(halfSpaces);

            return(new Polygon(entity, true));
        }
示例#6
0
        /// <summary>
        /// Vytvoří polygon
        /// </summary>
        /// <param name="points">Kolekce bodů polygonu</param>
        /// <returns>Polygon</returns>
        private void drawPolygonEntity(PointCollection points)
        {
            Point startPosition = new Point(double.NaN, double.NaN);
            Point endPosition   = new Point(double.NaN, double.NaN);

            foreach (Point vertex in points)
            {
                if (double.IsNaN(startPosition.X) || vertex.X < startPosition.X)
                {
                    startPosition.X = vertex.X;
                }
                if (double.IsNaN(startPosition.Y) || vertex.Y < startPosition.Y)
                {
                    startPosition.Y = vertex.Y;
                }
                if (double.IsNaN(endPosition.X) || vertex.X > endPosition.X)
                {
                    endPosition.X = vertex.X;
                }
                if (double.IsNaN(endPosition.Y) || vertex.Y > endPosition.Y)
                {
                    endPosition.Y = vertex.Y;
                }
            }

            PolygonEntity entity = Document.AddNewEntity <PolygonEntity>();

            entity.Move(startPosition);
            double width  = entity.Width = endPosition.X - startPosition.X;
            double height = entity.Height = endPosition.Y - startPosition.Y;

            foreach (Point vertex in points)
            {
                entity.AddPoint(new Point((vertex.X - startPosition.X) / width, (vertex.Y - startPosition.Y) / height));
            }
            this.drawEntity(entity);
            this.selection.SelectWithoutBorder(entity);
        }
    /// <summary>
    /// Finds the polygon generated by the overlap between 2 PolygonEntitites
    /// </summary>
    /// <param name="referencePolygon"> The polygon that will be used as a base for trimming </param>
    /// <param name="polygonToBeTrimmed"> The polygon that will be trimmed s</param>
    /// <returns></returns>
    public static List <Vector> SutherlandHodgmanClipping(PolygonEntity referencePolygon, PolygonEntity polygonToBeTrimmed)
    {
        List <Vector> outputList = polygonToBeTrimmed.GetVerticeList();

        //for each face in reference poly
        for (int i = 0; i < referencePolygon.GetVertices().Length; i++)
        {
            //use output from previous iteration as new input
            List <Vector> inputList = new List <Vector>(outputList);

            //start with an empty output list
            outputList.Clear();

            int secondIndex = i + 1 >= referencePolygon.GetVertices().Length ? 0 : i + 1;
            //get reflected face normal
            Vector StartPoint = referencePolygon.GetVertices()[i];

            Vector Endpoint = referencePolygon.GetVertices()[secondIndex];

            //for every point in incident poly
            for (int j = 0; j < inputList.Count; j++)
            {
                //get v1
                Vector v1             = inputList[j];
                int    secondIncIndex = j + 1 >= inputList.Count ? 0 : j + 1;
                Vector v2             = inputList[secondIncIndex];
                //get v2
                float v1DisToLine = DistancePointToLine(Endpoint, StartPoint, v1);
                float v2DisToLine = DistancePointToLine(Endpoint, StartPoint, v2);

                //entered end point first to get the normal facing towards the polygon
                bool v1IsFront = v1DisToLine > 0;
                bool v2IsFront = v2DisToLine > 0;


                //if v1 + v2 in front
                if (v1IsFront && v2IsFront)
                {
                    //save v2
                    outputList.Add(v2);
                }
                //if v1 in front and v2 in the back
                else if (v1IsFront && !v2IsFront)
                {
                    //save intersection
                    outputList.Add(CollisionDetection.FindLineIntersection(StartPoint, Endpoint, v1, v2));
                }
                //if v1 in back and v2 in the front
                else if (!v1IsFront && v2IsFront)
                {
                    //save intersection and v2
                    outputList.Add(CollisionDetection.FindLineIntersection(StartPoint, Endpoint, v1, v2));
                    outputList.Add(v2);
                }

                //if both are on the back
                //save none
            }
        }
        return(outputList);
    }
    /// <summary>
    /// Given 2 PolygonEntities generates a Manifold , generates a manifold containing the information required to
    /// resolve the collision (if there was one to begin with).
    /// </summary>
    public static Manifold GenerateManifold(PolygonEntity A, PolygonEntity B)
    {
        Manifold Result;

        int FaceA = 0;
        int FaceB = 0;
        //find reference face
        float AtBPenetration = CollisionDetection.FindAxisLeastPenetration(A, B, ref FaceA);

        if (AtBPenetration > 0)
        {
            return(GenerateEmptyManifold());
        }

        float BtAPenetration = CollisionDetection.FindAxisLeastPenetration(B, A, ref FaceB);

        if (BtAPenetration > 0)
        {
            return(GenerateEmptyManifold());
        }



        PolygonEntity refPol;
        PolygonEntity IncPol;
        bool          flip    = false;
        int           refFace = -1234;

        if (BiasGreaterThan(AtBPenetration, BtAPenetration))
        {
            refPol  = A;
            IncPol  = B;
            flip    = false;
            refFace = FaceA;
        }
        else
        {
            refPol  = B;
            IncPol  = A;
            refFace = FaceB;
            flip    = true;
        }

        if (refFace == -1234)
        {
            Console.WriteLine("ERROR");
        }

        Vector Normal = refPol.GetFaceNormal(refFace).Normalized();

        //SUTHERLAND HODGEMAN
        List <Vector> ClippedPolygon = SutherlandHodgmanClipping(A, B);


        Vector Max = Utils.GetSupportPoint(Normal, ClippedPolygon);
        Vector Min = Utils.GetSupportPoint(Normal * -1, ClippedPolygon);

        Vector PenetrationVector = Max - Min;
        float  Penertration      = Mathf.Abs(Vector.Dot(PenetrationVector, Normal));


        //Find points in polygon that are in the reference face
        Vector v1 = A.GetVertices()[FaceA];

        int nextIndex = FaceA + 1 >= A.GetVertices().Length ? 0 : FaceA + 1;

        Vector v2 = A.GetVertices()[nextIndex];
        //Console.WriteLine("V1 " + v1);
        // Console.WriteLine("V2 :  " + v2);
        Vector faceDirection = v2 - v1;

        //Console.WriteLine("START ");
        //PointInFace.RemoveRange(2, PointInFace.Count - 2);

        List <Vector> ContactPoint = new List <Vector>();

        foreach (Vector Point in ClippedPolygon)
        {
            //Console.WriteLine("Point " + Point);
            if (Point.IsEqualTo(v1, 0.01f) || Point.IsEqualTo(v2, 0.01f))
            {
                //Console.WriteLine("Inline v1/v2");
                continue;
            }
            float Distance = DistancePointToLine(v2, v1, Point);
            //Console.WriteLine("DIst " + Distance);
            if (Distance > 0)
            {
                ContactPoint.Add(Point);
            }
        }


        if (ContactPoint.Count >= 2)
        {
            if (ContactPoint[0].IsEqualTo(ContactPoint[1], 0.01f))
            {
                ContactPoint.RemoveAt(1);
            }
        }



        Penertration /= ContactPoint.Count;

        if (flip)
        {
            Normal = -1 * Normal;
        }

        Result.A = A;
        Result.B = B;
        Result.PenetrationDepth = Penertration;
        Result.Normal           = Normal;
        Result.ContactPoint     = ContactPoint;


        //Console.WriteLine("POF C" + ContactPoint.Count);
        Result.IsEmpty = false;
        return(Result);
    }
    /// <summary>
    /// Given a PolygonEntitiy and a Circle Entity, generates a manifold containing the information required to
    /// resolve the collision (if there was one to begin with).
    /// </summary>
    public static Manifold GenerateManifold(PolygonEntity poly, CircleEntity circle)
    {
        Manifold Result;

        Result.A            = poly;
        Result.B            = circle;
        Result.IsEmpty      = false;
        Result.ContactPoint = new List <Vector>();

        Vector relativeCirclePos = circle.position - poly.position;

        float seperation = -10000;
        int   face       = -1234;

        for (int i = 0; i < poly.GetVertices().Length; i++)
        {
            //get the normal
            Vector normal        = poly.GetFaceNormal(i).Normalized();
            Vector circleToPoint = relativeCirclePos - poly.GetLocalSpaceVertices()[i];
            //dot the normal with the circle position
            float currentSeperation = Vector.Dot(normal, circleToPoint);

            //if result of dot is bigger than radius
            if (currentSeperation > circle.Radius)
            {
                return(GenerateEmptyManifold());
            }
            //return

            //if its bigger than stored penetration
            if (currentSeperation > seperation)
            {
                face       = i;
                seperation = currentSeperation;
            }
        }


        Vector v1          = poly.GetVertices()[face];
        int    secondIndex = face + 1 >= poly.GetVertices().Length ? 0 : face + 1;
        Vector v2          = poly.GetVertices()[secondIndex];

        //if point is inside polygon
        if (seperation < EPSILON)
        {
            //normal is negative face normal
            Result.Normal           = poly.GetFaceNormal(face).Normalized() * -1f;
            Result.PenetrationDepth = circle.Radius;
            Result.ContactPoint.Add(Result.Normal * circle.Radius + circle.position);
            //penetration depth is radius
            //contact point is -normal*radius + position
        }


        //determine which voronoi region the circle lies in
        //dot with first point
        float v1Dot = Vector.Dot(circle.position - v1, v2 - v1);
        float v2Dot = Vector.Dot(circle.position - v2, v1 - v2);

        Result.PenetrationDepth = circle.Radius - seperation;

        //dot with second point
        //penetration depth is radius-seperation

        //if dot with first point is negative
        if (v1Dot <= 0)
        {
            if (Mathf.DistanceSquared(v1.x, v1.y, circle.position.x, circle.position.y) > circle.Radius * circle.Radius)
            {
                return(GenerateEmptyManifold());
            }
            Result.Normal = (v1 - poly.position).Normalized();
            Result.ContactPoint.Add(v1);
            //normal is point-center
            //contact point is point
        }
        else if (v2Dot <= 0)
        {
            if (Mathf.DistanceSquared(v2.x, v2.y, circle.position.x, circle.position.y) > circle.Radius * circle.Radius)
            {
                return(GenerateEmptyManifold());
            }
            Result.Normal = (v2 - poly.position).Normalized();
            Result.ContactPoint.Add(v2);
        }
        else
        {
            Result.Normal = poly.GetFaceNormal(face).Normalized();
            Result.ContactPoint.Add(Result.Normal * circle.Radius + circle.position);
        }

        return(Result);
    }
示例#10
0
 public override bool CheckCollision(PolygonEntity other)
 {
     return(CollisionDetection.DetectBoundingVolumeCollision(this, other));;
 }
示例#11
0
 public override Manifold GenerateManifold(PolygonEntity other)
 {
     return(CollisionResolution.GenerateManifold(other, this));
 }
示例#12
0
 public abstract Manifold GenerateManifold(PolygonEntity other);
示例#13
0
 public abstract bool CheckCollision(PolygonEntity other);