public void Break(Vector2 position) { var area = Area; Debug.Log(area); if (area > MinBreakArea) { var calc = new VoronoiCalculator(); var clip = new VoronoiClipper(); var sites = new Vector2[3]; for (int i = 0; i < sites.Length; i++) { var dist = Mathf.Abs(NormalizedRandom(0.0f, 1.0f / 2.0f)); var angle = 2.0f * Mathf.PI * Random.value; sites[i] = position + new Vector2( dist * Mathf.Cos(angle), dist * Mathf.Sin(angle)); } var diagram = calc.CalculateDiagram(sites); var clipped = new List <Vector2>(); for (int i = 0; i < sites.Length; i++) { clip.ClipSite(diagram, Polygon, i, ref clipped); if (clipped.Count > 0) { var newGo = Instantiate(gameObject, transform.parent); newGo.transform.localPosition = transform.localPosition; newGo.transform.localRotation = transform.localRotation; var bs = newGo.GetComponent <BreakableSurface>(); bs.Thickness = Thickness; bs.Polygon.Clear(); bs.Polygon.AddRange(clipped); var childArea = bs.Area; var rb = bs.GetComponent <Rigidbody>(); rb.mass = Rigidbody.mass * (childArea / area); } } gameObject.SetActive(false); Destroy(gameObject); } }
// calcula o diagrama de voronoi link para a implementação utilizada: https://github.com/OskarSigvardsson/unity-delaunay // serve mais para ser usar a triangulação de delaunay do resultado do diagrama public void BuildVoronoi() { var points2d = Graham.GetPointVectorList(); GK.VoronoiCalculator voronoiCalculator = new GK.VoronoiCalculator(); Diagram = voronoiCalculator.CalculateDiagram(Graham.GetPointVectorList()); //var extends = Map.GetComponent<MeshFilter>().mesh.bounds.size; //extends.Scale(Map.transform.localScale); VoronoiMesh = CreateVoronoiMesh(Diagram); BuildGraph(); }
public void GenerateCity() { // use our seed for generation Random.State currentRNGState = Random.state; Random.InitState(citySeed); myCity = new City(); myCity.thisCity = new GameObject("NewCity"); myCity.cityNoiseOffset = new Vector2(Random.Range(-10000, 10000), Random.Range(-10000, 10000)); GK.VoronoiDiagram cityDiagram = new GK.VoronoiDiagram(); //generate points List <Vector2> points = CreateCityPoint(myCity.cityNoiseOffset);// calulate voroni fracture sites //calculate city cityDiagram = new GK.VoronoiCalculator().CalculateDiagram(points);//calculate vorino diagram (ie roads seperating suburbs) using out sites //bounding List <Vector2> Polygon = new List <Vector2>(); Polygon.Add(new Vector2(0, 0)); Polygon.Add(new Vector2(citySize.x, 0)); Polygon.Add(new Vector2(citySize.x, citySize.y)); Polygon.Add(new Vector2(0, citySize.y)); List <Vector2> clippedSite = new List <Vector2>(); for (int siteIndex = 0; siteIndex < cityDiagram.Sites.Count; siteIndex++) { new GK.VoronoiClipper().ClipSite(cityDiagram, Polygon, siteIndex, ref clippedSite);// clip each of our suburbs if (clippedSite.Count > 0) { // assign and create a suburb object Suburb newSuburb = new Suburb(); myCity.suburbs.Add(newSuburb); newSuburb.thisSuburb = new GameObject("Suburb"); newSuburb.sitePosition = cityDiagram.Sites[siteIndex]; newSuburb.thisSuburb.transform.position = new Vector3(newSuburb.sitePosition.x, 0, newSuburb.sitePosition.y); newSuburb.thisSuburb.transform.SetParent(myCity.thisCity.transform); newSuburb.borders = new List <Vector2>(clippedSite); float xCoord = myCity.cityNoiseOffset.x + newSuburb.sitePosition.x / citySize.x * noiseScale; float yCoord = myCity.cityNoiseOffset.x + newSuburb.sitePosition.y / citySize.y * noiseScale; float noiseValue = curve.Evaluate(Mathf.PerlinNoise(xCoord, yCoord)); for (int i = 0; i < curve.keys.Length; i++)//set which type of suburb will be generated bassed off our noise weight at the suburbs position { if (noiseValue == curve.keys[i].value) { switch (i) { case 0: { newSuburb.suburbType = residentialSettings; break; } case 1: { newSuburb.suburbType = urbanSettings; break; } default: { newSuburb.suburbType = citySettings; break; } } } } newSuburb.seed = Random.Range(int.MinValue, int.MaxValue); } } Random.state = currentRNGState; }
//subdivide our suburb into blocks public void GenerateBlocks(float spacing, float deviation = 0, float alignmentRotation = 0) { //set our seed for the suburb Random.State currentRNGState = Random.state; Random.InitState(seed); float minX = float.MaxValue, maxX = float.MinValue, minY = float.MaxValue, maxY = float.MinValue; Vector2 rotationPivot = new Vector2(0, 0); List <Vector2> shrunkBorders = new List <Vector2>(borders); List <Vector2> sites = new List <Vector2>(); // shrink our borders so our points arnt created to close to the edge, this will result in blocks that are to small shrunkBorders = CityTest.Shrink(shrunkBorders, spacing / 2); if (shrunkBorders.Count >= 3) { for (int i = 0; i < shrunkBorders.Count; i++)//find anchorPoint { if (shrunkBorders[i].x < rotationPivot.x) { rotationPivot.x = shrunkBorders[i].x; } if (shrunkBorders[i].y < rotationPivot.y) { rotationPivot.y = shrunkBorders[i].y; } } //find rotate boarders for alignment and find bounding volume for (int i = 0; i < shrunkBorders.Count; i++) { shrunkBorders[i] = shrunkBorders[i].RotateAroundPoint(rotationPivot, alignmentRotation);// Vector2.MoveTowards(shrunkBorders[i].RotateAroundPoint(rotationPivot, alignmentRotation), borderCenter, spacing/2);// spacing/2); if (shrunkBorders[i].x > maxX) { maxX = shrunkBorders[i].x; } else if (shrunkBorders[i].x < minX) { minX = shrunkBorders[i].x; } if (shrunkBorders[i].y > maxY) { maxY = shrunkBorders[i].y; } else if (shrunkBorders[i].y < minY) { minY = shrunkBorders[i].y; } } //triangulate out polygon so we can check if created points are within our poly GK.DelaunayTriangulation triangulation = new GK.DelaunayCalculator().CalculateTriangulation(shrunkBorders); float xCenterOffset = ((maxX - minX) % spacing) / 2; float yCenterOffset = ((maxY - minY) % spacing) / 2; for (float x = minX - xCenterOffset; x < maxX; x += spacing) { for (float y = minY - yCenterOffset; y < maxY; y += spacing) { Vector2 newPoint = new Vector2(x + Random.Range(-deviation, deviation), y + Random.Range(-deviation, deviation)); // generate a points i a grid for (int i = 0; i < triangulation.Triangles.Count; i += 3) // if the point is contained within our polygon { if (GK.Geom.PointInTriangle(newPoint, triangulation.Vertices[triangulation.Triangles[i]], triangulation.Vertices[triangulation.Triangles[i + 1]], triangulation.Vertices[triangulation.Triangles[i + 2]])) { Vector2 rotatedPoint = newPoint.RotateAroundPoint(rotationPivot, -alignmentRotation); sites.Add(rotatedPoint);// rotate our aligned point to its original rotation and add it to the block site list break; } } } } } if (sites.Count >= 3) // we can only create a diagram if we have more then 2 verts { GK.VoronoiDiagram blockVoronoiDiagram = new GK.VoronoiCalculator().CalculateDiagram(sites); // generate our streets and blocks in our suburb for (int i = 0; i < blockVoronoiDiagram.Sites.Count; i++) { List <Vector2> clippedSite = null; if (blockVoronoiDiagram.FirstEdgeBySite.Count > 0) ////THIS IS NEEDED BECAUSE THE DIAGRAM CAN BE INVALID SOMETIMES { new GK.VoronoiClipper().ClipSite(blockVoronoiDiagram, borders, i, ref clippedSite); // clip our block by our suburb if (clippedSite.Count > 0) { Block newBlock = new Block();// create and assign the block newBlock.borders = new List <Vector2>(clippedSite); newBlock.parentSuburb = this; newBlock.seed = Random.Range(int.MinValue, int.MaxValue); newBlock.blockPosition = blockVoronoiDiagram.Sites[i]; newBlock.thisBlock = new GameObject("Block"); newBlock.thisBlock.transform.SetParent(thisSuburb.transform); newBlock.thisBlock.transform.localPosition = new Vector3(newBlock.blockPosition.x, 0, newBlock.blockPosition.y); myBlocks.Add(newBlock); } else { Debug.LogError("SUBURB SITE AFTER CLIPPED WASNT VALID"); } } else////THIS IS NEEDED BECAUSE THE DIAGRAM CAN BE INVALID SOMETIMES if its not valid make the entire subrb a block { Debug.LogWarning("SITE COULTNT BE CREATED BECASUE DIAGRAM DOESNT HAVE STARTING EDGES"); Block newBlock = new Block(); newBlock.borders = new List <Vector2>(borders); newBlock.parentSuburb = this; newBlock.seed = Random.Range(int.MinValue, int.MaxValue); newBlock.blockPosition = sitePosition; newBlock.thisBlock = new GameObject("Block"); newBlock.thisBlock.transform.SetParent(thisSuburb.transform); newBlock.thisBlock.transform.localPosition = new Vector3(newBlock.blockPosition.x, 0, newBlock.blockPosition.y); myBlocks.Add(newBlock); break; } } } else// if the suburb has less then 3 verts it cant be split so we make the entire suburb a block { Block newBlock = new Block(); newBlock.borders = new List <Vector2>(borders); newBlock.parentSuburb = this; newBlock.seed = Random.Range(int.MinValue, int.MaxValue); newBlock.blockPosition = sitePosition; newBlock.thisBlock = new GameObject("Block"); newBlock.thisBlock.transform.SetParent(thisSuburb.transform); newBlock.thisBlock.transform.localPosition = new Vector3(newBlock.blockPosition.x, 0, newBlock.blockPosition.y); myBlocks.Add(newBlock); } Random.state = currentRNGState; }