Beispiel #1
0
        public override void init()
        {
            if (!inited)
            {
                if (branchType == BranchType.Trank)
                {
                    radiusRate  *= 1.5f;
                    gravityConst = new float[10] {
                        0.0f, 0.15f, 0.25f, 0.50f, 0.25f, 0.0f, -0.15f, -0.25f, -0.40f, 0.0f
                    };
                    gravityLenthNormalized = 0.25f;
                    branchStart            = (int)(3.0f * this.trunkLen);
                }
                if (branchType == BranchType.Branch)
                {
                    height *= 1.1f;

                    step         = 1;
                    steps        = 5;
                    count        = 1;
                    branchStart  = 2;
                    branchEnd    = (MathCore.RandomRange(random, -1.0f, 1.0f) > 0.0f ? 7 : 8);
                    spread       = 0.05f;
                    stepRand     = 180.0f;
                    overAllRand  = 180.0f;
                    forceOverall = 0.0f;
                    overallRoll  = 90.0f;

                    radStart = 0.6f;
                    radEnd   = 0.8f;

                    heightStart = 1.4f;
                    heightEnd   = 1.5f;

                    tiltStart = 60f;
                    tiltEnd   = 35f;
                }
                if (iterationStep == 2)
                {
                    step        = 1;
                    steps       = 4;
                    count       = 1;
                    branchStart = 6;
                    branchEnd   = 7;
                }
                inited = true;
            }

            //添加样条线节点
            spline.Clear();
            for (int i = 0; i < nodes; i++)
            {
                spline.Add(new TreeSplineNode());
            }

            //处理样条线的形态
            UpdateSpline();
        }
Beispiel #2
0
        public void UpdateSpline()
        {
            int i = 0;

            float startRadius, endRadius;

            startRadius = radiusRate * growRate;

            if (branchType == BranchType.Leaves)
            {
                return;
            }
            if (branchType == BranchType.Trank)
            {
                endRadius = startRadius * endRadiusScale;
            }
            else
            {
                endRadius = startRadius * 0.02f;
            }

            Vector3    startPos = centerPos;
            Quaternion q        = rotation;

            lengthStep = height * growRate / (spline.Count);

            /*
             * 在样条线上加一个PerlinNoise,两层(一层是幅度一层是相位)
             * 转轴旋转平面垂直于上一个节点的生长方向,从0开始旋转noiseP度;
             * 然后绕转轴旋转noiseA度。
             */

            int   noiseStep = spline.Count / 4;
            float noiseAmpl = 8;//(height * growRate) / 6.0;

            float[] noiseA = MathCore.PerlinNoise(random, spline.Count, noiseStep, noiseAmpl, null);
            float[] noiseP = MathCore.PerlinNoise(random, spline.Count, noiseStep, 180, null);//相位先设定为2pi

            //重力
            float[] gravityFactor        = MathCore.PerlinNoise(random, spline.Count, noiseStep, 0.1f, gravityConst);
            float   gravityInfectionStep = gravityLenthNormalized / nodes;

            //向心旋转(它的主要组成就是perlinNoise)
            float[] gnarlFactor        = MathCore.PerlinNoise(random, spline.Count, noiseStep, 1.0f, gnarlConst);
            float   gnarlInfectionStep = gnarlLenthNormalized / nodes;

            //样条线
            //第一个点和当前node的数据一致
            spline[i].position       = centerPos;
            spline[i].rotationGlobal = rotation;
            spline[i].tangentGlobal  = (rotation * new Vector3(1, 0, 0));//假定切线在x轴
            spline[i].radius         = startRadius;

            //如果是主干,根部加粗
            if (branchType == BranchType.Trank)
            {
                spline[i].radius *= rootScale;
            }

            for (i = 1; i < spline.Count; i++)
            {
                //位置是由上一个node的生长方向决定的
                spline[i].position = spline[i - 1].position + spline[i - 1].rotationGlobal * new Vector3(0, lengthStep, 0);

                //先让这个节点的方向和上一个节点的方向保持一致
                spline[i].rotationGlobal = spline[i - 1].rotationGlobal;
                spline[i].tangentGlobal  = spline[i - 1].tangentGlobal;

                //当前生长方向
                Vector3 dirc = spline[i].rotationGlobal * Vector3.up;

                ////////////////////
                //处理重力
                ////////////////////

                /*
                 * 重力直接作用于生长方向上。
                 * 相加,规范化,乘以步长。
                 */
                dirc += gravityInfectionStep * gravityFactor[i] * gravityAxis;
                dirc.Normalize();

                ////////////////////
                //处理旋力
                ////////////////////

                /*
                 * 为了处理“旋力”,我们需要求出在以主干为圆心,过当前点的切线向量。
                 * 并将这个向量和当前的生长方向相加,规范化,乘以步长。
                 * 最后根据它求得这一段的rotation。
                 */

                //先拿到当前点相对父树枝原点的位置
                Vector3 posLocal = spline[i].position - parentCenterPos;
                //把这个相对位置绕父树枝的方向旋转2度,与原向量相减规范化得到近似的切线朝向
                Vector3 tang = Quaternion.AngleAxis(1.0f, parentAxis) * posLocal - posLocal;
                tang.Normalize();

                dirc += tang * gnarlInfectionStep * gnarlFactor[i];
                dirc.Normalize();

                ////////////////////
                //计算rotation
                ////////////////////

                spline[i].rotationLocal = Quaternion.FromToRotation(spline[i - 1].rotationGlobal * Vector3.up, dirc);

                ////////////////////
                //处理噪声
                ////////////////////

                //当前旋转方向由噪声决定
                //处理旋转
                //转轴
                Vector3 rotateAxis = Quaternion.AngleAxis(noiseP[i], spline[i - 1].rotationGlobal * new Vector3(0, lengthStep, 0)) * spline[i - 1].tangentGlobal;
                rotateAxis.Normalize();

                //旋转,并保存一个相对与上一个节点的旋转( rotationLocal )
                spline[i].rotationLocal = Quaternion.AngleAxis(noiseA[i], rotateAxis) * spline[i].rotationLocal;

                //更新global
                spline[i].rotationGlobal = spline[i].rotationLocal * spline[i].rotationGlobal;
                spline[i].tangentGlobal  = spline[i].rotationLocal * spline[i].tangentGlobal;

                //处理当前结点截面的大小
                spline[i].radius = ((endRadius - startRadius) * (i / ((float)spline.Count)) + startRadius) * MathCore.RandomRange(random, 0.9f, 1.1f);
            }

            //处理一下rotation
            for (i = 1; i < spline.Count; i++)
            {
                spline[i].rotationLocal  = Quaternion.FromToRotation(spline[i - 1].rotationGlobal * Vector3.up, spline[i].position - spline[i - 1].position);
                spline[i].rotationGlobal = spline[i].rotationLocal * spline[i].rotationGlobal;
            }

            rotation = spline[i - 1].rotationGlobal;
        }
