- Home /
Recursive Tree Loop? How do i make the matrix-array?
I would like to make fractal tree in Unity3d, omitting branch angles and lengths, just to instantiate cubes as a tree, like 2,4,8,16... i look for solution all day and i figure it could take me days yet? Should i use an array to store and recall a list of coordinates that each new branch should be at? would it contain 2 or 16 values?
Here is an interactive JS code for trees: http://www.processing.org/learning/topics/tree.html
It uses the following code, please bypass the canvas, rotations, stalk length, i'd be so happy to just have a tree like in the image.
branch(120);
}
void branch(float h) {
// Each branch will be 2/3rds the size of the previous one
h *= 0.66;
// All recursive functions must have an exit condition!!!!
// Here, ours is when the length of the branch is 2 pixels or less
if (h > 2) {
pushMatrix(); // Save the current state of transformation (i.e. where are we now)
rotate(theta); // Rotate by theta
line(0, 0, 0, -h); // Draw the branch
translate(0, -h); // Move to the end of the branch
branch(h); // Ok, now call myself to draw two new branches!!
popMatrix(); // Whenever we get back here, we "pop" in order to restore the previous matrix state
// Repeat the same thing, only branch off to the "left" this time!
pushMatrix();
rotate(-theta);
line(0, 0, 0, -h);
translate(0, -h);
branch(h);
popMatrix();
} }
here is my funny attempt thus far:
var bullet : Transform;
private var rot : Quaternion;
function Start()
{
for (var j : float = 0; j<10; j++)
{
for (var i : float = 0; i<10; i++)
{
rot.eulerAngles = Vector3(0,10,0);//Rotation to use with instatiation
var InstantiateObject = Instantiate(bullet, Vector3(Mathf.Sin(i*432)*i*j,j*5,Mathf.Cos(i*4375)*i*j), rot);//call clones
InstantiateObject.localScale += Vector3(25-j*2,22-j*2,22-j*2);//resize clones
}
}
}
Answer by Herman-Tulleken · Jul 21, 2011 at 07:27 AM
Try this as a staring point:
public class CubeSpawn : MonoBehaviour
{
public GameObject cubePrefab;
public GameObject root;
private Vector3[] CORNERS =
{
new Vector3(-1, 1, -1),
new Vector3(-1, 1, 1),
new Vector3(1, 1, 1),
new Vector3(1, 1, -1),
};
public void Start()
{
AddChildren(root, 0.5f, 5);
}
public void AddChildren(GameObject parent, float childToParentRatio, int depth)
{
foreach (Vector3 corner in CORNERS)
{
GameObject cube = (GameObject) Instantiate(cubePrefab);
Vector3 newPosition = parent.transform.TransformPoint(corner * 0.5f);
//align parent and child
cube.transform.rotation = parent.transform.rotation;
cube.transform.position = newPosition;
cube.transform.localScale *= childToParentRatio;
if(depth > 0)
{
AddChildren(cube, childToParentRatio * childToParentRatio, depth - 1);
}
}
}
public Vector3 prod(Vector3 v1, Vector3 v2)
{
return new Vector3(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z);
}
}
Put the script on an empty game object. Drag in the parent (you can modify it later to instantiate or whatever), and drag in your cube prefab.
The function above is called recursively on the new corners; the depth value makes sure it is not called indefinitely.
Thankyou so much! That's very interesting. i will take a long while to understand and tailor it for other shapes now. I had to add the line "using UnityEngine;" at the top.
the childToParentRatio was scaling exponentially small so i changed line 37 to this: AddChildren(cube, childToParentRatio - (childToParentRatio /2), depth - 1);
because otherwise you could only see the first 3 rows although it would make more sense to write:
AddChildren(cube, childToParentRatio - (childToParentRatio *.6), depth - 1);
but it wouldnt let me! CubeSpawn.AddChildren(UnityEngine.GameObject, float, int)' Argument
#2' cannot convert double' expression to type
float'
so it's saying 0.6 is a double not a float? so i have to declare a var as a float and then say it is 0.6? ok i get it. brb ;)
For float literals, just put an f, for example, 0.6f
.
what is the most computationally efficient way to use such a structure in Unity3d? should "combine mesh" to reduce draw calls, should i do some postprocessing to cull hiddent vertexes and objects? I was only just beginning JS, even instantiation seems very tricky in C#, i haven't yet managed to instantiate the central parent cube.
I think you may want to ask a separate question for that; I am not a 3D model optimisation guru :P.
Answer by vestax_ion · Sep 06, 2011 at 05:19 PM
Here is a JS version of your C# script:
var cubePrefab: GameObject ;
var root : GameObject ;
private var corners = new Array (Vector3(-1, 1, -1), Vector3(-1, 1, 1),Vector3(1, 1, 1),Vector3(1, 1, -1));
function Start()
{
var root = Instantiate(cubePrefab,Vector3.zero,Quaternion.identity);
AddChildren( root,0.5, 4);
}
function AddChildren( ploppy, ratio ,depth)
{
for (var x = 0; x < 4; x++)
{
var cube = Instantiate(cubePrefab,Vector3.zero,Quaternion.identity);
//align parent and child
//cube.transform.rotation = prt.transform.rotation;
cube.transform.position = ploppy.transform.TransformPoint(corners[x]*.5);
cube.transform.localScale *= ratio;
if(depth > 0)
{
AddChildren( cube, ratio - (ratio*.6) , depth - 1);
}
}
}
Answer by tonydincau · Feb 01, 2013 at 08:15 AM
There is some info and a source project to draw reference from here http://tonydincau.com/fractal-trees/
Your answer
Follow this Question
Related Questions
Large matrix formation and multiplication 0 Answers
How to correctly shorten this script using arrays and iterations 2 Answers
Checking an array variable in C# vs JavaScript 3 Answers
OverlapSphere for parallel arrays 1 Answer
Create a button from an int, remove button when clicked, and never load it again 1 Answer