protected override void DoGenerate()
    {
        m_points  = new List <Vector2>();
        m_regions = new List <VoronoiRegion>();

        for (int i = 0; i < NumPoints; ++i)
        {
            float x = Random.value;
            float y = Random.value;

            m_points.Add(new Vector2(x, y));
        }

        Voronoi voronoi = new Voronoi(m_points, new Rectf(0.0f, 0.0f, 1.0f, 1.0f), 30);

        m_points = voronoi.SiteCoords();

        foreach (var region in voronoi.Regions())
        {
            VoronoiRegion newRegion = new VoronoiRegion();
            newRegion.regionPoints = region;
            newRegion.isWater      = Random.Range(0, 2) == 0;

            m_regions.Add(newRegion);
        }
    }
Exemplo n.º 2
0
        public void AddRegion(VoronoiRegion <Vertex2> region)
        {
            PolygonRegionIndex ri = new PolygonRegionIndex();
            PolygonRegion      r  = new PolygonRegion();

            //添加多边形顶点,计算多边形中心点
            Vector3 center = Vector3.zero;

            foreach (var c in region.Cells)
            {
                var z        = na.NoiseValue(c.CircumCenter.X, c.CircumCenter.Y);
                var tmpPoint = new Vector3(c.CircumCenter.X, c.CircumCenter.Y, z);
                var p        = Contain(tmpPoint);
                center += p;
                r.Vertexs.Add(p);
                if (!vertexs.Contains(p))
                {
                    vertexs.Add(p);
                }
            }

            r.position = center / region.Cells.Count;
            ri.center  = center / region.Cells.Count;

            //添加多边形边
            foreach (var e in region.Edges)
            {
                var pA   = Contain(new Vector3(e.From.CircumCenter.X, e.From.CircumCenter.Y));
                var pB   = Contain(new Vector3(e.To.CircumCenter.X, e.To.CircumCenter.Y));
                var edge = Contain(new PolygonEdge(pA, pB));
                r.Edges.Add(edge);
                if (!edges.Contains(edge))
                {
                    edges.Add(edge);
                }
            }

            foreach (var e in region.Edges)
            {
                var pA    = ContainVertexIndex(new Vector3(e.From.CircumCenter.X, e.From.CircumCenter.Y));
                var pB    = ContainVertexIndex(new Vector3(e.To.CircumCenter.X, e.To.CircumCenter.Y));
                var edge  = new PolygonEdgeIndex(pA, pB);
                var index = Contain(edge);
                if (index == -1)
                {
                    edgesIndex.Add(edge);
                    index = edgesIndex.Count - 1;
                }
                ri.EdgesIndex.Add(index);
            }

            regions.Add(r);
            regionsIndex.Add(ri);
        }
