IEnumerator DetectBuildableAreas(List <SurroundedArea> areas, BuildingCondition condition, List <SurroundedArea> output) { output.Clear(); for (int i0 = 0; i0 < areas.Count; ++i0) { var areaPoints = new List <Vector3>(areas[i0].AreaPoints); if (areaPoints.Count == 3) { areaPoints.Add(areaPoints[2]); } if (CanBuildBuilding(areaPoints, condition) != false) { output.Add(new SurroundedArea { AreaPoints = areaPoints }); } if (System.DateTime.Now.Subtract(lastInterruptionTime).TotalMilliseconds >= LinePolygonCreator.kElapsedTimeToInterrupt) { yield return(null); lastInterruptionTime = System.DateTime.Now; } } }
bool CanBuildBuilding(List <Vector3> areaPoints, BuildingCondition condition) { bool canBuild = true; if (IsConvex(areaPoints) == false) { canBuild = false; } else { Vector3 side1 = areaPoints[1] - areaPoints[0]; Vector3 side2 = areaPoints[2] - areaPoints[1]; Vector3 side3 = areaPoints[3] - areaPoints[2]; Vector3 side4 = areaPoints[0] - areaPoints[3]; float area = (Mathf.Abs(Vector3.Cross(side1, side2).y) + Mathf.Abs(Vector3.Cross(side3, side4).y)) * 0.5f; float sideRatio = condition.sideRatio; if (area < condition.minAreaSize || (CalcRatio(side1, side3) >= sideRatio && CalcRatio(side2, side4) >= sideRatio)) { canBuild = false; } else { for (int i0 = 0; i0 < areaPoints.Count; ++i0) { Vector3 pos0 = areaPoints[i0]; Vector3 pos1 = areaPoints[(i0 + 1) % areaPoints.Count]; Vector3 pos2 = areaPoints[(i0 + areaPoints.Count - 1) % areaPoints.Count]; Vector3 dir1 = pos1 - pos0; Vector3 dir2 = pos2 - pos0; float angle = -Vector2.SignedAngle(new Vector2(dir1.x, dir1.z), new Vector2(dir2.x, dir2.z)); angle = angle < 0 ? 360 + angle : angle; if (angle < condition.minAngle || angle > condition.maxAngle) { canBuild = false; break; } } } } return(canBuild); }
//第3引数使用していません public IEnumerator CreateBuildingMesh(List <SurroundedArea> areas, BuildingCondition condition, float buildingInterval = 100f) { lastInterruptionTime = System.DateTime.Now; var allBuildingParameters = new List <BuildingParameter>(); var types = new BuildingParameter.BuildingType[] { BuildingParameter.BuildingType.kBuildingA01, BuildingParameter.BuildingType.kBuildingA02, BuildingParameter.BuildingType.kBuildingA03, BuildingParameter.BuildingType.kBuildingA04, BuildingParameter.BuildingType.kBuildingB01, BuildingParameter.BuildingType.kBuildingB02, BuildingParameter.BuildingType.kBuildingB03, BuildingParameter.BuildingType.kBuildingB04, BuildingParameter.BuildingType.kBuildingC01, BuildingParameter.BuildingType.kBuildingC02, BuildingParameter.BuildingType.kBuildingC03, BuildingParameter.BuildingType.kBuildingC04, BuildingParameter.BuildingType.kBuildingD01, BuildingParameter.BuildingType.kBuildingD02, BuildingParameter.BuildingType.kBuildingD03, BuildingParameter.BuildingType.kBuildingD04, BuildingParameter.BuildingType.kBuildingE01, BuildingParameter.BuildingType.kBuildingE02, BuildingParameter.BuildingType.kBuildingE03, BuildingParameter.BuildingType.kBuildingE04, BuildingParameter.BuildingType.kBuildingF01, BuildingParameter.BuildingType.kBuildingF02, BuildingParameter.BuildingType.kBuildingF03, BuildingParameter.BuildingType.kBuildingF04, BuildingParameter.BuildingType.kBuildingG01, BuildingParameter.BuildingType.kBuildingG02, BuildingParameter.BuildingType.kBuildingG03, BuildingParameter.BuildingType.kBuildingG04, BuildingParameter.BuildingType.kBuildingH01, BuildingParameter.BuildingType.kBuildingH02, BuildingParameter.BuildingType.kBuildingH03, BuildingParameter.BuildingType.kBuildingH04, }; var buildableAreas = new List <SurroundedArea>(); yield return(CoroutineUtility.CoroutineCycle(DetectBuildableAreas(areas, condition, buildableAreas))); int max = Mathf.RoundToInt((float)buildableAreas.Count * Mathf.Clamp01(condition.generationRate)); var randomAreas = new List <SurroundedArea>(); for (int i0 = 0; i0 < max; ++i0) { int randomIndex = random.Next(buildableAreas.Count); randomAreas.Add(buildableAreas[randomIndex]); int lastIndex = buildableAreas.Count - 1; buildableAreas[randomIndex] = buildableAreas[lastIndex]; buildableAreas.RemoveAt(lastIndex); } randomAreas.Sort((a, b) => a.GetCenter().x.CompareTo(b.GetCenter().x)); randomAreas.Sort((a, b) => a.GetCenter().z.CompareTo(b.GetCenter().z)); int sqrtBuildingCount = 3; float buildingRatio = 0.25f; float spacingRatio = (1.0f - buildingRatio * sqrtBuildingCount) / (float)(sqrtBuildingCount - 1); for (int i0 = 0; i0 < randomAreas.Count; ++i0) { IReadOnlyList <Vector3> areaPoints = randomAreas[i0].AreaPoints; float minHeight, maxHeight; DetectRange(condition.heightRanges, out minHeight, out maxHeight); int buildingCountInArea = 0; // var demolishCounts = new int[] { 0, 3, 5 }; // int demolishCount = demolishCounts[ random.Next(demolishCounts.Length)]; int demolishCount = 0; var buildingNumbers = new List <int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; var demolishIndices = new HashSet <int>(); for (int i1 = 0; i1 < demolishCount; ++i1) { int buildingRandomIndex = random.Next(buildingNumbers.Count); demolishIndices.Add(buildingNumbers[buildingRandomIndex]); buildingNumbers.RemoveAt(buildingRandomIndex); } for (int row = 0; row < sqrtBuildingCount; ++row) { Vector3 top1 = Vector3.Lerp(areaPoints[0], areaPoints[3], (buildingRatio + spacingRatio) * row); Vector3 top2 = Vector3.Lerp(areaPoints[1], areaPoints[2], (buildingRatio + spacingRatio) * row); Vector3 bottom1 = Vector3.Lerp(areaPoints[0], areaPoints[3], (buildingRatio + spacingRatio) * row + buildingRatio); Vector3 bottom2 = Vector3.Lerp(areaPoints[1], areaPoints[2], (buildingRatio + spacingRatio) * row + buildingRatio); for (int column = 0; column < sqrtBuildingCount; ++column) { ++buildingCountInArea; if (demolishIndices.Contains(buildingCountInArea) == false) { Vector3 leftTop = Vector3.Lerp(top1, top2, (buildingRatio + spacingRatio) * column); Vector3 rightTop = Vector3.Lerp(top1, top2, (buildingRatio + spacingRatio) * column + buildingRatio); Vector3 rightBottom = Vector3.Lerp(bottom1, bottom2, (buildingRatio + spacingRatio) * column + buildingRatio); Vector3 leftBottom = Vector3.Lerp(bottom1, bottom2, (buildingRatio + spacingRatio) * column); var buildingPoints = new List <Vector3>() { leftTop, rightTop, rightBottom, leftBottom }; var param = new BuildingParameter(buildingPoints); param.SetBuildingType(types[random.Next(types.Length)], random.Next(4)); param.SetBuildingHeight(Mathf.Lerp(minHeight, maxHeight, (float)random.NextDouble())); allBuildingParameters.Add(param); } } } if (System.DateTime.Now.Subtract(lastInterruptionTime).TotalMilliseconds >= LinePolygonCreator.kElapsedTimeToInterrupt) { yield return(null); lastInterruptionTime = System.DateTime.Now; } } int totalBuildingCount = allBuildingParameters.Count; int buildingCountPerMesh = totalBuildingCount / meshCreators.Count; int surplus = totalBuildingCount % meshCreators.Count; for (int i0 = 0; i0 < meshCreators.Count; ++i0) { int startIndex = buildingCountPerMesh * i0; int buildingCount = buildingCountPerMesh + (i0 == meshCreators.Count - 1 ? surplus : 0); List <BuildingParameter> parameters = allBuildingParameters.GetRange(startIndex, buildingCount); if (condition.enabledSort != false) { parameters.Sort((a, b) => (int)a.TextureType - (int)b.TextureType); } meshCreators[i0].BuildingPolygonCreate(parameters, buildingInterval); } }