public void UpdateSpline() { int i = 0; float startRadius, endRadius; startRadius = radiusRate * growRate; if (branchType == BranchType.Leaves) { return; } if (branchType == BranchType.Trank) { endRadius = startRadius * 0.15f; } 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(spline.Count, noiseStep, noiseAmpl, null); float[] noiseP = MathCore.PerlinNoise(spline.Count, noiseStep, 180, null);//相位先设定为2pi //重力 float[] gravityFactor = MathCore.PerlinNoise(spline.Count, noiseStep, 0.1f, gravityConst); float gravityInfectionStep = gravityLenthNormalized / nodes; //向心旋转(它的主要组成就是perlinNoise) float[] gnarlFactor = MathCore.PerlinNoise(spline.Count, noiseStep, 0.4f, 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 *= 2.0f; } 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; 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) * Random.Range(0.9f, 1.1f); } rotation = spline[i - 1].rotationGlobal; }
public void UpdateSpline() { int i = 0; float startRadius, endRadius; startRadius = radiusRate * growRate; if (branchType == BranchType.Leaves) { return; } if (branchType == BranchType.Trank) { endRadius = startRadius * 0.15f; } else { endRadius = startRadius * 0.02f; } Vector3 startPos = centerPos; Quaternion q = rotation; float 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(spline.Count, noiseStep, noiseAmpl, null); float[] noiseP = MathCore.PerlinNoise(spline.Count, noiseStep, 180, null);//相位先设定为2pi //样条线 //第一个点和当前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 *= 2.0f; } 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 rotateAxis = Quaternion.AngleAxis(noiseP[i], spline[i - 1].rotationGlobal * new Vector3(0, lengthStep, 0)) * spline[i - 1].tangentGlobal; rotateAxis.Normalize(); //旋转 Quaternion quaternion = Quaternion.AngleAxis(noiseA[i], rotateAxis); spline[i].rotationGlobal = quaternion * spline[i].rotationGlobal; spline[i].tangentGlobal = quaternion * spline[i].tangentGlobal; //处理当前结点截面的大小 spline[i].radius = ((endRadius - startRadius) * (i / ((float)spline.Count)) + startRadius) * Random.Range(0.9f, 1.1f); } }