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;
}
}