Staredit Network > Forums > Technology & Computers > Topic: C# Fractal Tree genetor
C# Fractal Tree genetor
Jul 27 2017, 4:58 am
By: payne  

Jul 27 2017, 4:58 am payne Post #1

:payne:



Here is my current result.
I took and modified the code I was using to complete this tutorial.

I'm pleased with the result, though I'm surprised by one thing: why is it that my initially cubic shape turns into a trapezoid shape as it is being turned around? Is it because of the 3D nature of the rotation (Euler transformations?)?
I wanted rectangular lines the whole way.

Code
using UnityEngine;
using System.Collections;

public class BranchGen : MonoBehaviour {
   
    public Mesh mesh;
    public Material material;
    public int maxDepth;
    public float childScale;

    private int depth;
    private Material[,] materials;
    private static Vector3[] childDirections = {Vector3.up, Vector3.up};
    private static Quaternion[] childOrientations = {Quaternion.Euler(0f, 0f, 35f), Quaternion.Euler(0f, 0f, -35f)};

    private void Start () {
        if (materials == null){
            InitializeMaterials();
        }
        gameObject.AddComponent<MeshFilter>().mesh = mesh;
        gameObject.AddComponent<MeshRenderer>().material = materials[depth, Random.Range(0, 2)];
        if (depth < maxDepth) {
            StartCoroutine(CreateChildren());
        }
    }

    private void InitializeMaterials (){
        materials = new Material[maxDepth +1, 2];
        for (int i = 0; i <= maxDepth; i++){
            float t = i / (maxDepth - 1f);
            t *= t;
            materials[i, 0] = new Material(material);
            materials[i, 0].color = Color.Lerp(Color.white, Color.yellow, t);
            materials[i, 1] = new Material(material);
            materials[i, 1].color = Color.Lerp(Color.white, Color.cyan, t);
        }
        materials[maxDepth,0].color = Color.magenta;
        materials[maxDepth,1].color = Color.red;
    }

    private void Initialize (BranchGen parent, int childIndex) {
        mesh = parent.mesh;
        materials = parent.materials;
        maxDepth = parent.maxDepth;
        depth = parent.depth + 1;
        childScale = parent.childScale;
        transform.parent = parent.transform;
        transform.localScale = new Vector3(1, 1.5f, 1) * childScale;
        transform.localPosition = childDirections[childIndex] * (0.5f + 0.5f * childScale);
        transform.localRotation = childOrientations[childIndex];
    }

    private IEnumerator CreateChildren () {
        for (int i = 0; i < childDirections.Length; i++){
                yield return new WaitForSeconds(.2f);
                new GameObject("BranchGen Child").AddComponent<BranchGen>().Initialize(this, i);
        }
    }
}


I also wanted to make a (1,VARIABLE FLOAT VALUE,1) Mesh to use so that I wouldn't have to change the code itself to quickly look at different results, but couldn't figure out how to do it. I tried using an IF-THEN statement to set the scales (I wanted the first-created Cube Mesh to see its scale modified to that VARIABLE FLOAT VALUE, and then every subsequent one to have yet another VARIABLE (already in the code) modify it as it goes through the iterations).
I couldn't figure out how to get the IF statement to work properly, nor how to plug a FLOAT VAR into this line:
Code
        transform.localScale = new Vector3(1, 1.5f, 1) * childScale;

So that it would look like:
Code
        transform.localScale = new Vector3(1, VARIABLE, 1) * childScale;



I was basically trying to achieve this result:


My next goal after solving this is to create a Snowflake fractal.
I've no idea how to make a starting Mesh that would be a Triangle, though. :(





Jul 27 2017, 4:23 pm Roy Post #2

An artist's depiction of an Extended Unit Death

Quote from payne
I couldn't figure out how to get the IF statement to work properly, nor how to plug a FLOAT VAR into this line:
Code
        transform.localScale = new Vector3(1, 1.5f, 1) * childScale;

So that it would look like:
Code
        transform.localScale = new Vector3(1, VARIABLE, 1) * childScale;
Code
float value = 1.5f;
transform.localScale = new Vector3(1, value, 1) * childScale;

I mean, you're using childScale in the exact same manner...

I'm gonna take a guess and say you're confused as to why a float value ends in "f". If you just put "1.5", that's evaluated to be a double, not a float. You could also write "1.5f" as "(float)1.5", which would be casting a double value to a float value.

Examples:
Code
int i = 15; // integer of value 15
int i = 0xF; // same as above

double d = 1.5d; // double of value 1.5
double d = 1.5; // same as above

float f = 1.5f; // float of value 1.5
float f = (float)1.5; // same as above
float f = 1.5; // compile error

