private void OnSceneGUI() { spline = target as MtreeBezier; handleTransform = spline.transform; handleRotation = Tools.pivotRotation == PivotRotation.Local ? handleTransform.rotation : Quaternion.identity; Vector3 p0 = ShowPoint(0); if (spline.points.Length > 3) { for (int i = 1; i < spline.ControlPointCount; i += 3) { Vector3 p1 = ShowPoint(i); Vector3 p2 = ShowPoint(i + 1); Vector3 p3 = ShowPoint(i + 2); Handles.color = Color.gray; Handles.DrawLine(p0, p1); Handles.DrawLine(p2, p3); Handles.DrawBezier(p0, p3, p1, p2, Color.white, null, 2f); p0 = p3; } } }
public void BezierManager() { if (hasBezier == 1) { mtreeBezier = gameObject.AddComponent <MtreeBezier> (); mtreeBezier.MTreeDoBezier = true; GenerateTree(); } if (mtreeBezier == null) { mtreeBezier = GetComponent <MtreeBezier> (); } if (hasBezier == 0 && mtreeBezier != null) { mtreeBezier.MTreeDoBezier = false; mtreeBezier.MTreeLeafDirection = false; DestroyImmediate(mtreeBezier); GenerateTree(); } }
public void AddTrunk(Vector3 position, Vector3 direction, float length, AnimationCurve radius, float radiusMultiplier, float resolution , float randomness, int creator, AnimationCurve rootShape, float rootRadius, float rootHeight, float RootResolutionMultiplier , float originAttraction) { MtreeBezier bezier = treeTransform.GetComponent <MtreeBezier>(); float remainingLength = length; Node extremity = new Node(position, radius.Evaluate(0) * radiusMultiplier, direction, creator, NodeType.Flare); stems.Add(extremity); if (!bezier || bezier && !bezier.MTreeDoBezier) { while (remainingLength > 0) { float res = resolution; NodeType type = NodeType.Trunk; Vector3 tangent = Vector3.Cross(direction, Random.onUnitSphere); if (length - remainingLength < rootHeight) { tangent /= RootResolutionMultiplier * 2; res *= RootResolutionMultiplier; type = NodeType.Flare; } float branchLength = 1f / res; Vector3 dir = randomness * tangent + extremity.direction * (1 - randomness); Vector3 originAttractionVector = (position - extremity.position) * originAttraction; originAttractionVector.y = 0; dir += originAttractionVector; dir.Normalize(); if (remainingLength <= branchLength) { branchLength = remainingLength; } remainingLength -= branchLength; Vector3 pos = extremity.position + dir * branchLength; float rad = radius.Evaluate(1 - remainingLength / length) * radiusMultiplier; //if (length - remainingLength < rootHeight) // rad += radiusMultiplier * rootRadius * rootShape.Evaluate((length - remainingLength) / rootHeight); Node child = new Node(pos, rad, dir, creator, type, distancToOrigin: length - remainingLength); extremity.children.Add(child); extremity = child; } } if (bezier && bezier.MTreeDoBezier) { length = bezier.GetLength(); remainingLength = length; while (remainingLength > 1f / resolution) { float step = 1 - (remainingLength / length); Vector3 stepDir = bezier.GetDirection(step); Vector3 stepPos = bezier.GetPoint(step) - treeTransform.position; float res = resolution; NodeType type = NodeType.Trunk; Vector3 tangent = Vector3.Cross(direction, Random.onUnitSphere); if (length - remainingLength < rootHeight) { tangent /= RootResolutionMultiplier * 2; res *= RootResolutionMultiplier; type = NodeType.Flare; } float branchLength = 1f / res; Vector3 dir = randomness * tangent + stepDir * (1 - randomness); Vector3 originAttractionVector = (position - stepPos) * originAttraction; originAttractionVector.y = 0; dir += originAttractionVector; dir.Normalize(); if (remainingLength <= branchLength) { branchLength = remainingLength; } remainingLength -= branchLength; Vector3 pos = stepPos + dir * branchLength; float rad = radius.Evaluate(1 - remainingLength / length) * radiusMultiplier; //if (length - remainingLength < rootHeight) // rad += radiusMultiplier * rootRadius * rootShape.Evaluate((length - remainingLength) / rootHeight); Node child = new Node(pos, rad, dir, creator, type, distancToOrigin: length - remainingLength); extremity.children.Add(child); extremity = child; } } }
public void Split(int selection, int expectedNumber, float splitAngle, int creator, float splitRadius, float startLength , float spread, float flatten) { Queue <Node> candidates = GetSplitCandidates(selection, startLength); MtreeBezier bezier = treeTransform.GetComponent <MtreeBezier>(); Vector3 direction = Vector3.zero; if (bezier && bezier.MTreeLeafDirection) { direction = bezier.s_branchdirection; } float totalLength = 0; foreach (Node ext in candidates) { totalLength += (ext.position - ext.children[0].position).magnitude; } float splitPerMeter = expectedNumber / totalLength; float remainder = 0f; foreach (Node ext in candidates) { float distToChild = (ext.position - ext.children[0].position).magnitude; float targetSplitNumber = distToChild * splitPerMeter + remainder; int number = (int)targetSplitNumber; remainder = targetSplitNumber - number; Vector3 randomVect = Random.onUnitSphere; if (flatten > 0) { randomVect = Vector3.Lerp(randomVect, Vector3.up, flatten).normalized *(Random.Range(0, 1) * 2 - 1); } Vector3 tangent = Vector3.Cross(randomVect, ext.direction); Quaternion rot = Quaternion.AngleAxis(360f / number, ext.direction); Vector3 spreadDirection = ext.children[0].direction; for (int i = 0; i < number; i++) { float blend = Random.value * spread; float rad = Mathf.Lerp(ext.radius * splitRadius, ext.children[0].radius * splitRadius, blend); Vector3 pos = ext.position + spreadDirection * blend * distToChild; Vector3 dir = Vector3.LerpUnclamped(ext.direction, tangent, splitAngle * (1 - ext.positionInBranch * .7f)).normalized + direction; float radiusFactor = Mathf.Clamp01(rad); Node child0 = new Node(pos, ext.radius * radiusFactor + rad * (1 - radiusFactor), dir, creator, distancToOrigin: ext.distanceFromOrigin + blend * distToChild); child0.branchVariation = ext.branchVariation; if (ext.type == NodeType.Trunk || ext.type == NodeType.Flare) { child0.type = NodeType.FromTrunk; } Node child1 = new Node(pos + dir * ext.radius / Mathf.Max(0.3f, Vector3.Dot(dir, tangent)) * 1f, rad, dir, creator, distancToOrigin: ext.distanceFromOrigin + blend * distToChild); child1.branchVariation = ext.branchVariation; child0.children.Add(child1); child0.growth.canBeSplit = false; ext.children.Add(child0); tangent = rot * tangent; } } }
public override void OnInspectorGUI() { var gs = new GUIStyle(); gs.fontStyle = FontStyle.Bold; spline = target as MtreeBezier; GUILayout.Space(10); EditorGUI.BeginChangeCheck(); EditorGUILayout.LabelField("MTree Addon", gs); if (spline.MTreeDoBezier) { DoBezier = "Deactivate Bezier Mode"; } else { DoBezier = "Activate Bezier Mode"; } if (GUILayout.Button(DoBezier)) { Undo.RecordObject(spline, DoBezier); spline.MTreeDoBezier = !spline.MTreeDoBezier; EditorUtility.SetDirty(spline); } if (GUILayout.Button("Add Curve")) { Undo.RecordObject(spline, "Add Curve"); spline.AddCurve(); EditorUtility.SetDirty(spline); } if (EditorGUI.EndChangeCheck()) { spline.GetComponent <MtreeComponent>().GenerateTree(); } GUILayout.Space(10); EditorGUI.BeginChangeCheck(); EditorGUILayout.LabelField("Branch / Leaf Directions", gs); if (spline.MTreeLeafDirection) { DoLeaf = "Deactivate Leaf Direction Mode"; } else { DoLeaf = "Activate Leaf Direction Mode"; } if (GUILayout.Button(DoLeaf)) { Undo.RecordObject(spline, DoLeaf); spline.MTreeLeafDirection = !spline.MTreeLeafDirection; EditorUtility.SetDirty(spline); } spline.s_branchdirection = EditorGUILayout.Vector3Field("Branch Growth Direction", spline.s_branchdirection); if (EditorGUI.EndChangeCheck()) { spline.s_branchdirection.x = Mathf.Clamp(spline.s_branchdirection.x, -1, 1); spline.s_branchdirection.y = Mathf.Clamp(spline.s_branchdirection.y, -1, 1); spline.s_branchdirection.z = Mathf.Clamp(spline.s_branchdirection.z, -1, 1); Undo.RecordObject(spline, "Branch Growth Direction"); spline.GetComponent <MtreeComponent>().GenerateTree(); EditorUtility.SetDirty(spline); } GUILayout.Space(10); if (selectedIndex >= 0 && selectedIndex < spline.ControlPointCount) { EditorGUILayout.LabelField("Bezier Position / Mode", gs); DrawSelectedPointInspector(); } }