Exemplo n.º 3
0
        //Relies on the triangle being located in the local space of the convex object.  The convex transform is used to transform the
        //contact points back from the convex's local space into world space.
        ///<summary>
        /// Generates a contact between the triangle and convex.
        ///</summary>
        ///<param name="contactList">Contact between the shapes, if any.</param>
        ///<returns>Whether or not the shapes are colliding.</returns>
        public override bool GenerateContactCandidates(TriangleShape triangle, out TinyStructList <ContactData> contactList)
        {
            contactList = new TinyStructList <ContactData>();


            Vector3 ab, ac;

            Vector3.Subtract(ref triangle.vB, ref triangle.vA, out ab);
            Vector3.Subtract(ref triangle.vC, ref triangle.vA, out ac);
            Vector3 triangleNormal;

            Vector3.Cross(ref ab, ref ac, out triangleNormal);
            if (triangleNormal.LengthSquared() < Toolbox.Epsilon * .01f)
            {
                //If the triangle is degenerate, use the offset between its center and the sphere.
                Vector3.Add(ref triangle.vA, ref triangle.vB, out triangleNormal);
                Vector3.Add(ref triangleNormal, ref triangle.vC, out triangleNormal);
                Vector3.Multiply(ref triangleNormal, 1 / 3f, out triangleNormal);
                if (triangleNormal.LengthSquared() < Toolbox.Epsilon * .01f)
                {
                    triangleNormal = Toolbox.UpVector; //Alrighty then! Pick a random direction.
                }
            }


            float dot;

            Vector3.Dot(ref triangleNormal, ref triangle.vA, out dot);
            switch (triangle.sidedness)
            {
            case TriangleSidedness.DoubleSided:
                if (dot < 0)
                {
                    Vector3.Negate(ref triangleNormal, out triangleNormal);     //Normal must face outward.
                }
                break;

            case TriangleSidedness.Clockwise:
                if (dot > 0)
                {
                    return(false);    //Wrong side, can't have a contact pointing in a reasonable direction.
                }
                break;

            case TriangleSidedness.Counterclockwise:
                if (dot < 0)
                {
                    return(false);    //Wrong side, can't have a contact pointing in a reasonable direction.
                }
                break;
            }


            Vector3 closestPoint;

            //Could optimize this process a bit.  The 'point' being compared is always zero.  Additionally, since the triangle normal is available,
            //there is a little extra possible optimization.
            lastRegion = Toolbox.GetClosestPointOnTriangleToPoint(ref triangle.vA, ref triangle.vB, ref triangle.vC, ref Toolbox.ZeroVector, out closestPoint);
            float lengthSquared = closestPoint.LengthSquared();
            float marginSum     = triangle.collisionMargin + sphere.collisionMargin;

            if (lengthSquared <= marginSum * marginSum)
            {
                var contact = new ContactData();
                if (lengthSquared < Toolbox.Epsilon)
                {
                    //Super close to the triangle.  Normalizing would be dangerous.

                    Vector3.Negate(ref triangleNormal, out contact.Normal);
                    contact.Normal.Normalize();
                    contact.PenetrationDepth = marginSum;
                    contactList.Add(ref contact);
                    return(true);
                }

                lengthSquared = (float)Math.Sqrt(lengthSquared);
                Vector3.Divide(ref closestPoint, lengthSquared, out contact.Normal);
                contact.PenetrationDepth = marginSum - lengthSquared;
                contact.Position         = closestPoint;
                contactList.Add(ref contact);
                return(true);
            }
            return(false);
        }
        //Relies on the triangle being located in the local space of the convex object.  The convex transform is used to transform the
        //contact points back from the convex's local space into world space.
        ///<summary>
        /// Generates a contact between the triangle and convex.
        ///</summary>
        ///<param name="contactList">Contact between the shapes, if any.</param>
        ///<returns>Whether or not the shapes are colliding.</returns>
        public override bool GenerateContactCandidate(out TinyStructList<ContactData> contactList)
        {
            contactList = new TinyStructList<ContactData>();

            Vector3 ab, ac;
            Vector3.Subtract(ref triangle.vB, ref triangle.vA, out ab);
            Vector3.Subtract(ref triangle.vC, ref triangle.vA, out ac);
            Vector3 triangleNormal;
            Vector3.Cross(ref ab, ref ac, out triangleNormal);
            if (triangleNormal.LengthSquared() < Toolbox.Epsilon * .01f)
            {
                //If the triangle is degenerate, use the offset between its center and the sphere.
                Vector3.Add(ref triangle.vA, ref triangle.vB, out triangleNormal);
                Vector3.Add(ref triangleNormal, ref triangle.vC, out triangleNormal);
                Vector3.Multiply(ref triangleNormal, 1 / 3f, out triangleNormal);
                if (triangleNormal.LengthSquared() < Toolbox.Epsilon * .01f)
                    triangleNormal = Toolbox.UpVector; //Alrighty then! Pick a random direction.

            }

            float dot;
            Vector3.Dot(ref triangleNormal, ref triangle.vA, out dot);
            switch (triangle.sidedness)
            {
                case TriangleSidedness.DoubleSided:
                    if (dot < 0)
                        Vector3.Negate(ref triangleNormal, out triangleNormal); //Normal must face outward.
                    break;
                case TriangleSidedness.Clockwise:
                    if (dot > 0)
                        return false; //Wrong side, can't have a contact pointing in a reasonable direction.
                    break;
                case TriangleSidedness.Counterclockwise:
                    if (dot < 0)
                        return false; //Wrong side, can't have a contact pointing in a reasonable direction.
                    break;

            }

            Vector3 closestPoint;
            //Could optimize this process a bit.  The 'point' being compared is always zero.  Additionally, since the triangle normal is available,
            //there is a little extra possible optimization.
            lastRegion = Toolbox.GetClosestPointOnTriangleToPoint(ref triangle.vA, ref triangle.vB, ref triangle.vC, ref Toolbox.ZeroVector, out closestPoint);
            float lengthSquared = closestPoint.LengthSquared();
            float marginSum = triangle.collisionMargin + sphere.collisionMargin;

            if (lengthSquared <= marginSum * marginSum)
            {
                var contact = new ContactData();
                if (lengthSquared < Toolbox.Epsilon)
                {
                    //Super close to the triangle.  Normalizing would be dangerous.

                    Vector3.Negate(ref triangleNormal, out contact.Normal);
                    contact.Normal.Normalize();
                    contact.PenetrationDepth = marginSum;
                    contactList.Add(ref contact);
                    return true;
                }

                lengthSquared = (float)Math.Sqrt(lengthSquared);
                Vector3.Divide(ref closestPoint, lengthSquared, out contact.Normal);
                contact.PenetrationDepth = marginSum - lengthSquared;
                contact.Position = closestPoint;
                contactList.Add(ref contact);
                return true;

            }
            return false;
        }