构造分形树时的问题

时间:2017-01-26 14:07:59

标签: c# unity3d

我一直在尝试使用我在这个fractal tutorial中学到的东西来制作我可以用于自己项目的东西。我想要一个可以在Unity中生成树的脚本。我觉得我已经取得了很大的进步,但已经碰壁了。

我设置脚本的方式是根据两个参数缩放分支:

  • a)publich'childScale'变量。
  • b)从前一个分支发芽的分支数量。

最大的问题是,当儿童成为非均匀尺度物体的父母时,他们会以无意识的方式扭曲。为了绕过,我已经制作了其他GameObjects的预制实例(默认为1,1,1)。这些GameObjects也是包含其他预制实例的其他GameObject的父对象。这是有问题的,因为分形的缩放原则需要从父级继续继承规模,但子预制实例从不传递任何东西。所以我最终必须调整预制实例的比例,使它们能够直接从彼此继承。由于指数修饰符(在'else'之后的Start()中间),下面的脚本“起作用”,但仅当所有分支具有相同数量的分支时,即仅当公共最小和最大分支密度变量相同时整数。

总结一下,我有两个问题,我希望您提出意见。

  • 主要问题:尽管缺乏连续的层次结构,同时允许树的整体形式不均匀,我怎样才能保持分形原理的缩放完整性?

  • 到目前为止,第二个问题是我的'thicknessScaler'变量使我的分支太薄,尤其是它越多。现在它只是将1除以分支的数量,所以我需要一个不会刮掉的东西。

using UnityEngine;
using System.Collections;

public class TreeFractal : MonoBehaviour
{
    public GameObject[] branches; // the last branch is pointed, while all the others are rounded
    public int maxDepth;
    public float childScale; 
    public float maxTwist; // OFF temporarily
    public Vector3 baseBranchSize; // proportions of instantiated prefab
    public int minBranchDensity; // amount of offshoots per node, randomized
    public int maxBranchDensity; 
    public float branchTilt;

    private int depth;
    private int branchDensity;
    private GameObject branch;
    private GameObject instance;
    private TreeFractal grandparent;
    private float displace;
    private float thicknessScaler = 1;
    private float parentDensity;

    private void Start()
    {
        if (depth < maxDepth)
            branch = branches[0];
        else
            branch = branches[1];

        instance = Instantiate(branch); 

        instance.transform.parent = transform; // prefabs (non-uniform proportions) are made the children of uniform-scaled Game Objects.

        if (depth == 0)
        {
            displace = baseBranchSize.y;
            instance.transform.localScale = baseBranchSize;
        }

        else //Multiplication by density^depth is to make up for the shrinking game objects, as the prefab instances do not pass on their scale
            //while the GameObjects do. This only works when all 'depths' of the tree have the same amount of offshoots.
            //Because the GameObject must remain uniform, all scaling of the y axis must occur in the prefab instance.
        {
            displace = baseBranchSize.y * Mathf.Pow(parentDensity, depth);
            //if (depth == 2)3
                print(baseBranchSize.y * Mathf.Pow(parentDensity, depth));
            instance.transform.localScale = new Vector3
            (
                baseBranchSize.x,
                baseBranchSize.y  * Mathf.Pow(parentDensity, depth),
                baseBranchSize.z
            );
        }

        instance.transform.localPosition = new Vector3(0f, 1f * (displace / 2), 0f); //prefab instance pivots at one end of the GameObject, for rotations.
        instance.transform.localRotation = Quaternion.Euler(0f, 0f, 0f);

        transform.Rotate(Random.Range(-maxTwist * ((float)(depth + 1)/ maxDepth), maxTwist * ((float)(depth + 1) / maxDepth)), 0f, 0f);
        //increases the potential randomized twist more, the smaller the branches get.

        if (depth < maxDepth)
        {
            StartCoroutine(CreateChildren());
        }
    }

    private void Update()
    {

    }

    private IEnumerator CreateChildren()
    {
        branchDensity = Random.Range(minBranchDensity, maxBranchDensity + 1);


        for (int i = 0; i < branchDensity; i++)
        {

            yield return new WaitForSeconds(Random.Range(0.1f, 0.5f));

            Quaternion quaternion = BranchRotater(branchDensity, i); 

            new GameObject("Fractal Child").AddComponent<TreeFractal>().
            Initialize(this, i, quaternion);

        }

    }

    private Quaternion BranchRotater (int density, int childIndex) //returns the rotation of the branch depending on the index and amount of branches.
    {
        Quaternion quaternion = Quaternion.Euler
            (0f,
            (360 / density) * childIndex,
            branchTilt
            );
        return quaternion;
    }

    private void Initialize(TreeFractal parent, int childIndex, Quaternion quaternion)
    {
        branches = parent.branches; 
        branchTilt = parent.branchTilt;
        maxDepth = parent.maxDepth; 
        depth = parent.depth + 1;
        baseBranchSize = parent.baseBranchSize;
        maxTwist = parent.maxTwist; 
        transform.parent = parent.transform;
        childScale = parent.childScale;
        minBranchDensity = parent.minBranchDensity;
        maxBranchDensity = parent.maxBranchDensity;
        thicknessScaler = 1f / parent.branchDensity; // I need a better equation here. This scaler is too small.
        transform.localScale = Vector3.one * childScale * thicknessScaler; // reproportions all 3 axes of child GameObject so that
            //the child remains of uniform scale. This must then be compensated for in the scaling of said object's child-prefab. 
        parentDensity = parent.branchDensity;
        transform.localPosition = Vector3.up * parent.displace; //positions child relative to its parent
        transform.localRotation = quaternion;


    }

}

1 个答案:

答案 0 :(得分:0)

如果您构建这样的预制件,则可以在预制件的根节点处应用父对子比例,并在子节点处应用非均匀比例。如果现在将子项的根附加到根节点,则只会统一比例结转。

prefab:
 [root]
   |--->[non-uni]
   |        |---> mesh
   .
   .
   [childRoot]