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); } }
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); }
//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; }