private void GenerateSegment(Vector3 startPosition, Quaternion orientation, float segmentGrowth, List <int> startRing) { int segmentNumber = Mathf.FloorToInt(Growth - segmentGrowth); float startScale = Mathf.Pow(segmentGrowth, Species.ScaleExponent); float endScale = Mathf.Pow(segmentGrowth - 1, Species.ScaleExponent); float segmentLength = Species.SegmentLength * startScale; if (Species.SegmentAngleNoise > 0) { Quaternion noiseRotation = Quaternion.LookRotation(Random.insideUnitSphere, Vector3.up); orientation = Quaternion.Lerp(orientation, noiseRotation, Species.SegmentAngleNoise); } // build stem segment geometry int startVC = mg.VertexCount; mg.SetMaterial(0); float sliceAngle = 2 * Mathf.PI / Species.StemSides; if (startRing == null) { startRing = tempIndices.GetNext(); startRing.Clear(); for (int i = 0; i < Species.StemSides; i++) { startRing.Add(mg.AddVertex(RadialPoint(i * sliceAngle, Species.SegmentRadius * startScale, 0))); } } if (segmentGrowth >= 1) { // normal (tube) segment List <int> endRing = tempIndices.GetNext(); endRing.Clear(); for (int i = 0; i < Species.StemSides; i++) { endRing.Add(mg.AddVertex(RadialPoint(i * sliceAngle, Species.SegmentRadius * endScale, segmentLength))); } for (int i = 0; i < Species.StemSides; i++) { int j = (i + 1) % Species.StemSides; mg.AddFace(endRing[i], endRing[j], startRing[j], startRing[i]); } startRing = endRing; } else { // end (cone) segment int endPoint = mg.AddVertex(new Vector3(0, segmentLength, 0)); for (int i = 0; i < Species.StemSides; i++) { int j = (i + 1) % Species.StemSides; mg.AddFace(endPoint, startRing[j], startRing[i]); } } // orient and position stem segment int endVC = mg.VertexCount; mg.RotateVertices(startVC, endVC, orientation); mg.TranslateVertices(startVC, endVC, startPosition); // grow leaves if (segmentNumber > 0 && segmentGrowth > Species.LeafThreshold && Species.LeavesPerSegment > 0) { float leafBaseRotation = segmentNumber * 180 * (Fibonacci[Species.WhorlNumber] / (float)Fibonacci[Species.WhorlNumber + 1]); float leafAngleSeparation = 360f / Species.LeavesPerSegment; for (int i = 0; i < Species.LeavesPerSegment; i++) { Quaternion rotate = Quaternion.AngleAxis(leafBaseRotation + i * leafAngleSeparation, Vector3.up); if (Species.LeafAngleNoise > 0) { Quaternion noiseRotation = Quaternion.LookRotation(Random.insideUnitSphere, Vector3.up); rotate = Quaternion.Lerp(rotate, noiseRotation, Species.LeafAngleNoise); } GenerateLeaf(startPosition, rotate * orientation, segmentGrowth - Species.LeafThreshold); } } // grow a new segment if necessary if (segmentGrowth > 1) { Vector3 endOffset = Vector3.up * segmentLength; Vector3 endPosition = startPosition + orientation * endOffset; GenerateSegment(endPosition, orientation, segmentGrowth - 1, startRing); } }