private static List <BranchArmature> CreateBranches(int count, TreeArmature armature) { var branches = new List <BranchArmature>(); var trunkSize = armature.trunkVertices.Count; var branchPointCandidates = new List <int>(); for (var i = 0; i < trunkSize; i++) { if (i > Mathf.RoundToInt(trunkSize * .33f) && i < trunkSize - Mathf.RoundToInt(trunkSize * .1f)) { branchPointCandidates.Add(i); } } // Find highest value for normalizing var max = branchPointCandidates.Max(); // Select #count branch points on tree var branchPoints = new List <int>(count); do { for (var i = 0; i < branchPointCandidates.Count && branchPoints.Count < count; i++) { var branchPoint = branchPointCandidates[i]; var chance = (float)branchPoint / max * .75f; if (Random.value < chance) { if (!branchPoints.Contains(branchPoint)) { branchPoints.Add(branchPoint); } } } } while (branchPoints.Count != count); foreach (var branchPoint in branchPoints) { var branchOrigin = armature.trunkVertices[branchPoint]; var branch = CreateBranchArmature(branchOrigin, trunkSize - 1 - branchPoint - Mathf.RoundToInt(trunkSize * .1f), armature.SegmentHeight, armature.variance); branch.RotateVertices(branchOrigin, Quaternion.Euler(0, Random.Range(0, 360), Random.value * armature.variance)); branches.Add(new BranchArmature { branchVertices = branch, branchVertexIndex = branchPoint }); } armature.branches = branches; return(branches); }
private void Update() { if (armature != TreeMeshGenerator.Armature) { armature = TreeMeshGenerator.Armature; if (!keepChildren) { foreach (Transform obj in transform) { Destroy(obj.gameObject); } } var lines = new List <List <Vector3> > { armature.trunkVertices }; armature.branches?.ForEach(branch => lines.Add(branch.branchVertices)); var i = 0; foreach (var vertList in lines) { var obj = new GameObject($"branch{i}"); obj.transform.SetParent(transform, false); var gen = new MeshGenerator(); gen.AddVertices(vertList); var mf = obj.AddComponent <MeshFilter>(); mf.sharedMesh = gen.GetMesh($"branch{i}"); obj.AddComponent <MeshRenderer>(); var vis = obj.AddComponent <NormalVisualiser>(); vis.drawLines = true; vis.showGizmos = true; vis.showMeshInfoOnSelect = false; i++; } } }
public static Mesh CreateTree(int vertCount, float radius, float height, int subdivisions, float variance, int branchCount) { var meshGen = new MeshGenerator(); var armature = CreateArmature(subdivisions, height, variance); var branches = CreateBranches(branchCount, armature); armature.branches = branches; Armature = armature; // Trunk { // Create trunk edge loops var edgeloops = new List <List <Vector3> >(armature.trunkVertices.Count); for (var i = 0; i < armature.trunkVertices.Count; i++) { var circle = CreateCircle(vertCount, radius * Mathf.Sqrt(1 - (float)i / subdivisions), armature.trunkVertices[i]); edgeloops.Add(circle); meshGen.AddVertices(circle); } // Bridge trunk edge loops for (var i = 0; i < subdivisions; i++) { meshGen.BridgeEdgeLoops(edgeloops[i], edgeloops[i + 1]); } } // Branches { foreach (var branch in branches) { var divisions = branch.branchVertices.Count - 1; var edgeloops = new List <List <Vector3> >(branch.branchVertices.Count); for (var i = 0; i < branch.branchVertices.Count; i++) { var branchPointRadius = radius * Mathf.Sqrt(1 - (float)branch.branchVertexIndex / subdivisions); var circle = CreateCircle(vertCount, branchPointRadius * .7f * Mathf.Sqrt(1 - (float)i / divisions), branch.branchVertices[i]); Vector3 rotationDir; if (i == 0 || i == branch.branchVertices.Count - 1) { rotationDir = branch.branchVertices[i]; } else { rotationDir = branch.branchVertices[i - 1] + branch.branchVertices[i]; } circle.RotateVertices(branch.branchVertices[i], Quaternion.LookRotation(rotationDir, Vector3.down)); edgeloops.Add(circle); meshGen.AddVertices(circle); } // Bridge edge loops for (var i = 0; i < divisions; i++) { meshGen.BridgeEdgeLoops(edgeloops[i], edgeloops[i + 1]); } } } var mesh = meshGen.GetMesh("Tree"); mesh.RecalculateNormals(); return(mesh); }