/// <summary> /// 生成路径的递归函数 /// </summary> /// <param name="lightningSegment">需要划分的线段</param> /// <param name="fractalTime">当前递归次数</param> /// <param name="maxFractalTime">最大递归次数</param> /// <param name="baseAttenuation">基础衰减</param> /// <param name="offsetRange">偏离值的范围</param> /// <param name="direction">闪电方向</param> /// <param name="forward">与闪电方向垂直的一个单位向量</param> /// <param name="right">与闪电方向垂直的一个单位向量</param> /// <param name="branchChance">生成分支的几率</param> private void GetFractcalLightning(LightningSegment lightningSegment, int fractalTime, int maxFractalTime, float baseAttenuation, Vector2 offsetRange, Vector3 direction, Vector3 forward, Vector3 right, float branchChance = 0f) { if (!lightningSegment.isLeaf() || fractalTime > maxFractalTime) { return; } float zOffset = Mathf.Exp(-baseAttenuation * fractalTime) * Random.Range(offsetRange.x, offsetRange.y); float xOffset = Mathf.Exp(-baseAttenuation * fractalTime) * Random.Range(offsetRange.x, offsetRange.y); Vector3 mid = lightningSegment.Middle() + xOffset * right + zOffset * forward; lightningSegment.LeftChild = new LightningSegment(lightningSegment.start, mid); lightningSegment.LeftChild.fractal = fractalTime + 1; lightningSegment.LeftChild.uv = lightningSegment.uv - LightningCreator.arrayForUV[lightningSegment.LeftChild.fractal]; lightningSegment.RightChild = new LightningSegment(mid, lightningSegment.end); lightningSegment.RightChild.fractal = fractalTime + 1; lightningSegment.RightChild.uv = lightningSegment.uv + LightningCreator.arrayForUV[lightningSegment.RightChild.fractal]; GetFractcalLightning(lightningSegment.LeftChild, fractalTime + 1, maxFractalTime, baseAttenuation, offsetRange, direction, forward, right, branchChance); GetFractcalLightning(lightningSegment.RightChild, fractalTime + 1, maxFractalTime, baseAttenuation, offsetRange, direction, forward, right, branchChance); if (Random.Range(0f, 1f) < branchChance) { //制作h形片段 zOffset = Mathf.Exp(-baseAttenuation * fractalTime) * Random.Range(offsetRange.x, offsetRange.y); xOffset = Mathf.Exp(-baseAttenuation * fractalTime) * Random.Range(offsetRange.x, offsetRange.y); float yOffset = Mathf.Exp(-baseAttenuation * fractalTime) * Random.Range(offsetRange.x, offsetRange.y); Vector3 branchEnd = lightningSegment.Middle() + xOffset * right + zOffset * forward + yOffset * direction; lightningSegment.Branch = new LightningSegment(mid, branchEnd); lightningSegment.Branch.fractal = fractalTime + 1; lightningSegment.Branch.uv = lightningSegment.uv + LightningCreator.arrayForUV[lightningSegment.Branch.fractal]; GetFractcalLightning(lightningSegment.Branch, fractalTime + 1, maxFractalTime, baseAttenuation, offsetRange, direction, forward, right, branchChance); } }
/// <summary> /// 填充Mesh的递归函数 /// </summary> /// <param name="lightningSegment">需要生成Mesh的线段</param> /// <param name="vertices"></param> /// <param name="triangle"></param> /// <param name="uv"></param> /// <param name="obPos">摄像机位置</param> /// <param name="radius">当前的闪电粗细</param> /// <param name="attenuation">分支闪电的衰减程度</param> /// <param name="idx">顶点序号</param> private void SegmentToMesh(LightningSegment lightningSegment, List <Vector3> vertices, List <int> triangle, List <Vector2> uv, Vector3 obPos, float radius, float attenuation, ref int idx) { if (lightningSegment.isLeaf()) { Vector3 zMid = lightningSegment.Middle(); Vector3 zNormal = Vector3.Cross(zMid - obPos, lightningSegment.end - lightningSegment.start).normalized; var finalR = radius * attenuation; if (lightningSegment.Branch == null) { //Z型片段的Mesh生成 vertices.Add(lightningSegment.start + finalR * zNormal); vertices.Add(lightningSegment.start - finalR * zNormal); vertices.Add(lightningSegment.end + finalR * zNormal); vertices.Add(lightningSegment.end - finalR * zNormal); triangle.Add(idx + 1); triangle.Add(idx); triangle.Add(idx + 2); triangle.Add(idx + 1); triangle.Add(idx + 2); triangle.Add(idx + 3); uv.Add(new Vector2(1, lightningSegment.uv)); uv.Add(new Vector2(0, lightningSegment.uv)); uv.Add(new Vector2(1, lightningSegment.uv)); uv.Add(new Vector2(0, lightningSegment.uv)); idx += 4; } } else { SegmentToMesh(lightningSegment.LeftChild, vertices, triangle, uv, obPos, radius, attenuation, ref idx); SegmentToMesh(lightningSegment.RightChild, vertices, triangle, uv, obPos, radius, attenuation, ref idx); if (lightningSegment.Branch != null) { SegmentToMesh(lightningSegment.Branch, vertices, triangle, uv, obPos, radius * attenuation, attenuation, ref idx); } } }