Beispiel #3
0
        public override void generateChildren()
        {
            float dAngle = 360.0f / count;

            if (count == 1)
            {
                dAngle = 0f;
            }

            float overallAngle = overallRoll, stepAngle = 0f;

            int i, j, stepCount = 0;

            for (i = branchStart; i <= branchEnd; i += step)
            {
                stepCount++;
                stepAngle = overallAngle;
                for (j = 0; j < count; j++)
                {
                    //创建树枝
                    TreeVer4_Ultra branch = new TreeVer4_Ultra(random);

                    if (iterationStep == 2)
                    {
                        if (MathCore.RandomRange(random, 0, 10) < 10)
                        {
                            //这是一片叶子
                            branch.branchType = BranchType.Leaves;

                            //这片叶子的旋转
                            float tilt = MathCore.RandomRange(random, -tiltRand, tiltRand) -
                                         (tiltStart - tiltEnd) * ((stepCount - 1) / (float)(steps - 1)) + tiltStart;

                            branch.rotation = Quaternion.AngleAxis(tilt,
                                                                   Quaternion.AngleAxis(stepAngle, Vector3.up) * Vector3.forward) * spline[i].rotationGlobal;

                            //这个树枝的起始位置
                            float spreadF = MathCore.RandomRange(random, -spread, spread);

                            if (spreadF > 0.0f || i == 0)
                            {
                                branch.centerPos = spline[i].position + spline[i].rotationGlobal * Vector3.up *
                                                   spreadF * height * growRate;
                            }
                            else
                            {
                                branch.centerPos = spline[i].position - spline[i - 1].rotationGlobal * Vector3.up *
                                                   (-spreadF) * height * growRate;
                            }

                            //树叶偏离树枝一点
                            branch.centerPos += branch.rotation * (Vector3.up * 0.7f);

                            //这个树枝的生长率(长度与粗细)
                            float radius = spline[i].radius * (((radEnd - radStart) * ((stepCount - 1) / (float)(steps - 1)) + radStart) + MathCore.RandomRange(random, -radRand, radRand));
                            branch.growRate = radius / branch.radiusRate * crownWidth;

                            //下一个树叶要旋转一下
                            stepAngle += dAngle + MathCore.RandomRange(random, -stepRand, stepRand);
                        }
                    }
                    else
                    {
                        //这是一个树枝
                        branch.branchType = BranchType.Branch;

                        //这个树枝依附于当前结点
                        branch.parentCenterPos = spline[i].position;
                        branch.parentAxis      = spline[i].rotationGlobal * Vector3.up;

                        //这个树枝的起始位置
                        float spreadF = MathCore.RandomRange(random, -spread, spread);

                        //hotfix:如果已经在顶上就往下走
                        if (i == (nodes - 1))
                        {
                            spreadF = MathCore.RandomRange(random, spread - 0.05f, -0.05f);
                        }

                        if (spreadF > 0.0f || i == 0)
                        {
                            branch.centerPos = spline[i].position + spline[i].rotationGlobal * Vector3.up *
                                               spreadF * height * growRate;
                        }
                        else
                        {
                            branch.centerPos = spline[i].position - spline[i - 1].rotationGlobal * Vector3.up *
                                               (-spreadF) * height * growRate;
                        }

                        //这个树枝的旋转
                        float tilt = MathCore.RandomRange(random, -tiltRand, tiltRand) -
                                     (tiltStart - tiltEnd) * ((stepCount - 1) / (float)(steps - 1)) + tiltStart;

                        if (branchType == BranchType.Branch)
                        {
                            stepAngle = stepAngle % 360f;
                            if (stepAngle < 90f || stepAngle > 270f)
                            {
                                stepAngle += 90.0f;
                                stepAngle  = stepAngle % 360.0f;

                                stepAngle  = (stepAngle - 90f) * 0.3f + 90f;
                                stepAngle -= 90.0f;
                            }
                            else
                            {
                                stepAngle = (stepAngle - 180f) * 0.3f + 180f;
                            }
                        }

                        branch.rotation = Quaternion.AngleAxis(tilt,
                                                               Quaternion.AngleAxis(stepAngle, Vector3.up) * Vector3.forward) * spline[i].rotationGlobal;

                        //这个树枝的生长率(长度与粗细)
                        float radius = spline[i].radius * (((radEnd - radStart) * ((stepCount - 1) / (float)(steps - 1)) + radStart) + MathCore.RandomRange(random, -radRand, radRand));
                        branch.growRate = radius / branch.radiusRate * crownWidth;

                        //这个树枝会越来越“细长”
                        branch.height *= ((heightEnd - heightStart) * ((stepCount - 1) / (float)(steps - 1)) + heightStart);

                        //下一个树枝要旋转一下
                        stepAngle += dAngle + MathCore.RandomRange(random, -stepRand, stepRand);

                        if (branchType == BranchType.Branch)
                        {
                            //除了第一级枝干,之后的每一级重力常数都要减小
                            branch.gravityLenthNormalized *= 0.7f;
                            branch.gnarlLenthNormalized    = 6.0f;
                        }
                    }

                    //Check iteration steps
                    branch.iterationStep = iterationStep + 1;
                    branch.startGrowRate = startGrowRate;

                    branch.init();

                    child.Add(branch);
                }

                //交错分布
                overallAngle += (dAngle / 2f) + MathCore.RandomRange(random, -overAllRand, overAllRand) + forceOverall;
            }
        }