decimal d = 1.5m; // decimal of value 1.5
decimal d = (decimal)1.5; // same as above
decimal d = 1.5; // compile error

The "f" is specifying the type of the value, not the type of the variable you're storing it into. If you do Console.Write(1.5f);, it will print "1.5" to the console, because it's printing a float value of 1.5.

I hope that makes sense.

Post has been edited 3 time(s), last time on Jul 27 2017, 4:50 pm by Roy.




Jul 28 2017, 12:20 am payne Post #3

:payne:

So when I write down 'value', as it is already specified to be a float-type, I do not need to write "valuef" ?

Also, any answer for my rectangular > trapezoid change? I only wanted to 'rotate + stretch'. It seems like I'm using the wrong function.
Finally, I'm still wondering how to create a new Mesh that would be a Rectangle with a variable deciding its size values.




Jul 28 2017, 2:00 am Roy Post #4

An artist's depiction of an Extended Unit Death

Quote from payne
So when I write down 'value', as it is already specified to be a float-type, I do not need to write "valuef" ?
I'm not sure how I can explain it clearer than I already have: the name of a variable does not dictate its type or value. If you did this:
Code
float value = 1.5f;
transform.localScale = new Vector3(1, valuef, 1) * childScale;

You'd get a compile error saying there is no variable named "valuef", which is true, because the only variable you've declared is one called "value". Again, "childScale" is another float variable, and you're using it as one would expect on this very same statement, so I'm not sure where your confusion is coming from.

Quote from payne
Also, any answer for my rectangular > trapezoid change? I only wanted to 'rotate + stretch'. It seems like I'm using the wrong function.
You can reproduce what you're doing in an image editor and see how it's happening. You're stretching the Y-axis on a rotated object, rather than stretching it on its rotated axis. In other words, you're trying to behave like the red box, but you're actually behaving like the blue box:







In short, you're gonna have to change your algorithm for stretching child objects. How you do that is up to you.

Quote from payne
Finally, I'm still wondering how to create a new Mesh that would be a Rectangle with a variable deciding its size values.
Variables are just names with values assigned to them. Anywhere that you could put a raw value into can be a variable, like a parameter to a constructor/method call.




Jul 28 2017, 12:35 pm payne Post #5

:payne:

Those images blew my mind. It all makes sense now.

I don't know enough about programming to know which different functions offer themselves to me for me to be able to work-around my current problem, but at least I get the source of it.

Another friend of mine was making me notice how it might be possible of an effect as well that since the Children take up the added effects of what happens to themselves + what happens to their Parents, it is possible that the iterations happening with the "parent." link on it might screw up with whatever I was trying to achieve.

Also, messing around with the camera's angle to try to figure out what the source of the problem was, I also noticed how somehow despite me trying to change the scale purely on the 'Y' axis (1f, 1.5f, 1f), each child created down the line also happens to be thinner (lower depth scale value).




Jul 31 2017, 12:06 pm payne Post #6

:payne:


May that be the source of this oddity?

I found this, however, that I intend on trying:
https://docs.unity3d.com/ScriptReference/Object.Instantiate.html
Code
public static Object Instantiate(Object original, Vector3 position, Quaternion rotation, Transform parent);

I'll probably just rewrite the whole code to be adapted to the Instantiate function.

Also, Roy, as far as I have figured out, your explanation with the Red/Blue images might be wrong: the transforms I'm doing are local, and as the rotation occurs, the axis rotate with it, don't they?
Just so many weird behaviors... :/

Post has been edited 1 time(s), last time on Jul 31 2017, 12:14 pm by payne.




Options
  Back to forum
Please log in to reply to this topic or to report it.
Members in this topic: None.
[11:50 pm]
O)FaRTy1billion[MM] -- nice, now i have more than enough
[11:49 pm]
O)FaRTy1billion[MM] -- if i don't gamble them away first
[11:49 pm]
O)FaRTy1billion[MM] -- o, due to a donation i now have enough minerals to send you minerals
[2024-4-17. : 3:26 am]
O)FaRTy1billion[MM] -- i have to ask for minerals first tho cuz i don't have enough to send
[2024-4-17. : 1:53 am]
Vrael -- bet u'll ask for my minerals first and then just send me some lousy vespene gas instead
[2024-4-17. : 1:52 am]
Vrael -- hah do you think I was born yesterday?
[2024-4-17. : 1:08 am]
O)FaRTy1billion[MM] -- i'll trade you mineral counts
[2024-4-16. : 5:05 pm]
Vrael -- Its simple, just send all minerals to Vrael until you have 0 minerals then your account is gone
[2024-4-16. : 4:31 pm]
Zoan -- where's the option to delete my account
[2024-4-16. : 4:30 pm]
Zoan -- goodbye forever
Please log in to shout.


Members Online: Roy