Esempio n. 1
0
        protected TreeBranch(int generation, Vector3 from, Vector3 tangent, Vector3 normal, Vector3 binormal, float length, float radius, float offset, TreeData data)
        {
            this.generation = generation;

            this.fromRadius = radius;
            this.toRadius   = (generation == 0) ? 0f : radius *data.RadiusAttenuation;

            this.from = from;

            var rotation = Quaternion.AngleAxis(data.GetRandomAngle(), normal) * Quaternion.AngleAxis(data.GetRandomAngle(), binormal);

            this.to     = from + rotation * tangent * length;
            this.length = length;
            this.offset = offset;

            segments = BuildSegments(data, radius, normal, binormal);

            children = new List <TreeBranch>();
            if (generation > 0)
            {
                int branches = data.GetRandomBranches();
                for (int i = 0; i < branches; i++)
                {
                    // 一番初めの枝は一続きの枝にする
                    bool sequence = (i == 0);

                    int index = sequence ? segments.Count - 1 : data.Range(1, segments.Count - 1);
                    var ratio = 1f * index / (segments.Count - 1);

                    var segment = segments[index];
                    var nt      = segment.Frame.Tangent;
                    var nn      = segment.Frame.Normal;
                    var nb      = segment.Frame.Binormal;

                    var child = new TreeBranch(
                        this.generation - 1,
                        segment.Position,
                        nt,
                        nn,
                        nb,
                        length * Mathf.Lerp(1f, data.LengthAttenuation, ratio),
                        radius * Mathf.Lerp(1f, data.RadiusAttenuation, ratio),
                        offset + length,
                        data
                        );

                    children.Add(child);
                }
            }
        }
        protected TreeBranch(List <TreeBranch> branches, int generation, int generations, Vector3 from, Vector3 tangent, Vector3 normal, Vector3 binormal, float length, float radius, float offset, TreeData data)
        {
            this.generation = generation;

            this.fromRadius = radius;
            this.toRadius   = (generation == 0) ? 0f : radius *data.radiusAttenuation;

            this.from = from;

            var scale    = Mathf.Lerp(1f, data.growthAngleScale, 1f - 1f * generation / generations);
            var rotation = Quaternion.AngleAxis(scale * data.GetRandomGrowthAngle(), normal) * Quaternion.AngleAxis(scale * data.GetRandomGrowthAngle(), binormal);

            this.to = from + rotation * tangent * length;

            this.length = length;
            this.offset = offset;

            segments = BuildSegments(data, fromRadius, toRadius, normal, binormal);

            branches.Add(this);

            children = new List <TreeBranch>();
            if (generation > 0)
            {
                int count = data.GetRandomBranches();
                for (int i = 0; i < count; i++)
                {
                    float ratio;
                    if (count == 1)
                    {
                        // for zero division
                        ratio = 1f;
                    }
                    else
                    {
                        ratio = Mathf.Lerp(0.5f, 1f, (1f * i) / (count - 1));
                    }

                    var index   = Mathf.FloorToInt(ratio * (segments.Count - 1));
                    var segment = segments[index];

                    Vector3 nt, nn, nb;
                    if (ratio >= 1f)
                    {
                        // sequence branch
                        nt = segment.Frame.Tangent;
                        nn = segment.Frame.Normal;
                        nb = segment.Frame.Binormal;
                    }
                    else
                    {
                        var phi = Quaternion.AngleAxis(i * 90f, tangent);
                        // var psi = Quaternion.AngleAxis(data.branchingAngle, normal) * Quaternion.AngleAxis(data.branchingAngle, binormal);
                        var psi = Quaternion.AngleAxis(data.branchingAngle, normal);
                        var rot = phi * psi;
                        nt = rot * tangent;
                        nn = rot * normal;
                        nb = rot * binormal;
                    }

                    var child = new TreeBranch(
                        branches,
                        this.generation - 1,
                        generations,
                        segment.Position,
                        nt,
                        nn,
                        nb,
                        length * Mathf.Lerp(1f, data.lengthAttenuation, ratio),
                        radius * Mathf.Lerp(1f, data.radiusAttenuation, ratio),
                        offset + length,
                        data
                        );

                    children.Add(child);
                }
            }
        }
Esempio n. 3
0
        protected TreeBranch(int generation, int generations, Vector3 from, Vector3 tangent, Vector3 normal, Vector3 binormal, float length, float radius, float offset, TreeData data)
        {
            this.generation = generation;

            this.fromRadius = radius;

            // 枝先である場合は先端の太さが0になる
            this.toRadius = (generation == 0) ? 0f : radius *data.radiusAttenuation;

            this.from = from;

            // 枝先ほど分岐する角度が大きくなる
            var scale = Mathf.Lerp(1f, data.growthAngleScale, 1f - 1f * generation / generations);

            // normal方向の回転
            var qn = Quaternion.AngleAxis(scale * data.GetRandomGrowthAngle(), normal);

            // binormal方向の回転
            var qb = Quaternion.AngleAxis(scale * data.GetRandomGrowthAngle(), binormal);

            // 枝先が向いているtangent方向にqn * qbの回転をかけつつ、枝先の位置を決める
            this.to = from + (qn * qb) * tangent * length;

            this.length = length;
            this.offset = offset;

            // モデル生成に必要な節を構築
            segments = BuildSegments(data, fromRadius, toRadius, normal, binormal);

            children = new List <TreeBranch>();
            if (generation > 0)
            {
                // 分岐する数を取得
                int count = data.GetRandomBranches();
                for (int i = 0; i < count; i++)
                {
                    float ratio; // [0.0 ~ 1.0]
                    if (count == 1)
                    {
                        // 分岐数が1である場合(0除算を回避)
                        ratio = 1f;
                    }
                    else
                    {
                        ratio = Mathf.Lerp(0.5f, 1f, (1f * i) / (count - 1));
                    }

                    // 分岐元の節を取得
                    var index   = Mathf.FloorToInt(ratio * (segments.Count - 1));
                    var segment = segments[index];

                    // 分岐元の節が持つベクトルをTreeBranchに渡すことで滑らかな分岐を得る
                    Vector3 nt = segment.Frame.Tangent;
                    Vector3 nn = segment.Frame.Normal;
                    Vector3 nb = segment.Frame.Binormal;

                    var child = new TreeBranch(
                        this.generation - 1,
                        generations,
                        segment.Position,
                        nt,
                        nn,
                        nb,
                        length * Mathf.Lerp(1f, data.lengthAttenuation, ratio),
                        radius * Mathf.Lerp(1f, data.radiusAttenuation, ratio),
                        offset + length,
                        data
                        );

                    children.Add(child);
                }
            }
        }