Beispiel #4
0
        public override void Express(
            World world,
            ref FractalRenderState state
            )
        {
            /////////////////////
            //树叶的情况
            /////////////////////

            float leaveRadius = 4.0f * startGrowRate / 24.0f;

            uint blk = branchBlock;

            if (branchType == BranchType.Leaves)
            {
                TestTree.FillLeaf(world, leafRenderingSetup, state.position + state.scale * centerPos, state.scale * Mathf.Min(growRate * 0.31f, 3.0f) * MathCore.RandomRange(random, 3.0f, 5.0f));
                //Debug.Log(growRate);
                //Debug.Log("Using green branch as leaves");
            }
            else
            {
                /////////////////////
                //树枝的情况
                /////////////////////

                /*
                 * 按圆柱表面坐标系上点的坐标给点标号。圆为横轴,高为纵轴。
                 * 顶点(x,y)坐标:
                 *  rad = x * (2f * Mathf.PI / circleFragments);
                 * Vertex =        (cos(rad) * radius, y * heightStep, sin(rad) * radius);
                 * 顶点(x,y)法线:
                 *  rad = x * (2f * Mathf.PI / circleFragments);
                 * Normal =        (cos(rad), 0, sin(rad))
                 * 构成整个子结构的面:
                 *  for(x = 0; x < circleFragments - 1; x++)
                 *      for(y = 0; y < heightFragments - 1; y++)
                 * Indices =               ( x, y ) ( x + 1, y + 1 ) ( x + 1, y ); ( x, y ) ( x , y + 1 ) ( x + 1, y + 1 )
                 *
                 *  不封口。反正也看不见(
                 */

                //绘制
                int   vert = 0, x, index;
                float rad, radiusReal;

                for (index = 0; index < (spline.Count - 1); index++)
                {
                    TestTree.FillCyclinder(
                        world,
                        blk,
                        (state.rotation * (state.scale * spline[index].position)) + state.position,
                        (state.rotation * (state.scale * spline[index + 1].position)) + state.position,
                        state.scale * spline[index].radius,
                        state.scale * spline[index + 1].radius,
                        state.rotation * (spline[index].rotationGlobal * Vector3.up),
                        state.rotation * (spline[index + 1].rotationGlobal * Vector3.up)
                        );
                    //break;
                }
            }

            //state.centerPos = Vector3.zero;
            //state.rotation = Quaternion.identity;
        }