void CreateTree() { if (oldSeed == null) { oldSeed = new Seed(); oldSeed.InitBranch(); } // If seed hasn't changed return; if (Seed.CompareSeeds(oldSeed, seed)) { return; } if (seed.randomSeedFromObjectHash) { int hash = this.transform.GetHashCode(); if (hash != seed.randomSeed) { seed.randomSeed = hash; } } Seed.CopySeedDataIntoOtherSeed(oldSeed, seed); //FIX: Might be for the better reduce function calls seed.InitBranch(); BranchRung firstTreeRung = new BranchRung { pos = ZERO, rot = new Vector2( -transform.localEulerAngles.z * Mathf.Deg2Rad, transform.localEulerAngles.x * Mathf.Deg2Rad) }; List <Branch> allBranches = new List <Branch>(); // This draws whole Tree Branch tree = new Branch(firstTreeRung, seed, allBranches); // 3D Model Logic: DrawTreeDModel(allBranches); }
public Branch(BranchRung baseRung, Seed seed, List <Branch> root, Seed originalSeed = null) { if (originalSeed == null) { originalSeed = seed; } core = new List <BranchRung>(); root.Add(this); randomGen = new System.Random(seed.randomSeed); int branchSeed = randomGen.Next(); int rungNum = Mathf.CeilToInt(seed.growth); float rungSize = seed.rungSize + (seed.growth * Seed.RUNG_VS_GROWTH_SIZE); float rungNumFloatDifference = seed.growth - (float)rungNum; float treeRadius = seed.treeRadius * seed.growth * .01f;; float treeSegments = Mathf.Round(seed.radialSegments * treeRadius); if (treeSegments < 3) { treeSegments = 3; } float treeScale = 1 / (rungNum * Seed.RUNG_CLOSENESS); branchShape = new System.Random(branchSeed); branchGenerator = new System.Random(branchSeed); core.Add(baseRung); //Accessing first branch BranchRung rootBranch = root[0].core[0]; for (int i = 1; i < rungNum; i++) { BranchRung prevRung = core[i - 1]; BranchRung rung = new BranchRung(); var percInBranch = 1 - ((float)i / (float)rungNum); //init rung.ringData = new List <Vector3>(); // Twisting the branch randomly var rndX = ((float)branchShape.NextDouble()); var rndY = ((float)branchShape.NextDouble()); rung.rot.x = prevRung.rot.x + (seed.halfTwistX - seed.twistX * rndX); rung.rot.y = prevRung.rot.y + (seed.halfTwistY - seed.twistY * rndY); // Straightening up the branch, otherwise it will look like sea weed. if (seed.correctiveBehavior != 0) { rung.rot.x += (rootBranch.rot.x - rung.rot.x) * seed.correctiveBehavior; rung.rot.y += (rootBranch.rot.y - rung.rot.y) * seed.correctiveBehavior; } if (seed.straightness != 0) { rung.rot.x += (baseRung.rot.x - rung.rot.x) * seed.straightness; rung.rot.y += (baseRung.rot.y - rung.rot.y) * seed.straightness; } // Creating new branch rung position var cosY = Mathf.Cos(rung.rot.y); var cartX = (cosY * Mathf.Sin(rung.rot.x)); var cartY = (cosY * Mathf.Cos(rung.rot.x)); var cartZ = Mathf.Sin(prevRung.rot.y); rungSize += (Seed.MIN_RUNG_SIZE - rungSize) * treeScale * Seed.RUNG_CLOSENESS; rung.pos.x = prevRung.pos.x + rungSize * cartX; rung.pos.y = prevRung.pos.y + rungSize * cartY; rung.pos.z = prevRung.pos.z + rungSize * cartZ; // TODO: FIX, randomizer is too random, use FI somehow. if (Mathf.RoundToInt(((float)branchGenerator.NextDouble()) * seed.branchHappening) == 0) { int newBranchSeed = randomGen.Next(); int leftOverGrowth = rungNum - i; fullUtilityRandom = new System.Random(newBranchSeed); // Randomizing branch direction from mother branch. var newRandX = 1f - (2f) * ((float)fullUtilityRandom.NextDouble()); var newRandY = 1f - (2f) * ((float)fullUtilityRandom.NextDouble()); Vector2 newDirection = rung.rot; newDirection.x += newRandX; newDirection.y += newRandY; rung.rot.x -= newRandX * seed.branchSplitForced; rung.rot.y -= newRandY * seed.branchSplitForced; // This ensures the pattern of random generators doesn't break. baseRung = rung; BranchRung newRung = new BranchRung { pos = rung.pos, rot = newDirection }; var reduction = .9f * percInBranch; var newRadialSegments = Mathf.RoundToInt(treeSegments * reduction); if (newRadialSegments < 3) { newRadialSegments = 3; } var newRadius = treeRadius * reduction; if (newRadius < originalSeed.minRadius) { newRadius = originalSeed.minRadius; } Seed newBranchOpts = new Seed { twistX = seed.twistX, twistY = seed.twistY, correctiveBehavior = seed.correctiveBehavior, randomSeed = newBranchSeed, branchHappening = seed.branchHappening, growth = (leftOverGrowth + rungNumFloatDifference) * (1 - .61802f), //TODO: FIX, dir does nothing growthDirection = Vector3.zero, treeRadius = newRadius, radialSegments = newRadialSegments }; newBranchOpts.rungSize = rungSize; newBranchOpts.InitBranch(); Branch newBranch = new Branch(newRung, newBranchOpts, root, originalSeed); } core.Add(rung); } var branchSize = core.Count; for (int i = 0; i < branchSize; i++) { float percInBranch = 1 - ((float)i / (float)branchSize); BranchRung rung = core[i]; rung.ringData = new List <Vector3>(); for (int a = 0; a < treeSegments; a++) { var aF = (float)a; var segmentsF = (float)treeSegments; var pieceAngle = (aF / segmentsF) * Mathf.PI * 2; var currentAngleX = -rung.rot.x; var currentAngleZ = rung.rot.y; var x = Mathf.Cos(pieceAngle) * treeRadius * percInBranch; var z = Mathf.Sin(pieceAngle) * treeRadius * percInBranch; var cosX = Mathf.Cos(currentAngleX); var sinX = Mathf.Sin(currentAngleX); var cosZ = Mathf.Cos(currentAngleZ); var sinZ = Mathf.Sin(currentAngleZ); var Axz = sinX * sinZ; var Ayz = -cosX * sinZ; var Azz = cosZ; var projectX = cosX * x + Axz * z; var projectY = sinX * x + Ayz * z; var projectZ = Azz * z; Vector3 vert = new Vector3 { x = projectX, y = projectY, z = projectZ }; rung.ringData.Add(vert); } } }
void DrawTreeDModel(List <Branch> branches) { // FIX: Change to regular [] arrays. List <Vector3> vertexList = new List <Vector3>(); List <Vector2> uvs = new List <Vector2>(); List <int> trisList = new List <int>(); int branchNum = branches.Count; int vertexSoFar = 0; for (int i = 0; i < branchNum; i++) { List <BranchRung> branch = branches[i].core; var rungNum = branch.Count; var segmentsNum = 0; for (int a = 0; a < rungNum; a++) { BranchRung rung = branch[a]; segmentsNum = rung.ringData.Count; var rungId = segmentsNum * (a - 1); var rungIdU = segmentsNum * (a); if (a > 0) { var lowL = rungId + vertexSoFar + segmentsNum - 1; var lowR = rungId + vertexSoFar; var upL = rungIdU + vertexSoFar + segmentsNum - 1; var upR = rungIdU + vertexSoFar; // tri 1 trisList.Add(upL); trisList.Add(lowR); trisList.Add(lowL); // tri 2 trisList.Add(upL); trisList.Add(upR); trisList.Add(lowR); } // Closing the 3D model for (int u = 0; u < segmentsNum; u++) { var vert = rung.ringData[u] + rung.pos; vertexList.Add(vert); // Tris are entirely ID based this is valid if (a > 0 && u > 0) { var lowL = rungId + vertexSoFar + u - 1; var lowR = rungId + vertexSoFar + u; var upL = rungIdU + vertexSoFar + u - 1; var upR = rungIdU + vertexSoFar + u; // tri 1 trisList.Add(upL); trisList.Add(lowR); trisList.Add(lowL); // tri 2 trisList.Add(upL); trisList.Add(upR); trisList.Add(lowR); } if (showGizmos) { Gizmos.DrawCube(vert, Vector3.one * 0.03f); } } if (showGizmos) { if (a > 0) { BranchRung prevRung = branch[a - 1]; Gizmos.DrawLine(prevRung.pos, rung.pos); } } } vertexSoFar = vertexList.Count; if (showGizmos) { var r = (float)colorRandomizerForGizmos.NextDouble(); var g = (float)colorRandomizerForGizmos.NextDouble(); var b = (float)colorRandomizerForGizmos.NextDouble(); Gizmos.color = new Vector4(r, g, b, 1); } } // TEMP: FIX: Convert lists to Arrays, temporary. Vector3[] verts = new Vector3[vertexSoFar]; for (int i = 0; i < vertexSoFar; i++) { verts[i] = vertexList[i]; } int triCount = trisList.Count; int[] tris = new int[triCount]; for (int i = 0; i < triCount; i++) { tris[i] = trisList[i]; } //FIX: Check garbage collector, meshes are a mess. // Mesh times, create mesh access filter and renderer. MeshFilter meshFilter = GetComponent <MeshFilter>() as MeshFilter; MeshRenderer meshRenderer = GetComponent <MeshRenderer>() as MeshRenderer; treeMesh = new Mesh(); treeMesh.vertices = verts; treeMesh.triangles = tris; //treeMesh.uv = uvs; //not yet meshFilter.mesh = treeMesh; treeMesh.RecalculateBounds(); treeMesh.RecalculateNormals(); }