using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Unity.Burst; using Unity.Collections; using Unity.Jobs; using UnityEngine; /// /// 贝塞尔算法 边缘细分 Jobs /// public class UnitAlgorithmJobsSideSubdivision : UnitAlgorithm, UnitAlgorithm { /// 贝塞尔算法 边缘细分 Jobs public UnitAlgorithmJobsSideSubdivision() { } public void Compute(DataPlateDesign plateDesign) { int count = plateDesign.plate.plateSides.Count; List plateSides = plateDesign.plate.plateSides; NativeArray jobSubdivisions = new NativeArray(count, Allocator.TempJob); NativeArray jobHandles = new NativeArray(count, Allocator.TempJob); //创建作业任务 for (int i = 0; i < count; i++) { jobSubdivisions[i] = ToJob(plateSides[i]); jobHandles[i] = jobSubdivisions[i].Schedule(); } //执行作业 JobHandle.CompleteAll(jobHandles); //作业结果转换 List points = new List(); for (int i = 0; i < count; i++) { DataPlateSideDesign design = plateSides[i].dataDesign; JobToDesign(design, jobSubdivisions[i]); points.AddRange(design.positions); } plateDesign.points = points.Distinct().ToArray(); //释放作业 jobSubdivisions.Dispose(); jobHandles.Dispose(); } public void Compute(DataPlateBaking plateBaking) { //int count = plateBaking.plate.plateSides.Count; //List plateSides = plateBaking.plate.plateSides; //NativeArray jobSubdivisions = new NativeArray(count, Allocator.Temp); //NativeArray jobHandles = new NativeArray(count, Allocator.Temp); ////创建作业任务 //for (int i = 0; i < count; i++) { // jobSubdivisions[i] = ToJob(plateSides[i]); // jobHandles[i] = jobSubdivisions[i].Schedule(); //} ////执行作业 //JobHandle.CompleteAll(jobHandles); ////作业结果转换 ////List points = new List(); //for (int i = 0; i < count; i++) { // DataPlateSideBaking sideBaking = plateSides[i].dataBaking; // JobToBaking(sideBaking, jobSubdivisions[i]); // //points.AddRange(sideBaking.positions); //} ////plateBaking.points = points.Distinct().ToArray(); } /// 转换作业系统数据 public JobSubdivision ToJob(DataPlateSide side) { JobSubdivision jobSubdivision = new JobSubdivision(); jobSubdivision.bezier = side.bezier; jobSubdivision.aPoint = side.aPoint.position; jobSubdivision.bPoint = side.bPoint.position; jobSubdivision.aBezier = side.aBezier; jobSubdivision.bBezier = side.bBezier; //距离 float distance = Vector2.Distance(jobSubdivision.aPoint, jobSubdivision.bPoint); jobSubdivision.distance = distance; //求余,得商数 jobSubdivision.quotient = side.bezier == Bezier.一阶 ? 2 : 10; jobSubdivision.length = new NativeArray(1, Allocator.TempJob); jobSubdivision.positions = new NativeArray(jobSubdivision.quotient, Allocator.TempJob); jobSubdivision.lines = new NativeArray(jobSubdivision.quotient - 1, Allocator.TempJob); return jobSubdivision; } /// 作业系统数据转换设计数据 public void JobToDesign(DataPlateSideDesign design, JobSubdivision job) { design.length = job.length[0]; design.positions = job.positions.ToArray(); DataPlateLine[] lines = new DataPlateLine[job.lines.Length]; for (int i = 0; i < job.lines.Length; i++) { lines[i] = ToData(job.lines[i]); } design.lines = lines; job.length.Dispose(); job.positions.Dispose(); job.lines.Dispose(); } /// 作业系统数据转换烘焙数据 public void JobToBaking(DataPlateSideBaking baking, JobSubdivision job) { baking.length = job.length[0]; baking.positions = job.positions.ToArray(); DataPlateLine[] lines = new DataPlateLine[job.lines.Length]; for (int i = 0; i < job.lines.Length; i++) { lines[i] = ToData(job.lines[i]); } baking.lines = lines; job.length.Dispose(); job.positions.Dispose(); job.lines.Dispose(); } /// 转换托管数据 public DataPlateLine ToData(JobDataLine jobDataLine) { DataPlateLine line = new DataPlateLine(); line.a = jobDataLine.a; line.b = jobDataLine.b; line.origin = jobDataLine.origin; return line; } /// 作业系统数据 public struct JobDataLine { /// 线段起点a public Vector3 a; /// 线段终点b public Vector3 b; /// 原始距离 public float origin; } [BurstCompile] public struct JobSubdivision : IJob { #region 输入 /// 贝塞尔类型 public Bezier bezier; /// a点 public Vector3 aPoint; /// b点 public Vector3 bPoint; /// a点贝塞尔点 public Vector3 aBezier; /// b点贝塞尔点 public Vector3 bBezier; /// a-b距离 public float distance; /// 细分数 public int quotient; #endregion #region 输出 /// 总长度 public NativeArray length; /// public NativeArray positions; /// 线 public NativeArray lines; #endregion public void Execute() { //细分点 if (bezier == Bezier.一阶) { ComputeBezierA(); } if (bezier == Bezier.二阶) { ComputeBezierB(); } if (bezier == Bezier.三阶) { ComputeBezierC(); } //线段 for (int i = 0; i < quotient - 1; i++) { JobDataLine line = new JobDataLine(); line.a = positions[i]; line.b = positions[i + 1]; line.origin = length[0]; lines[i] = line; length[0] += Vector3.Distance(line.a, line.b); } } public void ComputeBezierA() { positions[0] = aPoint; positions[1] = bPoint; } public void ComputeBezierB() { for (int i = 0; i < quotient; i++) { float t = i * (distance / quotient) / distance; Vector2 position = ComputeBezier(aPoint, aBezier, bPoint, t); positions[i] = position; } } public void ComputeBezierC() { for (int i = 0; i < quotient; i++) { float t = i * (distance / quotient) / distance; Vector2 position = ComputeBezier(aPoint, aBezier, bBezier, bPoint, t); positions[i] = position; } } } /// 商数 public static int Quotient(float distance, float smooth) { int a = (int)(distance * 1000); int b = (int)(smooth * 1000); return Math.DivRem(a, b, out int remainder); } /// /// 一阶贝塞尔算法 /// /// 起点 /// 终点 /// 进度 /// public static Vector3 ComputeBezier(Vector3 a, Vector3 b, float t) { return a + (b - a) * t; } /// /// 二阶贝塞尔算法 /// /// 起点 /// 贝塞尔点 /// 终点 /// 进度 /// 当前进度的曲线点 public static Vector3 ComputeBezier(Vector3 a, Vector3 b, Vector3 c, float t) { Vector3 aa = a + (b - a) * t; Vector3 bb = b + (c - b) * t; return aa + (bb - aa) * t; } /// /// 三阶贝塞尔算法 /// /// 起点 /// 起点的贝塞尔点 /// 终点的贝塞尔点 /// 终点 /// 进度 /// 当前进度的曲线点 public static Vector3 ComputeBezier(Vector3 a, Vector3 b, Vector3 c, Vector3 d, float t) { Vector3 aa = a + (b - a) * t; Vector3 bb = b + (c - b) * t; Vector3 cc = c + (d - c) * t; Vector3 aaa = aa + (bb - aa) * t; Vector3 bbb = bb + (cc - bb) * t; return aaa + (bbb - aaa) * t; } }