1
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 烘焙顶点计算
|
||||
/// </summary>
|
||||
public class UnitAlgorithmBakingVertex : UnitAlgorithm<DataPlateBaking> {
|
||||
|
||||
/// <summary> 烘焙顶点计算 </summary>
|
||||
public UnitAlgorithmBakingVertex() { }
|
||||
|
||||
public void Compute(DataPlateBaking plateBaking) {
|
||||
DataBorder border = plateBaking.border;
|
||||
Vector3[] points = border.points;
|
||||
|
||||
//计算内部顶点
|
||||
//plateBaking.grid = new GridTool<DataPlateVertex>(border.GridWide, border.GridHigh, (x, y) => {
|
||||
// Vector3 position = border.MinPoint + new Vector3(x * border.smooth, y * border.smooth);
|
||||
// DataPlateVertex vertex = new DataPlateVertex();
|
||||
// vertex.isValid = FindPlateInside(points, position);
|
||||
// vertex.position = position;
|
||||
// return vertex;
|
||||
//});
|
||||
|
||||
//List<DataPlateSide> plateSides = plateBaking.plate.plateSides;
|
||||
//边缘所有的线段
|
||||
//for (int i = 0; i < plateSides.Count; i++) {
|
||||
//Compute(plateSides[i], border.GridWide, border.GridHigh, border, border.smooth, plateBaking.grid);
|
||||
//}
|
||||
}
|
||||
/// <summary> 向网格和边缘写入顶点数据 </summary>
|
||||
private void Compute(DataPlateSide side, int wide, int high, DataBorder border, float smooth, GridTool<DataPlateVertex> grid) {
|
||||
DataPlateLine[] lines = side.dataBaking.lines;
|
||||
List<SideVertex> sideVertices = new List<SideVertex>();
|
||||
//计算水平线段顶点
|
||||
for (int x = 0; x < wide; x++) {
|
||||
Vector3 a = new Vector3(border.minX + x * smooth, border.minY - 1);
|
||||
Vector3 b = new Vector3(border.minX + x * smooth, border.maxY + 1);
|
||||
for (int i = 0; i < lines.Length; i++) {
|
||||
DataPlateVertex vertex = Compute(a, b, lines[i], smooth, border, grid);
|
||||
if (vertex == null) { continue; }
|
||||
float distance = Vector3.Distance(lines[i].a, vertex.position) + lines[i].origin;
|
||||
SideVertex sideVertex = new SideVertex();
|
||||
sideVertex.distance = distance;
|
||||
sideVertex.vertex = vertex;
|
||||
sideVertices.Add(sideVertex);
|
||||
}
|
||||
}
|
||||
//计算垂直线段顶点
|
||||
for (int y = 0; y < high; y++) {
|
||||
Vector3 a = new Vector3(border.minX - 1, border.minY + y * smooth);
|
||||
Vector3 b = new Vector3(border.maxX + 1, border.minY + y * smooth);
|
||||
for (int i = 0; i < lines.Length; i++) {
|
||||
DataPlateVertex vertex = Compute(a, b, lines[i], smooth, border, grid);
|
||||
if (vertex == null) { continue; }
|
||||
float distance = Vector3.Distance(lines[i].a, vertex.position) + lines[i].origin;
|
||||
SideVertex sideVertex = new SideVertex();
|
||||
sideVertex.distance = distance;
|
||||
sideVertex.vertex = vertex;
|
||||
sideVertices.Add(sideVertex);
|
||||
}
|
||||
}
|
||||
sideVertices.Sort();
|
||||
List<DataPlateVertex> vertices = new List<DataPlateVertex>();
|
||||
for (int i = 0; i < sideVertices.Count; i++) {
|
||||
vertices.Add(sideVertices[i].vertex);
|
||||
}
|
||||
//side.vertices = vertices.ToArray();
|
||||
}
|
||||
/// <summary> 向网格写入边缘顶点数据 </summary>
|
||||
private DataPlateVertex Compute(Vector3 a, Vector3 b, DataPlateLine line, float smooth, DataBorder border, GridTool<DataPlateVertex> grid) {
|
||||
//计算交点
|
||||
if (!TryGetIntersectPoint(a, b, line.a, line.b, out Vector3 IntersectPoint)) { return null; }
|
||||
//计算顶点xy
|
||||
Vector3 offset = new Vector3(smooth, smooth, 0) * 0.3f;
|
||||
Vector3 position = IntersectPoint - border.MinPoint + offset;
|
||||
int vertexX = Mathf.FloorToInt(position.x / smooth);
|
||||
int vertexY = Mathf.FloorToInt(position.y / smooth);
|
||||
//填充数据
|
||||
DataPlateVertex vertex = grid.Get(vertexX, vertexY);
|
||||
vertex.isValid = true;
|
||||
vertex.position = IntersectPoint;
|
||||
return vertex;
|
||||
}
|
||||
|
||||
public class SideVertex : IComparable<SideVertex> {
|
||||
public float distance;
|
||||
public DataPlateVertex vertex;
|
||||
|
||||
public int CompareTo(SideVertex other) {
|
||||
return other.distance >= distance ? 1 : -1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> 转角法查询位置是否在板片内 </summary>
|
||||
public static bool FindPlateInside(Vector3[] points, Vector3 position) {
|
||||
double angles = 0;
|
||||
for (int i = 0; i < points.Length; i++) {
|
||||
Vector3 a = points.LoopIndex(i + 0) - position;
|
||||
Vector3 b = points.LoopIndex(i + 1) - position;
|
||||
float angle = Vector2.SignedAngle(a, b);
|
||||
angles += angle;
|
||||
}
|
||||
int normal = (int)(angles * 1000);
|
||||
return normal > 1000;
|
||||
}
|
||||
/// <summary>
|
||||
/// 计算AB与CD两条线段的交点.
|
||||
/// </summary>
|
||||
/// <param name="a">A点</param>
|
||||
/// <param name="b">B点</param>
|
||||
/// <param name="c">C点</param>
|
||||
/// <param name="d">D点</param>
|
||||
/// <param name="intersectPos">AB与CD的交点</param>
|
||||
/// <returns>是否相交 true:相交 false:未相交</returns>
|
||||
private bool TryGetIntersectPoint(Vector3 a, Vector3 b, Vector3 c, Vector3 d, out Vector3 intersectPos) {
|
||||
intersectPos = Vector3.zero;
|
||||
|
||||
Vector3 ab = b - a;
|
||||
Vector3 ca = a - c;
|
||||
Vector3 cd = d - c;
|
||||
|
||||
Vector3 v1 = Vector3.Cross(ca, cd);
|
||||
// 不共面
|
||||
if (Mathf.Abs(Vector3.Dot(v1, ab)) > 1e-6) { return false; }
|
||||
// 平行
|
||||
if (Vector3.Cross(ab, cd).sqrMagnitude <= 1e-6) { return false; }
|
||||
|
||||
Vector3 ad = d - a;
|
||||
Vector3 cb = b - c;
|
||||
// 快速排斥
|
||||
if (Mathf.Min(a.x, b.x) > Mathf.Max(c.x, d.x) || Mathf.Max(a.x, b.x) < Mathf.Min(c.x, d.x)
|
||||
|| Mathf.Min(a.y, b.y) > Mathf.Max(c.y, d.y) || Mathf.Max(a.y, b.y) < Mathf.Min(c.y, d.y)
|
||||
|| Mathf.Min(a.z, b.z) > Mathf.Max(c.z, d.z) || Mathf.Max(a.z, b.z) < Mathf.Min(c.z, d.z)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 跨立试验
|
||||
if (Vector3.Dot(Vector3.Cross(-ca, ab), Vector3.Cross(ab, ad)) > 0
|
||||
&& Vector3.Dot(Vector3.Cross(ca, cd), Vector3.Cross(cd, cb)) > 0) {
|
||||
Vector3 v2 = Vector3.Cross(cd, ab);
|
||||
float ratio = Vector3.Dot(v1, v2) / v2.sqrMagnitude;
|
||||
intersectPos = a + ab * ratio;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e8b300a54238da848b5628cef749aeb2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -11,6 +11,32 @@ public class UnitAlgorithmBezier : UnitAlgorithm<DataPlate> {
|
||||
/// <summary> 贝塞尔算法 </summary>
|
||||
public UnitAlgorithmBezier() { }
|
||||
|
||||
public void Compute(DataPlate data) {
|
||||
List<Vector3> points = new List<Vector3>();
|
||||
for (int i = 0; i < data.plateSides.Count; i++) {
|
||||
Compute(data.plateSides[i]);
|
||||
//points.AddRange(data.plateSides[i].positions);
|
||||
}
|
||||
//去除重复边缘点
|
||||
points = points.Distinct().ToList();
|
||||
//data.edgePoints = points;
|
||||
}
|
||||
public void Compute(DataPlateSide data) {
|
||||
DataBezier dataBezier = new DataBezier();
|
||||
dataBezier.bezier = data.bezier;
|
||||
//dataBezier.smooth = data.plate.smooth;
|
||||
dataBezier.aPoint = data.aPoint.position;
|
||||
dataBezier.bPoint = data.bPoint.position;
|
||||
dataBezier.aBezier = data.aBezier;
|
||||
dataBezier.bBezier = data.bBezier;
|
||||
|
||||
dataBezier.Compute();
|
||||
|
||||
//data.length = dataBezier.length;
|
||||
//data.positions = dataBezier.positions.ToArray();
|
||||
//data.lines = dataBezier.lines.ToArray();
|
||||
}
|
||||
|
||||
public class DataBezier {
|
||||
//输入
|
||||
public float smooth;
|
||||
@@ -22,97 +48,57 @@ public class UnitAlgorithmBezier : UnitAlgorithm<DataPlate> {
|
||||
//输出
|
||||
public float length;
|
||||
public List<Vector3> positions = new List<Vector3>();
|
||||
public List<DataLine> lines = new List<DataLine>();
|
||||
}
|
||||
|
||||
public void Compute(DataPlate data) {
|
||||
List<Vector3> points = new List<Vector3>();
|
||||
for (int i = 0; i < data.sides.Count; i++) {
|
||||
Compute(data.sides[i]);
|
||||
points.AddRange(data.sides[i].positions);
|
||||
public List<DataPlateLine> lines = new List<DataPlateLine>();
|
||||
/// <summary> 计算曲线细分点 </summary>
|
||||
public void Compute() {
|
||||
//细分点
|
||||
if (bezier == Bezier.一阶) { positions = new List<Vector3> { aPoint, bPoint }; }
|
||||
if (bezier == Bezier.二阶) { positions = Compute(aPoint, aBezier, bPoint); }
|
||||
if (bezier == Bezier.三阶) { positions = Compute(aPoint, aBezier, bBezier, bPoint); }
|
||||
//线段
|
||||
lines = new List<DataPlateLine>();
|
||||
for (int i = 0; i < positions.Count - 1; i++) {
|
||||
DataPlateLine line = new DataPlateLine();
|
||||
line.a = positions.LoopIndex(i + 0);
|
||||
line.b = positions.LoopIndex(i + 1);
|
||||
line.origin = length;
|
||||
lines.Add(line);
|
||||
length += line.Distance;
|
||||
}
|
||||
}
|
||||
//去除重复边缘点
|
||||
points = points.Distinct().ToList();
|
||||
data.edgePoints = points;
|
||||
}
|
||||
public void Compute(DataSide data) {
|
||||
DataBezier dataBezier = new DataBezier();
|
||||
dataBezier.bezier = data.bezier;
|
||||
dataBezier.smooth = data.plate.smooth;
|
||||
dataBezier.aPoint = data.aPoint.position;
|
||||
dataBezier.bPoint = data.bPoint.position;
|
||||
dataBezier.aBezier = data.aBezier;
|
||||
dataBezier.bBezier = data.bBezier;
|
||||
|
||||
Compute(dataBezier);
|
||||
|
||||
data.length = dataBezier.length;
|
||||
data.positions = dataBezier.positions.ToArray();
|
||||
data.lines = dataBezier.lines.ToArray();
|
||||
}
|
||||
|
||||
/// <summary> 计算曲线细分点 </summary>
|
||||
private void Compute(DataBezier data) {
|
||||
//细分点
|
||||
if (data.bezier == Bezier.一阶) {
|
||||
data.positions = Compute(data.aPoint, data.bPoint);
|
||||
/// <summary> 二阶贝塞尔线段 </summary>
|
||||
private List<Vector3> Compute(Vector3 a, Vector3 b, Vector3 c) {
|
||||
List<Vector3> points = new List<Vector3>();
|
||||
//方向,距离
|
||||
float distance = Vector2.Distance(c, a);
|
||||
//求余,得商数
|
||||
int quotient = Quotient(distance, smooth);
|
||||
//贝塞尔曲线点
|
||||
for (int i = 0; i < quotient; i++) {
|
||||
float t = i * (distance / quotient) / distance;
|
||||
Vector2 position = ComputeBezier(a, b, c, t);
|
||||
points.Add(position);
|
||||
}
|
||||
points.Add(c);
|
||||
return points;
|
||||
}
|
||||
if (data.bezier == Bezier.二阶) {
|
||||
data.positions = Compute(data.aPoint, data.aBezier, data.bPoint, data.smooth);
|
||||
/// <summary> 三阶贝塞尔线段 </summary>
|
||||
private List<Vector3> Compute(Vector3 a, Vector3 b, Vector3 c, Vector3 d) {
|
||||
List<Vector3> points = new List<Vector3>();
|
||||
//方向,距离
|
||||
Vector2 direction = (d - a).normalized;
|
||||
float distance = Vector2.Distance(d, a);
|
||||
//求余,得商数
|
||||
int quotient = Quotient(distance, smooth);
|
||||
//贝塞尔曲线点
|
||||
for (int i = 0; i < quotient; i++) {
|
||||
float t = i * (distance / quotient) / distance;
|
||||
Vector2 position = ComputeBezier(a, b, c, d, t);
|
||||
points.Add(position);
|
||||
}
|
||||
points.Add(d);
|
||||
return points;
|
||||
}
|
||||
if (data.bezier == Bezier.三阶) {
|
||||
data.positions = Compute(data.aPoint, data.aBezier, data.bBezier, data.bPoint, data.smooth);
|
||||
}
|
||||
//线段
|
||||
data.lines = new List<DataLine>();
|
||||
float origin = 0;
|
||||
for (int i = 0; i < data.positions.Count - 1; i++) {
|
||||
DataLine line = new DataLine();
|
||||
line.a = data.positions.LoopIndex(i + 0);
|
||||
line.b = data.positions.LoopIndex(i + 1);
|
||||
line.origin = origin;
|
||||
data.lines.Add(line);
|
||||
data.length += line.Distance;
|
||||
origin += line.Distance;
|
||||
}
|
||||
}
|
||||
/// <summary> 二阶贝塞尔线段 </summary>
|
||||
private List<Vector3> Compute(Vector3 aPoint, Vector3 bPoint) {
|
||||
return new List<Vector3> { aPoint, bPoint };
|
||||
}
|
||||
/// <summary> 二阶贝塞尔线段 </summary>
|
||||
private List<Vector3> Compute(Vector3 a, Vector3 b, Vector3 c, float smooth) {
|
||||
List<Vector3> points = new List<Vector3>();
|
||||
//方向,距离
|
||||
Vector2 direction = (c - a).normalized;
|
||||
float distance = Vector2.Distance(c, a);
|
||||
//求余,得商数
|
||||
int quotient = Quotient(distance, smooth);
|
||||
//贝塞尔曲线点
|
||||
for (int i = 0; i < quotient; i++) {
|
||||
float t = i * (distance / quotient) / distance;
|
||||
Vector2 position = ComputeBezier(a, b, c, t);
|
||||
points.Add(position);
|
||||
}
|
||||
points.Add(c);
|
||||
return points;
|
||||
}
|
||||
/// <summary> 三阶贝塞尔线段 </summary>
|
||||
private List<Vector3> Compute(Vector3 a, Vector3 b, Vector3 c, Vector3 d, float smooth) {
|
||||
List<Vector3> points = new List<Vector3>();
|
||||
//方向,距离
|
||||
Vector2 direction = (d - a).normalized;
|
||||
float distance = Vector2.Distance(d, a);
|
||||
//求余,得商数
|
||||
int quotient = Quotient(distance, smooth);
|
||||
//贝塞尔曲线点
|
||||
for (int i = 0; i < quotient; i++) {
|
||||
float t = i * (distance / quotient) / distance;
|
||||
Vector2 position = ComputeBezier(a, b, c, d, t);
|
||||
points.Add(position);
|
||||
}
|
||||
points.Add(d);
|
||||
return points;
|
||||
}
|
||||
|
||||
/// <summary> 商数 </summary>
|
||||
|
||||
@@ -1,28 +1,35 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 散点边界算法
|
||||
/// </summary>
|
||||
public class UnitAlgorithmBorder : UnitAlgorithm<DataPlate> {
|
||||
public class UnitAlgorithmBorder : UnitAlgorithm<DataPlateBaking> {
|
||||
/// <summary> 散点边界算法 </summary>
|
||||
public UnitAlgorithmBorder() { }
|
||||
|
||||
public void Compute(DataPlate plate) {
|
||||
List<Vector3> edgePoints = new List<Vector3>(plate.edgePoints);
|
||||
plate.border = Border(edgePoints);
|
||||
public void Compute(DataPlateBaking plateBaking) {
|
||||
//List<DataPlateSide> plateSides = plateBaking.plate.plateSides;
|
||||
|
||||
//List<Vector3> points = new List<Vector3>();
|
||||
//for (int i = 0; i < plateSides.Count; i++) {
|
||||
// points.AddRange(plateSides[i].dataBaking.positions);
|
||||
//}
|
||||
|
||||
//plateBaking.border = Border(points.Distinct().ToArray());
|
||||
}
|
||||
|
||||
public static DataBorder Border(List<Vector3> points) {
|
||||
public static DataBorder Border(Vector3[] points) {
|
||||
float minX = 0; float minY = 0;
|
||||
float maxX = 0; float maxY = 0;
|
||||
for (int i = 0; i < points.Count; i++) {
|
||||
for (int i = 0; i < points.Length; i++) {
|
||||
if (points[i].x < minX) { minX = points[i].x; }
|
||||
if (points[i].x > maxX) { maxX = points[i].x; }
|
||||
if (points[i].y < minY) { minY = points[i].y; }
|
||||
if (points[i].y > maxY) { maxY = points[i].y; }
|
||||
}
|
||||
return new DataBorder(minX, maxX, minY, maxY);
|
||||
return new DataBorder(minX, maxX, minY, maxY, points);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ using UnityEngine;
|
||||
/// <summary>
|
||||
/// 多边形耳切法
|
||||
/// </summary>
|
||||
public class UnitAlgorithmEarCutting : UnitAlgorithm<DataPlate> {
|
||||
public class UnitAlgorithmEarCutting : UnitAlgorithm<DataPlateDesign> {
|
||||
/// <summary> 多边形耳切法 </summary>
|
||||
public UnitAlgorithmEarCutting() { }
|
||||
|
||||
@@ -17,27 +17,27 @@ public class UnitAlgorithmEarCutting : UnitAlgorithm<DataPlate> {
|
||||
public Vector3 cPoint;//+1
|
||||
}
|
||||
|
||||
public void Compute(DataPlate data) {
|
||||
List<Vector3> points = new List<Vector3>(data.edgePoints);
|
||||
public void Compute(DataPlateDesign plateDesign) {
|
||||
List<Vector3> points = new List<Vector3>(plateDesign.points);
|
||||
//判断散列点排序方向
|
||||
Vector3[] allArray = points.ToArray();
|
||||
bool isClockWise = IsClockWise(allArray);
|
||||
Vector3[] allPoints = plateDesign.points;
|
||||
bool isClockWise = IsClockWise(allPoints);
|
||||
//耳切法生成三角形
|
||||
List<DataTriangle> triangles = new List<DataTriangle>();
|
||||
ComputeAuriculare(triangles, points, allArray, isClockWise);
|
||||
data.triangles = triangles;
|
||||
ComputeAuriculare(triangles, points, allPoints, isClockWise);
|
||||
plateDesign.triangles = triangles;
|
||||
}
|
||||
|
||||
#region 函数
|
||||
/// <summary> 循环计算有效的耳点 </summary>
|
||||
public static void ComputeAuriculare(List<DataTriangle> triangles, List<Vector3> edgePoints, Vector3[] allArray, bool isClockWise) {
|
||||
List<DataTriangle> temp = ComputeAuriculare(edgePoints, allArray, isClockWise);
|
||||
public static void ComputeAuriculare(List<DataTriangle> triangles, List<Vector3> edgePoints, Vector3[] allPoints, bool isClockWise) {
|
||||
List<DataTriangle> temp = ComputeAuriculare(edgePoints, allPoints, isClockWise);
|
||||
if (temp.Count == 0) { return; }
|
||||
triangles.AddRange(temp);
|
||||
ComputeAuriculare(triangles, edgePoints, allArray, isClockWise);
|
||||
ComputeAuriculare(triangles, edgePoints, allPoints, isClockWise);
|
||||
}
|
||||
/// <summary> 计算一个有效的耳点 </summary>
|
||||
public static List<DataTriangle> ComputeAuriculare(List<Vector3> edgePoints, Vector3[] allArray, bool isClockWise) {
|
||||
public static List<DataTriangle> ComputeAuriculare(List<Vector3> edgePoints, Vector3[] allPoints, bool isClockWise) {
|
||||
Vector3[] array = edgePoints.ToArray();
|
||||
List<DataTriangle> polygons = new List<DataTriangle>();
|
||||
for (int i = 0; i < array.Length; i++) {
|
||||
@@ -45,7 +45,7 @@ public class UnitAlgorithmEarCutting : UnitAlgorithm<DataPlate> {
|
||||
// 等于180,大于180,不可能为耳点
|
||||
if (!GetAngleType(auriculare, isClockWise)) { continue; }
|
||||
// 包含其他点,不可能为耳点
|
||||
if (IsInsideTriangle(auriculare, allArray)) { continue; }
|
||||
if (IsInsideTriangle(auriculare, allPoints)) { continue; }
|
||||
// 包含其他耳点,不可能成为耳点
|
||||
if (!IsInsideAuriculare(auriculare, edgePoints)) { continue; }
|
||||
edgePoints.Remove(auriculare.aPoint);
|
||||
|
||||
@@ -35,7 +35,7 @@ public class UnitAlgorithmEdgePoint : UnitAlgorithm<DataPolygon> {
|
||||
|
||||
#region 函数
|
||||
/// <summary> 二阶贝塞尔线段 </summary>
|
||||
public List<Vector3> CreateLine(DataPoint aPoint, DataPoint bPoint, Vector3 b, float smooth) {
|
||||
public List<Vector3> CreateLine(DataPlatePoint aPoint, DataPlatePoint bPoint, Vector3 b, float smooth) {
|
||||
List<Vector3> points = new List<Vector3>();
|
||||
//方向,距离
|
||||
Vector2 direction = (bPoint.position - aPoint.position).normalized;
|
||||
@@ -53,7 +53,7 @@ public class UnitAlgorithmEdgePoint : UnitAlgorithm<DataPolygon> {
|
||||
return points;
|
||||
}
|
||||
/// <summary> 三阶贝塞尔线段 </summary>
|
||||
public List<Vector3> CreateLine(DataPoint aPoint, DataPoint bPoint, float smooth) {
|
||||
public List<Vector3> CreateLine(DataPlatePoint aPoint, DataPlatePoint bPoint, float smooth) {
|
||||
List<Vector3> points = new List<Vector3>();
|
||||
//方向,距离
|
||||
Vector2 direction = (bPoint.position - aPoint.position).normalized;
|
||||
|
||||
@@ -0,0 +1,239 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Unity.Burst;
|
||||
using Unity.Collections;
|
||||
using Unity.Jobs;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 贝塞尔算法 边缘细分 Jobs
|
||||
/// </summary>
|
||||
public class UnitAlgorithmJobsSideSubdivision : UnitAlgorithm<DataPlateDesign>, UnitAlgorithm<DataPlateBaking> {
|
||||
|
||||
/// <summary> 贝塞尔算法 边缘细分 Jobs </summary>
|
||||
public UnitAlgorithmJobsSideSubdivision() { }
|
||||
|
||||
public void Compute(DataPlateDesign plateDesign) {
|
||||
int count = plateDesign.plate.plateSides.Count;
|
||||
List<DataPlateSide> plateSides = plateDesign.plate.plateSides;
|
||||
NativeArray<JobSubdivision> jobSubdivisions = new NativeArray<JobSubdivision>(count, Allocator.TempJob);
|
||||
NativeArray<JobHandle> jobHandles = new NativeArray<JobHandle>(count, Allocator.TempJob);
|
||||
//创建作业任务
|
||||
for (int i = 0; i < count; i++) {
|
||||
jobSubdivisions[i] = ToJob(plateSides[i]);
|
||||
jobHandles[i] = jobSubdivisions[i].Schedule();
|
||||
}
|
||||
//执行作业
|
||||
JobHandle.CompleteAll(jobHandles);
|
||||
//作业结果转换
|
||||
List<Vector3> points = new List<Vector3>();
|
||||
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<DataPlateSide> plateSides = plateBaking.plate.plateSides;
|
||||
//NativeArray<JobSubdivision> jobSubdivisions = new NativeArray<JobSubdivision>(count, Allocator.Temp);
|
||||
//NativeArray<JobHandle> jobHandles = new NativeArray<JobHandle>(count, Allocator.Temp);
|
||||
////创建作业任务
|
||||
//for (int i = 0; i < count; i++) {
|
||||
// jobSubdivisions[i] = ToJob(plateSides[i]);
|
||||
// jobHandles[i] = jobSubdivisions[i].Schedule();
|
||||
//}
|
||||
////执行作业
|
||||
//JobHandle.CompleteAll(jobHandles);
|
||||
////作业结果转换
|
||||
////List<Vector3> points = new List<Vector3>();
|
||||
//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();
|
||||
}
|
||||
|
||||
/// <summary> 转换作业系统数据 </summary>
|
||||
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<float>(1, Allocator.TempJob);
|
||||
jobSubdivision.positions = new NativeArray<Vector3>(jobSubdivision.quotient, Allocator.TempJob);
|
||||
jobSubdivision.lines = new NativeArray<JobDataLine>(jobSubdivision.quotient - 1, Allocator.TempJob);
|
||||
|
||||
return jobSubdivision;
|
||||
}
|
||||
/// <summary> 作业系统数据转换设计数据 </summary>
|
||||
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();
|
||||
}
|
||||
/// <summary> 作业系统数据转换烘焙数据 </summary>
|
||||
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();
|
||||
}
|
||||
/// <summary> 转换托管数据 </summary>
|
||||
public DataPlateLine ToData(JobDataLine jobDataLine) {
|
||||
DataPlateLine line = new DataPlateLine();
|
||||
line.a = jobDataLine.a;
|
||||
line.b = jobDataLine.b;
|
||||
line.origin = jobDataLine.origin;
|
||||
return line;
|
||||
}
|
||||
|
||||
/// <summary> 作业系统数据 </summary>
|
||||
public struct JobDataLine {
|
||||
/// <summary> 线段起点a </summary>
|
||||
public Vector3 a;
|
||||
/// <summary> 线段终点b </summary>
|
||||
public Vector3 b;
|
||||
/// <summary> 原始距离 </summary>
|
||||
public float origin;
|
||||
}
|
||||
[BurstCompile]
|
||||
public struct JobSubdivision : IJob {
|
||||
|
||||
#region 输入
|
||||
/// <summary> 贝塞尔类型 </summary>
|
||||
public Bezier bezier;
|
||||
/// <summary> a点 </summary>
|
||||
public Vector3 aPoint;
|
||||
/// <summary> b点 </summary>
|
||||
public Vector3 bPoint;
|
||||
/// <summary> a点贝塞尔点 </summary>
|
||||
public Vector3 aBezier;
|
||||
/// <summary> b点贝塞尔点 </summary>
|
||||
public Vector3 bBezier;
|
||||
/// <summary> a-b距离 </summary>
|
||||
public float distance;
|
||||
/// <summary> 细分数 </summary>
|
||||
public int quotient;
|
||||
#endregion
|
||||
|
||||
#region 输出
|
||||
/// <summary> 总长度 </summary>
|
||||
public NativeArray<float> length;
|
||||
/// <summary> 点 </summary>
|
||||
public NativeArray<Vector3> positions;
|
||||
/// <summary> 线 </summary>
|
||||
public NativeArray<JobDataLine> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> 商数 </summary>
|
||||
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);
|
||||
}
|
||||
/// <summary>
|
||||
/// 一阶贝塞尔算法
|
||||
/// </summary>
|
||||
/// <param name="a">起点</param>
|
||||
/// <param name="b">终点</param>
|
||||
/// <param name="t">进度</param>
|
||||
/// <returns></returns>
|
||||
public static Vector3 ComputeBezier(Vector3 a, Vector3 b, float t) {
|
||||
return a + (b - a) * t;
|
||||
}
|
||||
/// <summary>
|
||||
/// 二阶贝塞尔算法
|
||||
/// </summary>
|
||||
/// <param name="a">起点</param>
|
||||
/// <param name="b">贝塞尔点</param>
|
||||
/// <param name="c">终点</param>
|
||||
/// <param name="t">进度</param>
|
||||
/// <returns>当前进度的曲线点</returns>
|
||||
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;
|
||||
}
|
||||
/// <summary>
|
||||
/// 三阶贝塞尔算法
|
||||
/// </summary>
|
||||
/// <param name="a">起点</param>
|
||||
/// <param name="b">起点的贝塞尔点</param>
|
||||
/// <param name="c">终点的贝塞尔点</param>
|
||||
/// <param name="d">终点</param>
|
||||
/// <param name="t">进度</param>
|
||||
/// <returns>当前进度的曲线点</returns>
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 39a35ef3408d163469eb7c66d1df96ac
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -10,12 +10,12 @@ using UnityEngine;
|
||||
/// <summary>
|
||||
/// 三角形合并网格
|
||||
/// </summary>
|
||||
public class UnitAlgorithmMergeTriangle : UnitAlgorithm<DataPlate> {
|
||||
public class UnitAlgorithmMergeTriangle : UnitAlgorithm<DataPlateDesign>, UnitAlgorithm<DataPlateBaking> {
|
||||
/// <summary> 三角形合并网格 </summary>
|
||||
public UnitAlgorithmMergeTriangle() { }
|
||||
|
||||
public void Compute(DataPlate data) {
|
||||
List<DataTriangle> polygons = data.triangles;
|
||||
public void Compute(DataPlateDesign plateDesign) {
|
||||
List<DataTriangle> polygons = plateDesign.triangles;
|
||||
//三角形合并
|
||||
List<Vector3> vertices = vertices = MergeVertices(polygons);
|
||||
List<int> triangles = JobFindTriangleIndex(polygons, vertices);
|
||||
@@ -23,12 +23,28 @@ public class UnitAlgorithmMergeTriangle : UnitAlgorithm<DataPlate> {
|
||||
List<Vector2> uv = new List<Vector2>();
|
||||
for (int i = 0; i < vertices.Count; i++) { uv.Add(vertices[i]); }
|
||||
//附加数据
|
||||
data.designMesh = new Mesh();
|
||||
data.designMesh.vertices = vertices.ToArray();
|
||||
data.designMesh.uv = uv.ToArray();
|
||||
data.designMesh.triangles = triangles.ToArray();
|
||||
data.designMesh.RecalculateBounds();
|
||||
data.designMesh.RecalculateNormals();
|
||||
plateDesign.mesh = new Mesh();
|
||||
plateDesign.mesh.vertices = vertices.ToArray();
|
||||
plateDesign.mesh.uv = uv.ToArray();
|
||||
plateDesign.mesh.triangles = triangles.ToArray();
|
||||
plateDesign.mesh.RecalculateBounds();
|
||||
plateDesign.mesh.RecalculateNormals();
|
||||
}
|
||||
public void Compute(DataPlateBaking plateBaking) {
|
||||
//List<DataTriangle> polygons = plateBaking.triangles;
|
||||
////三角形合并
|
||||
//List<Vector3> vertices = vertices = MergeVertices(polygons);
|
||||
//List<int> triangles = JobFindTriangleIndex(polygons, vertices);
|
||||
////展开uv (顶点去掉z坐标就是未缩放的平面UV)
|
||||
//List<Vector2> uv = new List<Vector2>();
|
||||
//for (int i = 0; i < vertices.Count; i++) { uv.Add(vertices[i]); }
|
||||
////附加数据
|
||||
//plateBaking.mesh = new Mesh();
|
||||
//plateBaking.mesh.vertices = vertices.ToArray();
|
||||
//plateBaking.mesh.uv = uv.ToArray();
|
||||
//plateBaking.mesh.triangles = triangles.ToArray();
|
||||
//plateBaking.mesh.RecalculateBounds();
|
||||
//plateBaking.mesh.RecalculateNormals();
|
||||
}
|
||||
/// <summary> 合并顶点 </summary>
|
||||
private List<Vector3> MergeVertices(List<DataTriangle> polygons) {
|
||||
@@ -54,7 +70,7 @@ public class UnitAlgorithmMergeTriangle : UnitAlgorithm<DataPlate> {
|
||||
triangleIndex.triangles = trianglesArray;
|
||||
|
||||
JobHandle dependency = new JobHandle();
|
||||
JobHandle handle = triangleIndex.ScheduleParallel(polygons.Count, 2048, dependency);
|
||||
JobHandle handle = triangleIndex.ScheduleParallel(polygons.Count, 32, dependency);
|
||||
handle.Complete();
|
||||
|
||||
List<int> triangles = new List<int>();
|
||||
|
||||
@@ -5,55 +5,58 @@ using UnityEngine;
|
||||
/// <summary>
|
||||
/// 菱形绘制三角形算法
|
||||
/// </summary>
|
||||
public class UnitAlgorithmRhombus : UnitAlgorithm<DataPlate> {
|
||||
public class UnitAlgorithmRhombus : UnitAlgorithm<DataPlateBaking> {
|
||||
|
||||
public void Compute(DataPlate data) {
|
||||
public void Compute(DataPlateBaking plateBaking) {
|
||||
List<DataTriangle> triangles = new List<DataTriangle>();
|
||||
data.vertexGrid.Loop((x, y) => {
|
||||
DataVertex vertex = data.vertexGrid.Get(x, y);
|
||||
if (!vertex.isValid) { return; }
|
||||
List<DataPlateVertex> vertexs = new List<DataPlateVertex>();
|
||||
//plateBaking.grid.Loop((x, y) => {
|
||||
// DataPlateVertex vertex = plateBaking.grid.Get(x, y);
|
||||
// if (!vertex.isValid) { return; }
|
||||
|
||||
TryGet(data.vertexGrid, x, y + 1, ref vertex.above);
|
||||
TryGet(data.vertexGrid, x, y - 1, ref vertex.below);
|
||||
TryGet(data.vertexGrid, x - 1, y, ref vertex.left);
|
||||
TryGet(data.vertexGrid, x + 1, y, ref vertex.right);
|
||||
// TryGet(plateBaking.grid, x, y + 1, ref vertex.above);
|
||||
// TryGet(plateBaking.grid, x, y - 1, ref vertex.below);
|
||||
// TryGet(plateBaking.grid, x - 1, y, ref vertex.left);
|
||||
// TryGet(plateBaking.grid, x + 1, y, ref vertex.right);
|
||||
|
||||
TryGet(data.vertexGrid, x - 1, y + 1, ref vertex.leftAbove);
|
||||
TryGet(data.vertexGrid, x - 1, y - 1, ref vertex.leftBelow);
|
||||
TryGet(data.vertexGrid, x + 1, y + 1, ref vertex.rightAbove);
|
||||
TryGet(data.vertexGrid, x + 1, y - 1, ref vertex.rightBelow);
|
||||
//默认绘制左上角
|
||||
if (vertex.above != null && vertex.left != null) {
|
||||
triangles.Add(CreateDataTriangle(vertex, vertex.left, vertex.above));
|
||||
}
|
||||
//默认绘制右下角
|
||||
if (vertex.below != null && vertex.right != null) {
|
||||
triangles.Add(CreateDataTriangle(vertex, vertex.right, vertex.below));
|
||||
}
|
||||
//如果右上角点不存在,则尝试绘制右上角
|
||||
if (vertex.rightAbove == null && vertex.above != null && vertex.right != null) {
|
||||
triangles.Add(CreateDataTriangle(vertex, vertex.above, vertex.right));
|
||||
}
|
||||
//如果左下角点不存在,则尝试绘制左下角
|
||||
if (vertex.leftBelow == null && vertex.below != null && vertex.left != null) {
|
||||
triangles.Add(CreateDataTriangle(vertex, vertex.below, vertex.left));
|
||||
}
|
||||
});
|
||||
data.triangles = triangles;
|
||||
// TryGet(plateBaking.grid, x - 1, y + 1, ref vertex.leftAbove);
|
||||
// TryGet(plateBaking.grid, x - 1, y - 1, ref vertex.leftBelow);
|
||||
// TryGet(plateBaking.grid, x + 1, y + 1, ref vertex.rightAbove);
|
||||
// TryGet(plateBaking.grid, x + 1, y - 1, ref vertex.rightBelow);
|
||||
// //默认绘制左上角
|
||||
// if (vertex.above != null && vertex.left != null) {
|
||||
// triangles.Add(CreateDataTriangle(vertex, vertex.left, vertex.above));
|
||||
// }
|
||||
// //默认绘制右下角
|
||||
// if (vertex.below != null && vertex.right != null) {
|
||||
// triangles.Add(CreateDataTriangle(vertex, vertex.right, vertex.below));
|
||||
// }
|
||||
// //如果右上角点不存在,则尝试绘制右上角
|
||||
// if (vertex.rightAbove == null && vertex.above != null && vertex.right != null) {
|
||||
// triangles.Add(CreateDataTriangle(vertex, vertex.above, vertex.right));
|
||||
// }
|
||||
// //如果左下角点不存在,则尝试绘制左下角
|
||||
// if (vertex.leftBelow == null && vertex.below != null && vertex.left != null) {
|
||||
// triangles.Add(CreateDataTriangle(vertex, vertex.below, vertex.left));
|
||||
// }
|
||||
// vertexs.Add(vertex);
|
||||
//});
|
||||
//plateBaking.triangles = triangles;
|
||||
//plateBaking.vertexs = vertexs.ToArray();
|
||||
}
|
||||
|
||||
/// <summary> 校验性获取网格上的点 </summary>
|
||||
private void TryGet(GridTool<DataVertex> grid, int x, int y, ref DataVertex vertex) {
|
||||
private void TryGet(GridTool<DataPlateVertex> grid, int x, int y, ref DataPlateVertex vertex) {
|
||||
vertex = null;
|
||||
if (!grid.TryGet(x, y, out DataVertex data)) { return; }
|
||||
if (!grid.TryGet(x, y, out DataPlateVertex data)) { return; }
|
||||
if (data.isValid) { vertex = data; }
|
||||
}
|
||||
/// <summary> 创建三角形 </summary>
|
||||
private DataTriangle CreateDataTriangle(DataVertex a, DataVertex b, DataVertex c) {
|
||||
private DataTriangle CreateDataTriangle(DataPlateVertex a, DataPlateVertex b, DataPlateVertex c) {
|
||||
DataTriangle triangle = new DataTriangle();
|
||||
triangle.b = a.design;
|
||||
triangle.c = b.design;
|
||||
triangle.a = c.design;
|
||||
triangle.b = a.position;
|
||||
triangle.c = b.position;
|
||||
triangle.a = c.position;
|
||||
return triangle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 烘焙的缝合线
|
||||
/// </summary>
|
||||
public class UnitAlgorithmSutureBaking : UnitAlgorithm<DataSutureSide> {
|
||||
/// <summary> 烘焙的缝合线 </summary>
|
||||
public UnitAlgorithmSutureBaking() { }
|
||||
|
||||
public void Compute(DataSutureSide sutureSide) {
|
||||
AllVertexs(sutureSide);
|
||||
//缝合范围内的顶点
|
||||
SetVertex(sutureSide);
|
||||
//顶点转换位置
|
||||
SetPositions(sutureSide);
|
||||
}
|
||||
/// <summary> 顶点距离数据 </summary>
|
||||
private List<DataSutureSideVertex> GetVertex(DataPlateVertex[] vertexsArray, bool isReversal) {
|
||||
float length = 0;
|
||||
List<DataSutureSideVertex> vertexs = new List<DataSutureSideVertex>();
|
||||
List<DataPlateVertex> sideVertexs = new List<DataPlateVertex>(vertexsArray);
|
||||
if (isReversal) { sideVertexs.Reverse(); }
|
||||
for (int i = 0; i < sideVertexs.Count - 1; i++) {
|
||||
DataSutureSideVertex vertex = new DataSutureSideVertex(length, sideVertexs[i], sideVertexs[i + 1]);
|
||||
vertexs.Add(vertex); length += vertex.Distance;
|
||||
}
|
||||
return vertexs;
|
||||
}
|
||||
/// <summary> 全部顶点 </summary>
|
||||
private void AllVertexs(DataSutureSide sutureSide) {
|
||||
DataPlateVertex[] vertexsArray = sutureSide.plateSide.dataBaking.vertexs;
|
||||
List<DataSutureSideVertex> allVertexs = GetVertex(vertexsArray, false);
|
||||
sutureSide.dataBaking.allVertexs = allVertexs.ToArray();
|
||||
}
|
||||
/// <summary> 缝合范围内的顶点 </summary>
|
||||
private void SetVertex(DataSutureSide sutureSide) {
|
||||
//全部顶点
|
||||
List<DataSutureSideVertex> allVertexs = GetVertex(sutureSide.plateSide.dataBaking.vertexs, sutureSide.isReversal);
|
||||
//缝合范围内的顶点
|
||||
float maxLength = sutureSide.suture.length;
|
||||
List<DataSutureSideVertex> vertexs = new List<DataSutureSideVertex>();
|
||||
for (int i = 0; i < allVertexs.Count; i++) {
|
||||
if (allVertexs[i].origin <= maxLength) { vertexs.Add(allVertexs[i]); }
|
||||
}
|
||||
sutureSide.dataBaking.vertexs = vertexs.ToArray();
|
||||
}
|
||||
/// <summary> 顶点转换位置 </summary>
|
||||
private void SetPositions(DataSutureSide sutureSide) {
|
||||
Vector3 platePosition = sutureSide.plateSide.plate.dataBaking.position;
|
||||
Vector3 plateEulerAngles = sutureSide.plateSide.plate.dataBaking.eulerAngles;
|
||||
List<Vector3> positions = new List<Vector3>();
|
||||
DataSutureSideVertex[] vertexs = sutureSide.dataBaking.vertexs;
|
||||
for (int i = 0; i < vertexs.Length; i++) {
|
||||
Quaternion quaternion = Quaternion.Euler(plateEulerAngles);
|
||||
Vector3 baking = quaternion * vertexs[i].a.position;
|
||||
Vector3 position = baking + platePosition;
|
||||
positions.Add(position);
|
||||
}
|
||||
sutureSide.dataBaking.positions = positions.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9735cc247f76e0b42b50f8b7956d3c8a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,52 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 设计的缝合线
|
||||
/// </summary>
|
||||
public class UnitAlgorithmSutureDesign : UnitAlgorithm<DataSutureSide> {
|
||||
/// <summary> 设计的缝合线 </summary>
|
||||
public UnitAlgorithmSutureDesign() { }
|
||||
|
||||
public class Line {
|
||||
public float origin;
|
||||
public Vector3 a;
|
||||
public Vector3 b;
|
||||
public Line(float origin, Vector3 a, Vector3 b) {
|
||||
this.origin = origin;
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
public float Distance => Vector3.Distance(a, b);
|
||||
}
|
||||
|
||||
public void Compute(DataSutureSide sutureSide) {
|
||||
float maxLength = sutureSide.suture.length;
|
||||
Vector3 platePosition = sutureSide.plateSide.plate.dataDesign.position;
|
||||
List<Vector3> sidePositions = new List<Vector3>(sutureSide.plateSide.dataDesign.positions);
|
||||
|
||||
float length = 0;
|
||||
List<Line> lines = new List<Line>();
|
||||
if (sutureSide.isReversal) { sidePositions.Reverse(); }
|
||||
for (int i = 0; i < sidePositions.Count - 1; i++) {
|
||||
Line line = new Line(length, sidePositions[i], sidePositions[i + 1]);
|
||||
lines.Add(line);
|
||||
length += line.Distance;
|
||||
}
|
||||
List<Vector3> positions = new List<Vector3>();
|
||||
for (int i = 0; i < lines.Count; i++) {
|
||||
Line line = lines[i];
|
||||
if (line.origin < maxLength) { positions.Add(line.a + platePosition); }
|
||||
float nextDistance = line.origin + line.Distance;
|
||||
if (nextDistance < maxLength) { continue; }
|
||||
if (nextDistance == maxLength) { positions.Add(line.b + platePosition); break; }
|
||||
float distance = maxLength - line.origin;
|
||||
Vector3 direction = (line.b - line.a).normalized;
|
||||
Vector3 position = line.a + direction * distance;
|
||||
positions.Add(position + platePosition);
|
||||
break;
|
||||
}
|
||||
sutureSide.dataDesign.positions = positions.ToArray();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b98adb17aebd36b4ab5dfe90020fb902
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -6,97 +6,95 @@ using UnityEngine;
|
||||
/// <summary>
|
||||
/// 顶点算法
|
||||
/// </summary>
|
||||
public class UnitAlgorithmVertex : UnitAlgorithm<DataPlate> {
|
||||
public class UnitAlgorithmVertex : UnitAlgorithm<DataPlateBaking> {
|
||||
|
||||
public class SideVertex : IComparable<SideVertex> {
|
||||
public float distance;
|
||||
public DataVertex vertex;
|
||||
public Vector3 position;
|
||||
|
||||
public int CompareTo(SideVertex other) {
|
||||
return other.distance >= distance ? 1 : -1;
|
||||
if (other == null || this == null) { return 0; }
|
||||
if (other == this) { return 0; }
|
||||
if (other.distance > distance) { return -1; }
|
||||
if (other.distance < distance) { return 1; }
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void Compute(DataPlate data) {
|
||||
float smooth = data.smooth;
|
||||
DataBorder border = data.border;
|
||||
List<Vector3> edgePoints = new List<Vector3>(data.edgePoints);
|
||||
public void Compute(DataPlateBaking plateBaking) {
|
||||
DataBorder border = plateBaking.border;
|
||||
Vector3[] points = border.points;
|
||||
|
||||
int wide = Mathf.FloorToInt(border.Wide / smooth) + 1;
|
||||
int high = Mathf.FloorToInt(border.High / smooth) + 1;
|
||||
//计算内部顶点
|
||||
data.vertexGrid = new GridTool<DataVertex>(wide, high, (x, y) => {
|
||||
Vector3 position = border.MinPoint + new Vector3(x * smooth, y * smooth);
|
||||
DataVertex vertex = new DataVertex();
|
||||
vertex.isValid = FindPlateInside(edgePoints, position);
|
||||
vertex.design = position;
|
||||
return vertex;
|
||||
});
|
||||
//plateBaking.grid = new GridTool<DataPlateVertex>(border.GridWide, border.GridHigh, (x, y) => {
|
||||
// Vector3 position = new Vector3(x, y) * border.smooth + border.MinPoint;
|
||||
// DataPlateVertex vertex = new DataPlateVertex();
|
||||
// vertex.isValid = FindPlateInside(points, position);
|
||||
// vertex.position = position;
|
||||
// return vertex;
|
||||
//});
|
||||
|
||||
//边缘所有的线段
|
||||
for (int i = 0; i < data.sides.Count; i++) {
|
||||
Compute(data.sides[i], wide, high, border, smooth, data.vertexGrid);
|
||||
}
|
||||
//List<DataPlateSide> plateSides = plateBaking.plate.plateSides;
|
||||
//for (int i = 0; i < plateSides.Count; i++) {
|
||||
// SubdivideSideVertex(plateBaking, plateSides[i]);
|
||||
//}
|
||||
}
|
||||
|
||||
/// <summary> 向网格和边缘写入顶点数据 </summary>
|
||||
private void Compute(DataSide side, int wide, int high, DataBorder border, float smooth, GridTool<DataVertex> grid) {
|
||||
DataLine[] lines = side.lines;
|
||||
List<SideVertex> sideVertices = new List<SideVertex>();
|
||||
private void SubdivideSideVertex(DataPlateBaking plateBaking, DataPlateSide plateSides) {
|
||||
DataBorder border = plateBaking.border;
|
||||
DataPlateLine[] lines = plateSides.dataBaking.lines;
|
||||
//计算水平线段顶点
|
||||
for (int x = 0; x < wide; x++) {
|
||||
Vector3 a = new Vector3(border.minX + x * smooth, border.minY - 1);
|
||||
Vector3 b = new Vector3(border.minX + x * smooth, border.maxY + 1);
|
||||
List<SideVertex> sideVertexs = new List<SideVertex>();
|
||||
for (int x = 0; x < border.GridWide; x++) {
|
||||
Vector3 a = new Vector3(border.minX + x * border.smooth, border.minY - 1);
|
||||
Vector3 b = new Vector3(border.minX + x * border.smooth, border.maxY + 1);
|
||||
for (int i = 0; i < lines.Length; i++) {
|
||||
DataVertex vertex = Compute(a, b, lines[i], smooth, border, grid);
|
||||
if (vertex == null) { continue; }
|
||||
float distance = Vector3.Distance(lines[i].a, vertex.design) + lines[i].origin;
|
||||
if (!TryGetIntersectPoint(a, b, lines[i].a, lines[i].b, out Vector3 IntersectPoint)) { continue; }
|
||||
float distance = Vector3.Distance(lines[i].a, IntersectPoint) + lines[i].origin;
|
||||
SideVertex sideVertex = new SideVertex();
|
||||
sideVertex.distance = distance;
|
||||
sideVertex.vertex = vertex;
|
||||
sideVertices.Add(sideVertex);
|
||||
sideVertex.position = IntersectPoint;
|
||||
sideVertexs.Add(sideVertex);
|
||||
}
|
||||
}
|
||||
//计算垂直线段顶点
|
||||
for (int y = 0; y < high; y++) {
|
||||
Vector3 a = new Vector3(border.minX - 1, border.minY + y * smooth);
|
||||
Vector3 b = new Vector3(border.maxX + 1, border.minY + y * smooth);
|
||||
for (int y = 0; y < border.GridHigh; y++) {
|
||||
Vector3 a = new Vector3(border.minX - 1, border.minY + y * border.smooth);
|
||||
Vector3 b = new Vector3(border.maxX + 1, border.minY + y * border.smooth);
|
||||
for (int i = 0; i < lines.Length; i++) {
|
||||
DataVertex vertex = Compute(a, b, lines[i], smooth, border, grid);
|
||||
if (vertex == null) { continue; }
|
||||
float distance = Vector3.Distance(lines[i].a, vertex.design) + lines[i].origin;
|
||||
if (!TryGetIntersectPoint(a, b, lines[i].a, lines[i].b, out Vector3 IntersectPoint)) { continue; }
|
||||
float distance = Vector3.Distance(lines[i].a, IntersectPoint) + lines[i].origin;
|
||||
SideVertex sideVertex = new SideVertex();
|
||||
sideVertex.distance = distance;
|
||||
sideVertex.vertex = vertex;
|
||||
sideVertices.Add(sideVertex);
|
||||
sideVertex.position = IntersectPoint;
|
||||
sideVertexs.Add(sideVertex);
|
||||
}
|
||||
}
|
||||
sideVertices.Sort();
|
||||
List<DataVertex> vertices = new List<DataVertex>();
|
||||
for (int i = 0; i < sideVertices.Count; i++) {
|
||||
vertices.Add(sideVertices[i].vertex);
|
||||
//排序
|
||||
sideVertexs.Sort();
|
||||
//写入网格,写入顶点
|
||||
Vector3 offset = border.MinPoint - new Vector3(border.smooth, border.smooth, 0) * 0.3f;
|
||||
List<DataPlateVertex> vertexs = new List<DataPlateVertex>();
|
||||
for (int i = 0; i < sideVertexs.Count; i++) {
|
||||
Vector3 position = sideVertexs[i].position;
|
||||
Vector3 gridPosition = position - offset;
|
||||
int vertexX = Mathf.FloorToInt(gridPosition.x / border.smooth);
|
||||
int vertexY = Mathf.FloorToInt(gridPosition.y / border.smooth);
|
||||
//填充数据
|
||||
//DataPlateVertex vertex = plateBaking.grid.Get(vertexX, vertexY);
|
||||
//vertex.isValid = true;
|
||||
//vertex.position = position;
|
||||
////写入顶点
|
||||
//vertexs.Add(vertex);
|
||||
}
|
||||
side.vertices = vertices.ToArray();
|
||||
}
|
||||
/// <summary> 向网格写入边缘顶点数据 </summary>
|
||||
private DataVertex Compute(Vector3 a, Vector3 b, DataLine line, float smooth, DataBorder border, GridTool<DataVertex> grid) {
|
||||
//计算交点
|
||||
if (!TryGetIntersectPoint(a, b, line.a, line.b, out Vector3 IntersectPoint)) { return null; }
|
||||
//计算顶点xy
|
||||
Vector3 offset = new Vector3(smooth, smooth, 0) * 0.3f;
|
||||
Vector3 position = IntersectPoint - border.MinPoint + offset;
|
||||
int vertexX = Mathf.FloorToInt(position.x / smooth);
|
||||
int vertexY = Mathf.FloorToInt(position.y / smooth);
|
||||
//填充数据
|
||||
DataVertex vertex = grid.Get(vertexX, vertexY);
|
||||
vertex.isValid = true;
|
||||
vertex.design = IntersectPoint;
|
||||
return vertex;
|
||||
plateSides.dataBaking.vertexs = vertexs.ToArray();
|
||||
}
|
||||
|
||||
/// <summary> 转角法查询位置是否在板片内 </summary>
|
||||
public static bool FindPlateInside(List<Vector3> points, Vector3 position) {
|
||||
public static bool FindPlateInside(Vector3[] points, Vector3 position) {
|
||||
double angles = 0;
|
||||
for (int i = 0; i < points.Count; i++) {
|
||||
for (int i = 0; i < points.Length; i++) {
|
||||
Vector3 a = points.LoopIndex(i + 0) - position;
|
||||
Vector3 b = points.LoopIndex(i + 1) - position;
|
||||
float angle = Vector2.SignedAngle(a, b);
|
||||
|
||||
Reference in New Issue
Block a user