From 698464b9d7655dece697f4ca515eb4b10a389dcc Mon Sep 17 00:00:00 2001 From: MuHua-123 <136542559+MuHua-123@users.noreply.github.com> Date: Fri, 29 Nov 2024 18:10:02 +0800 Subject: [PATCH] 1 --- .../ModuleAlgorithm/AlgorithmSidePoint.cs | 68 +- .../ModuleAlgorithm/AlgorithmSimplePolygon.cs | 14 +- .../AlgorithmSubdivisionPolygon.cs | 1183 ++++++++++++++++- .../ModuleAlgorithm/AlgorithmSuture.cs | 53 + .../ModuleAlgorithm/AlgorithmSuture.cs.meta | 11 + .../ModuleAlgorithm/AlgorithmSutureSide.cs | 112 +- .../ModuleAlgorithm/ResetBakingPolygon.cs | 18 + .../ResetBakingPolygon.cs.meta | 11 + Assets/ModuleCore/ModuleAssets/AssetsPlate.cs | 12 +- .../BuilderInsertPointToPoint.cs | 62 +- .../BuilderPlatePresetsToPlate.cs | 16 +- Assets/ModuleCore/ModuleCore.cs | 24 +- Assets/ModuleCore/ModuleFind/FindBezier.cs | 8 +- Assets/ModuleCore/ModuleFind/FindPoint.cs | 10 +- Assets/ModuleCore/ModuleFind/FindSide.cs | 24 +- .../ModuleCore/ModuleVisual/VisualBaking.cs | 78 +- .../ModuleCore/ModuleVisual/VisualDesign.cs | 94 +- .../ModuleVisual/VisualPlateBaking.cs | 46 + .../ModuleVisual/VisualPlateBaking.cs.meta | 11 + .../ModuleVisual/VisualPlateDesign.cs | 41 + .../ModuleVisual/VisualPlateDesign.cs.meta | 11 + .../ModuleVisual/VisualSutureBaking.cs | 31 + .../ModuleVisual/VisualSutureBaking.cs.meta | 11 + .../ModuleVisual/VisualSutureDesign.cs | 31 + .../ModuleVisual/VisualSutureDesign.cs.meta | 11 + Assets/ModuleData/DataBezier.cs | 2 +- Assets/ModuleData/DataBorder.cs | 19 +- Assets/ModuleData/DataPlate/DataPlate.cs | 71 +- Assets/ModuleData/DataPlate/DataPlateLine.cs | 17 + .../DataPlate/DataPlateLine.cs.meta | 11 + Assets/ModuleData/DataPlate/DataPlatePoint.cs | 21 + .../DataPlate/DataPlatePoint.cs.meta | 11 + Assets/ModuleData/DataPlate/DataPlateSide.cs | 62 + .../DataPlate/DataPlateSide.cs.meta | 11 + .../ModuleData/DataPlate/DataPlateVertex.cs | 28 + .../DataPlate/DataPlateVertex.cs.meta | 11 + Assets/ModuleData/DataPlate/DataSide.cs | 6 +- Assets/ModuleData/DataSuture/DataSuture.cs | 25 +- .../ModuleData/DataSuture/DataSuturePoint.cs | 14 + .../DataSuture/DataSuturePoint.cs.meta | 11 + .../ModuleData/DataSuture/DataSutureSide.cs | 76 +- Assets/ModuleData/DataTriangle.cs | 1 + Assets/ModulePrefab/PrefabPlateBaking.cs | 10 +- Assets/ModulePrefab/PrefabPlateDesign.cs | 7 +- Assets/ModulePrefab/PrefabPoint.cs | 8 +- Assets/ModulePrefab/PrefabSide.cs | 13 +- Assets/ModulePrefab/PrefabSutureBaking.cs | 10 +- Assets/ModulePrefab/PrefabSutureDesign.cs | 10 +- Assets/ModulePrefab/PrefabSutureSideBaking.cs | 5 +- Assets/ModulePrefab/PrefabSutureSideDesign.cs | 5 +- Assets/ModuleTools/DataSideTool.cs | 18 +- Assets/ModuleTools/DataSutureTool.cs | 12 +- .../UnitAlgorithmBakingVertex.cs | 151 +++ .../UnitAlgorithmBakingVertex.cs.meta | 11 + .../UnitAlgorithm/UnitAlgorithmBezier.cs | 162 ++- .../UnitAlgorithm/UnitAlgorithmBorder.cs | 21 +- .../UnitAlgorithm/UnitAlgorithmEarCutting.cs | 24 +- .../UnitAlgorithm/UnitAlgorithmEdgePoint.cs | 4 +- .../UnitAlgorithmJobsSideSubdivision.cs | 239 ++++ .../UnitAlgorithmJobsSideSubdivision.cs.meta | 11 + .../UnitAlgorithmMergeTriangle.cs | 36 +- .../UnitAlgorithm/UnitAlgorithmRhombus.cs | 77 +- .../UnitAlgorithmSutureBaking.cs | 64 + .../UnitAlgorithmSutureBaking.cs.meta | 11 + .../UnitAlgorithmSutureDesign.cs | 52 + .../UnitAlgorithmSutureDesign.cs.meta | 11 + .../UnitAlgorithm/UnitAlgorithmVertex.cs | 120 +- Assets/ModuleUnit/UnitFind.meta | 8 + .../UnitFind/FindSideIntersectPoint.cs | 74 ++ .../UnitFind/FindSideIntersectPoint.cs.meta | 11 + Assets/ModuleUnit/UnitFind/UnitFind.cs | 8 + Assets/ModuleUnit/UnitFind/UnitFind.cs.meta | 11 + .../UnitMouseInput/BakingMobilePlate.cs | 8 +- .../ModuleUnit/UnitMouseInput/DesignBezier.cs | 4 +- .../ModuleUnit/UnitMouseInput/DesignInsert.cs | 45 +- .../ModuleUnit/UnitMouseInput/DesignMobile.cs | 6 +- .../ModuleUnit/UnitMouseInput/DesignSuture.cs | 53 +- .../UnitMouseInput/DesignSutureReversal.cs | 8 +- Packages/manifest.json | 1 + Packages/packages-lock.json | 10 + ProjectSettings/ShaderGraphSettings.asset | 17 + 81 files changed, 3073 insertions(+), 671 deletions(-) create mode 100644 Assets/ModuleCore/ModuleAlgorithm/AlgorithmSuture.cs create mode 100644 Assets/ModuleCore/ModuleAlgorithm/AlgorithmSuture.cs.meta create mode 100644 Assets/ModuleCore/ModuleAlgorithm/ResetBakingPolygon.cs create mode 100644 Assets/ModuleCore/ModuleAlgorithm/ResetBakingPolygon.cs.meta create mode 100644 Assets/ModuleCore/ModuleVisual/VisualPlateBaking.cs create mode 100644 Assets/ModuleCore/ModuleVisual/VisualPlateBaking.cs.meta create mode 100644 Assets/ModuleCore/ModuleVisual/VisualPlateDesign.cs create mode 100644 Assets/ModuleCore/ModuleVisual/VisualPlateDesign.cs.meta create mode 100644 Assets/ModuleCore/ModuleVisual/VisualSutureBaking.cs create mode 100644 Assets/ModuleCore/ModuleVisual/VisualSutureBaking.cs.meta create mode 100644 Assets/ModuleCore/ModuleVisual/VisualSutureDesign.cs create mode 100644 Assets/ModuleCore/ModuleVisual/VisualSutureDesign.cs.meta create mode 100644 Assets/ModuleData/DataPlate/DataPlateLine.cs create mode 100644 Assets/ModuleData/DataPlate/DataPlateLine.cs.meta create mode 100644 Assets/ModuleData/DataPlate/DataPlatePoint.cs create mode 100644 Assets/ModuleData/DataPlate/DataPlatePoint.cs.meta create mode 100644 Assets/ModuleData/DataPlate/DataPlateSide.cs create mode 100644 Assets/ModuleData/DataPlate/DataPlateSide.cs.meta create mode 100644 Assets/ModuleData/DataPlate/DataPlateVertex.cs create mode 100644 Assets/ModuleData/DataPlate/DataPlateVertex.cs.meta create mode 100644 Assets/ModuleData/DataSuture/DataSuturePoint.cs create mode 100644 Assets/ModuleData/DataSuture/DataSuturePoint.cs.meta create mode 100644 Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmBakingVertex.cs create mode 100644 Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmBakingVertex.cs.meta create mode 100644 Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmJobsSideSubdivision.cs create mode 100644 Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmJobsSideSubdivision.cs.meta create mode 100644 Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmSutureBaking.cs create mode 100644 Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmSutureBaking.cs.meta create mode 100644 Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmSutureDesign.cs create mode 100644 Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmSutureDesign.cs.meta create mode 100644 Assets/ModuleUnit/UnitFind.meta create mode 100644 Assets/ModuleUnit/UnitFind/FindSideIntersectPoint.cs create mode 100644 Assets/ModuleUnit/UnitFind/FindSideIntersectPoint.cs.meta create mode 100644 Assets/ModuleUnit/UnitFind/UnitFind.cs create mode 100644 Assets/ModuleUnit/UnitFind/UnitFind.cs.meta create mode 100644 ProjectSettings/ShaderGraphSettings.asset diff --git a/Assets/ModuleCore/ModuleAlgorithm/AlgorithmSidePoint.cs b/Assets/ModuleCore/ModuleAlgorithm/AlgorithmSidePoint.cs index 342d1a4..769e6ba 100644 --- a/Assets/ModuleCore/ModuleAlgorithm/AlgorithmSidePoint.cs +++ b/Assets/ModuleCore/ModuleAlgorithm/AlgorithmSidePoint.cs @@ -5,41 +5,41 @@ using UnityEngine; /// /// 计算位置到边上最近的点 /// -public class AlgorithmSidePoint : ModuleAlgorithm { +//public class AlgorithmSidePoint : ModuleAlgorithm { - protected override void Awake() => ModuleCore.AlgorithmSidePoint = this; +// protected override void Awake() => ModuleCore.AlgorithmSidePoint = this; - public override void Compute(DataIntersect data) { - Vector3 position = data.position - data.side.plate.designPosition; - for (int i = 0; i < data.side.lines.Length; i++) { - DataLine line = data.side.lines[i]; - if (!Compute(line, position, out Vector3 intersectPoint)) { continue; } - data.isIntersect = true; - data.intersectPoint = intersectPoint + data.side.plate.designPosition; - return; - } - } +// public override void Compute(DataIntersect data) { +// Vector3 position = data.position - data.side.plate.designPosition; +// for (int i = 0; i < data.side.lines.Length; i++) { +// DataLine line = data.side.lines[i]; +// if (!Compute(line, position, out Vector3 intersectPoint)) { continue; } +// data.isIntersect = true; +// data.intersectPoint = intersectPoint + data.side.plate.designPosition; +// return; +// } +// } - /// 查询匹配的边 - private bool Compute(DataLine line, Vector3 position, out Vector3 intersectPoint) { - return ProjectDistance(line.a, line.b, position, out intersectPoint); - } +// /// 查询匹配的边 +// private bool Compute(DataLine line, Vector3 position, out Vector3 intersectPoint) { +// return ProjectDistance(line.a, line.b, position, out intersectPoint); +// } - /// - /// 向量投影法 - /// 计算点c到线段ab最近的点 - /// - /// - /// - /// - /// 如果不在线段上返回 false - public static bool ProjectDistance(Vector3 a, Vector3 b, Vector3 c, out Vector3 intersectPoint) { - Vector3 ab = b - a; - Vector3 ac = c - a; - Vector3 p = Vector3.Project(ac, ab.normalized); - intersectPoint = p + a; - if (ab.normalized != p.normalized) { return false; } - if (ab.magnitude < p.magnitude) { return false; } - return true; - } -} +// /// +// /// 向量投影法 +// /// 计算点c到线段ab最近的点 +// /// +// /// +// /// +// /// +// /// 如果不在线段上返回 false +// public static bool ProjectDistance(Vector3 a, Vector3 b, Vector3 c, out Vector3 intersectPoint) { +// Vector3 ab = b - a; +// Vector3 ac = c - a; +// Vector3 p = Vector3.Project(ac, ab.normalized); +// intersectPoint = p + a; +// if (ab.normalized != p.normalized) { return false; } +// if (ab.magnitude < p.magnitude) { return false; } +// return true; +// } +//} diff --git a/Assets/ModuleCore/ModuleAlgorithm/AlgorithmSimplePolygon.cs b/Assets/ModuleCore/ModuleAlgorithm/AlgorithmSimplePolygon.cs index e35d332..b2adec3 100644 --- a/Assets/ModuleCore/ModuleAlgorithm/AlgorithmSimplePolygon.cs +++ b/Assets/ModuleCore/ModuleAlgorithm/AlgorithmSimplePolygon.cs @@ -6,18 +6,18 @@ using UnityEngine; /// 散列点生成简单多边形算法 /// public class AlgorithmSimplePolygon : ModuleAlgorithm { - private UnitAlgorithm AlgorithmSideSubdivision = new UnitAlgorithmBezier(); - private UnitAlgorithm AlgorithmTriangle = new UnitAlgorithmEarCutting(); - private UnitAlgorithm AlgorithmMergeTriangle = new UnitAlgorithmMergeTriangle(); + private UnitAlgorithm AlgorithmSideSubdivision = new UnitAlgorithmJobsSideSubdivision(); + private UnitAlgorithm AlgorithmTriangle = new UnitAlgorithmEarCutting(); + private UnitAlgorithm AlgorithmMergeTriangle = new UnitAlgorithmMergeTriangle(); protected override void Awake() => ModuleCore.AlgorithmSimplePolygon = this; - public override void Compute(DataPlate data) { + public override void Compute(DataPlate plate) { //遍历计算边(DataSide)上的细分点(positions)和线(lines) - AlgorithmSideSubdivision.Compute(data); + AlgorithmSideSubdivision.Compute(plate.dataDesign); //计算三角面 - AlgorithmTriangle.Compute(data); + AlgorithmTriangle.Compute(plate.dataDesign); //三角面列表转换网格 - AlgorithmMergeTriangle.Compute(data); + AlgorithmMergeTriangle.Compute(plate.dataDesign); } } diff --git a/Assets/ModuleCore/ModuleAlgorithm/AlgorithmSubdivisionPolygon.cs b/Assets/ModuleCore/ModuleAlgorithm/AlgorithmSubdivisionPolygon.cs index 55b04ac..594f235 100644 --- a/Assets/ModuleCore/ModuleAlgorithm/AlgorithmSubdivisionPolygon.cs +++ b/Assets/ModuleCore/ModuleAlgorithm/AlgorithmSubdivisionPolygon.cs @@ -1,41 +1,1188 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Linq; +using Unity.Burst; +using Unity.Collections; +using Unity.Jobs; using UnityEngine; /// /// 细分多边形算法 /// public class AlgorithmSubdivisionPolygon : ModuleAlgorithm { - private UnitAlgorithm AlgorithmSideSubdivision = new UnitAlgorithmBezier(); - private UnitAlgorithm AlgorithmBorder = new UnitAlgorithmBorder(); - private UnitAlgorithm AlgorithmVertex = new UnitAlgorithmVertex(); - private UnitAlgorithm AlgorithmTriangle = new UnitAlgorithmRhombus(); - private UnitAlgorithm AlgorithmMergeTriangle = new UnitAlgorithmMergeTriangle(); + private static readonly float Subdivide = 0.1f; + private UnitAlgorithm bezierPolygonSide = new BezierPolygonSide(); + + private UnitAlgorithm Boundary = new PolygonalBoundary(); + private UnitAlgorithm Vertex = new VertexSubdivision(); + //private UnitAlgorithm sideVertex = new SideSubdivision(); + private UnitAlgorithm Triangle = new DrawTriangle(); protected override void Awake() => ModuleCore.AlgorithmSubdivisionPolygon = this; - public override void Compute(DataPlate data) { - //遍历计算边(DataSide)上的细分点(positions)和线(lines) - Chronoscope("遍历计算边(DataSide)上的细分点(positions)和线(lines)消耗时间:", () => AlgorithmSideSubdivision.Compute(data)); - //计算多边形边界 - Chronoscope("计算多边形边界消耗时间:", () => AlgorithmBorder.Compute(data)); - //计算顶点 - Chronoscope("计算顶点消耗时间:", () => AlgorithmVertex.Compute(data)); - //计算三角面 - Chronoscope("计算三角面消耗时间:", () => AlgorithmTriangle.Compute(data)); - //三角面列表转换网格 - Chronoscope("三角面列表转换网格消耗时间:", () => AlgorithmMergeTriangle.Compute(data)); + public override void Compute(DataPlate plate) { + Polygon polygon = To(plate); + //第一次计算边长 + bezierPolygonSide.Compute(polygon); + //第二次计算细分边长 + bezierPolygonSide.Compute(polygon); + + //Chronoscope("细分多边形计算耗时:", () => { + // //粗糙细分,生成边界 + // Boundary.Compute(plate); + // //计算顶点 + // Vertex.Compute(plate); + // //计算边点 + // SideVertex.Compute(plate); + // //计算三角面 + // Triangle.Compute(plate); + //}); } + #region 数据转换 + public Polygon To(DataPlate plate) { + Polygon polygon = new Polygon(); + polygon.sides = new PolygonSide[plate.plateSides.Count]; + for (int i = 0; i < plate.plateSides.Count; i++) { + polygon.sides[i] = To(plate.plateSides[i]); + } + return polygon; + } + public PolygonSide To(DataPlateSide plateSide) { + PolygonSide polygonSide = new PolygonSide(); + polygonSide.quotient = 20; + polygonSide.bezier = plateSide.bezier; + polygonSide.aPoint = plateSide.aPoint.position; + polygonSide.bPoint = plateSide.bPoint.position; + polygonSide.aBezier = plateSide.aBezier; + polygonSide.bBezier = plateSide.bBezier; + return polygonSide; + } + #endregion + + #region 数据结构 + public struct Polygon { + /// 多边形边 + public PolygonSide[] sides; + /// 多边形边界 + public PolygonBorder border; + } + public struct PolygonBorder { + /// minX + public float minX; + /// maxX + public float maxX; + /// minY + public float minY; + /// maxY + public float maxY; + /// 多边形边界点 + public Vector3[] positions; + + /// 边界宽 + public float Wide => maxX - minX; + /// 边界高 + public float High => maxY - minY; + /// 网格宽 + public int GridWide => Mathf.FloorToInt(Wide / Subdivide) + 1; + /// 网格高 + public int GridHigh => Mathf.FloorToInt(High / Subdivide) + 1; + /// 最小点 + public Vector3 MinPoint => new Vector3(minX, minY, 0); + /// 最大点 + public Vector3 MaxPoint => new Vector3(maxX, maxY, 0); + } + public struct PolygonSide { + /// 细分数 + public int quotient; + /// 长度 + public float length; + /// 贝塞尔类型 + public Bezier bezier; + /// a点 + public Vector3 aPoint; + /// b点 + public Vector3 bPoint; + /// a点贝塞尔点 + public Vector3 aBezier; + /// b点贝塞尔点 + public Vector3 bBezier; + + /// + public Vector3[] positions; + /// 线 + public PolygonLine[] lines; + /// 边点 + public PolygonSideVertex[] vertexs; + } + public struct PolygonSideVertex { + /// 到边起点的距离 + public float origin; + /// 位置 + public Vector3 position; + } + public struct PolygonLine { + /// 线段起点a + public Vector3 a; + /// 线段终点b + public Vector3 b; + /// 到边起点的距离 + public float origin; + } + #endregion + + #region 计时器 /// 是否启用计时器 - private readonly bool isEnableTimer = true; + public static readonly bool isEnableTimer = true; /// 计时器 - private void Chronoscope(string content, Action action) { + public static void Chronoscope(string content, Action action) { if (!isEnableTimer) { action?.Invoke(); return; } float time = Time.realtimeSinceStartup; action?.Invoke(); float consumed = Time.realtimeSinceStartup - time; Debug.Log($"{content}{consumed * 1000}"); } + #endregion + + #region 算法函数 + /// + /// 一阶贝塞尔算法 + /// + /// 起点 + /// 终点 + /// 进度 + /// + 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; + } + /// + /// 边界数据 + /// + /// 边界点数组 + /// + public static DataBorder Border(Vector3[] points) { + float minX = 0; float minY = 0; + float maxX = 0; float maxY = 0; + 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, points); + } + /// + /// 数组索引转换网格xy + /// + /// + /// + /// + /// + public static Vector2Int IndexToXY(int index, int wide) { + int y = Math.DivRem(index, wide, out int x); + return new Vector2Int(x, y); + } + /// + /// 网格xy转换数组索引 + /// + /// + /// + public static int XYToIndex(Vector2Int v2, int wide) { + return v2.y * wide + v2.x; + } + /// + /// 校验xy是否超限 + /// + /// + /// + /// + /// + /// + public static bool TryXY(int x, int y, int wide, int high) { + return x >= 0 && x < wide && y >= 0 && y < high; + } + /// + /// 转角法查询位置是否在板片内 + /// + /// 按顺序组成多边形的顶点 + /// 位置 + /// + public static bool FindPlateInside(NativeArray points, Vector3 position) { + double angles = 0; + for (int i = 0; i < points.Length; i++) { + Vector3 a = points[LoopIndexTool.LoopIndex(i + 0, points.Length)] - position; + Vector3 b = points[LoopIndexTool.LoopIndex(i + 1, points.Length)] - position; + float angle = Vector2.SignedAngle(a, b); + angles += angle; + } + int normal = (int)(angles * 1000); + return normal > 1000; + } + /// + /// 计算AB与CD两条线段的交点. + /// + /// A点 + /// B点 + /// C点 + /// D点 + /// AB与CD的交点 + /// 是否相交 true:相交 false:未相交 + public static 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; + } + #endregion + + #region 贝塞尔曲线化多边形的边 + public class BezierPolygonSide : UnitAlgorithm { + + #region 执行 + public void Compute(Polygon polygon) { + //创建作业任务 + int count = polygon.sides.Length; + NativeArray jobs = new NativeArray(count, Allocator.Temp); + NativeArray handles = new NativeArray(count, Allocator.Temp); + for (int i = 0; i < count; i++) { + jobs[i] = To(polygon.sides[i]); + handles[i] = jobs[i].Schedule(); + } + //执行作业 + JobHandle.CompleteAll(handles); + //转换数据 + for (int i = 0; i < count; i++) { To(jobs[i], polygon.sides[i]); } + } + #endregion + + #region 转换 + /// 转换作业数据 + private JobBezierPolygonSide To(PolygonSide polygonSide) { + JobBezierPolygonSide jobBezierPolygonSide = new JobBezierPolygonSide(); + jobBezierPolygonSide.quotient = polygonSide.quotient; + jobBezierPolygonSide.bezier = polygonSide.bezier; + jobBezierPolygonSide.aPoint = polygonSide.aPoint; + jobBezierPolygonSide.bPoint = polygonSide.bPoint; + jobBezierPolygonSide.aBezier = polygonSide.aBezier; + jobBezierPolygonSide.bBezier = polygonSide.bBezier; + + int quotient = polygonSide.quotient; + jobBezierPolygonSide.length = new NativeArray(1, Allocator.TempJob); + jobBezierPolygonSide.positions = new NativeArray(quotient, Allocator.TempJob); + jobBezierPolygonSide.lines = new NativeArray(quotient - 1, Allocator.TempJob); + return jobBezierPolygonSide; + } + /// 转换托管数据 + private void To(JobBezierPolygonSide job, PolygonSide polygonSide) { + polygonSide.quotient = (int)(Subdivide / job.length[0]); + polygonSide.length = job.length[0]; + polygonSide.positions = job.positions.ToArray(); + polygonSide.lines = job.lines.ToArray(); + job.length.Dispose(); + job.positions.Dispose(); + job.lines.Dispose(); + } + #endregion + + #region Jobs + [BurstCompile] + public struct JobBezierPolygonSide : IJob { + /// 细分数 + public int quotient; + /// 贝塞尔类型 + public Bezier bezier; + /// a点 + public Vector3 aPoint; + /// b点 + public Vector3 bPoint; + /// a点贝塞尔点 + public Vector3 aBezier; + /// b点贝塞尔点 + public Vector3 bBezier; + + /// 长度 + public NativeArray length; + /// + public NativeArray positions; + /// 线 + public NativeArray lines; + + public void Execute() { + //细分点 + if (bezier == Bezier.一阶) { ComputeBezierA(); } + if (bezier == Bezier.二阶) { ComputeBezierB(); } + if (bezier == Bezier.三阶) { ComputeBezierC(); } + //线段 + for (int i = 0; i < quotient - 1; i++) { + PolygonLine line = new PolygonLine(); + 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() { + Vector3 a = aPoint; + Vector3 b = bPoint; + for (int i = 0; i < quotient; i++) { + float t = i / (float)(quotient - 1); + positions[i] = ComputeBezier(a, b, t); + } + } + public void ComputeBezierB() { + Vector3 a = aPoint; + Vector3 b = aBezier; + Vector3 c = bPoint; + for (int i = 0; i < quotient; i++) { + float t = i / (float)(quotient - 1); + positions[i] = ComputeBezier(a, b, c, t); + } + } + public void ComputeBezierC() { + Vector3 a = aPoint; + Vector3 b = aBezier; + Vector3 c = bBezier; + Vector3 d = bPoint; + for (int i = 0; i < quotient; i++) { + float t = i / (float)(quotient - 1); + positions[i] = ComputeBezier(a, b, c, d, t); + } + } + } + #endregion + + } + + #endregion + + #region 多边形边界 + public class PolygonalBorder : UnitAlgorithm { + + #region 执行 + public void Compute(Polygon polygon) { + int count = polygon.sides.Length; + //创建作业任务 + JobPolygonalBorder job = To(polygon); + //执行作业 + JobHandle dependency = new JobHandle(); + JobHandle handle = job.Schedule(count, dependency); + handle.Complete(); + //转换数据 + polygon.border = To(job); + //释放 + job.border.Dispose(); + job.positions.Dispose(); + } + #endregion + + #region 转换 + private JobPolygonalBorder To(Polygon polygon) { + List positions = new List(); + for (int i = 0; i < polygon.sides.Length; i++) { + positions.AddRange(polygon.sides[i].positions); + } + + JobPolygonalBorder jobPolygonalBorder = new JobPolygonalBorder(); + jobPolygonalBorder.border = new NativeArray(4, Allocator.TempJob); + jobPolygonalBorder.positions = new NativeArray(positions.ToArray(), Allocator.TempJob); + return jobPolygonalBorder; + } + private PolygonBorder To(JobPolygonalBorder job) { + PolygonBorder border = new PolygonBorder(); + border.minX = job.border[0]; + border.maxX = job.border[1]; + border.minY = job.border[2]; + border.maxY = job.border[3]; + border.positions = job.positions.ToArray(); + return border; + } + #endregion + + #region Jobs + [BurstCompile] + public struct JobPolygonalBorder : IJobFor { + /// 0 = minX , 1 = MaxX , 2 = minY, 3 = MaxY + public NativeArray border; + /// + public NativeArray positions; + + public void Execute(int index) { + Vector3 position = positions[index]; + if (position.x < border[0]) { border[0] = position.x; } + if (position.x > border[1]) { border[1] = position.x; } + if (position.y < border[2]) { border[2] = position.y; } + if (position.y > border[3]) { border[3] = position.y; } + } + } + #endregion + + } + #endregion + + #region 边缘细分顶点 + public class SideSubdivisionVertex : UnitAlgorithm { + + #region 执行 + public void Compute(Polygon polygon) { + //创建作业任务 + int count = polygon.sides.Length; + NativeArray jobs = new NativeArray(count, Allocator.Temp); + NativeArray handles = new NativeArray(count, Allocator.Temp); + for (int i = 0; i < count; i++) { + jobs[i] = To(polygon, polygon.sides[i]); + handles[i] = jobs[i].Schedule(); + } + //执行作业 + JobHandle.CompleteAll(handles); + //转换数据 + for (int i = 0; i < count; i++) { To(jobs[i], polygon.sides[i]); } + } + #endregion + + #region 转换 + private JobSideVertex To(Polygon polygon, PolygonSide polygonSide) { + JobSideVertex jobSideVertex = new JobSideVertex(); + jobSideVertex.gridWide = polygon.border.GridWide; + jobSideVertex.gridHigh = polygon.border.GridHigh; + jobSideVertex.interval = Subdivide; + jobSideVertex.minX = polygon.border.minX; + jobSideVertex.maxX = polygon.border.maxX; + jobSideVertex.minY = polygon.border.minY; + jobSideVertex.maxY = polygon.border.maxY; + jobSideVertex.minPoint = polygon.border.MinPoint; + jobSideVertex.lines = new NativeArray(polygonSide.lines, Allocator.TempJob); + jobSideVertex.vertexs = new NativeList(Allocator.TempJob); + return jobSideVertex; + } + /// 转换托管数据 + private void To(JobSideVertex job, PolygonSide polygonSide) { + polygonSide.vertexs = job.vertexs.ToArray(); + job.lines.Dispose(); + job.vertexs.Dispose(); + } + #endregion + + #region Jobs + [BurstCompile] + public struct JobSideVertex : IJob { + /// 网格宽 + public int gridWide; + /// 网格高 + public int gridHigh; + /// 网格间隔 + public float interval; + /// minX + public float minX; + /// maxX + public float maxX; + /// minY + public float minY; + /// maxY + public float maxY; + /// 原点 + public Vector3 minPoint; + /// 输入边线 + public NativeArray lines; + + /// 输出边点 + public NativeList vertexs; + + public void Execute() { + for (int x = 0; x < gridWide; x++) { + Vector3 a = new Vector3(minX + x * interval, minY - 1); + Vector3 b = new Vector3(minX + x * interval, maxY + 1); + Subdivision(a, b); + } + for (int y = 0; y < gridHigh; y++) { + Vector3 a = new Vector3(minX - 1, minY + y * interval); + Vector3 b = new Vector3(maxX + 1, minY + y * interval); + Subdivision(a, b); + } + } + public void Subdivision(Vector3 a, Vector3 b) { + for (int i = 0; i < lines.Length; i++) { + PolygonLine line = lines[i]; + if (!TryGetIntersectPoint(a, b, line.a, line.b, out Vector3 intersectPoint)) { continue; } + float distance = Vector3.Distance(line.a, intersectPoint) + line.origin; + PolygonSideVertex sideVertex = new PolygonSideVertex(); + sideVertex.origin = distance; + sideVertex.position = intersectPoint; + vertexs.Add(sideVertex); + } + } + } + #endregion + + } + #endregion + + #region 内部细分顶点 + public class InsideSubdivisionVertex : UnitAlgorithm { + + #region 执行 + public void Compute(Polygon data) { + throw new NotImplementedException(); + } + #endregion + + #region 转换 + + #endregion + + #region Jobs + + #endregion + + } + #endregion + + #region 多边形边界 + public class PolygonalBoundary : UnitAlgorithm { + + #region 执行 + public void Compute(DataPlate plate) { + int count = plate.plateSides.Count; + List plateSides = plate.plateSides; + //创建作业任务 + NativeArray jobs = new NativeArray(count, Allocator.Temp); + NativeArray handles = new NativeArray(count, Allocator.Temp); + for (int i = 0; i < count; i++) { + jobs[i] = DataPlateSideToJobSideSubdivision(plateSides[i], 10); + handles[i] = jobs[i].Schedule(); + } + //执行作业 + JobHandle.CompleteAll(handles); + //转换数据 + List points = new List(); + for (int i = 0; i < count; i++) { + OutputSideToDataPlateSide(jobs[i].outputSide, plateSides[i]); + points.AddRange(plateSides[i].dataBaking.positions); + } + plate.dataBaking.border = Border(points.Distinct().ToArray()); + } + #endregion + + #region Jobs + [BurstCompile] + public struct JobPolygonalBoundary : IJob { + /// 输入 + public InputSide inputSide; + /// 输出 + public OutputSide outputSide; + + public void Execute() { + //细分点 + for (int i = 0; i < inputSide.quotient; i++) { + float t = i / (float)(inputSide.quotient - 1); + if (inputSide.bezier == Bezier.一阶) { + outputSide.positions[i] = ComputeBezier(inputSide.aPoint, inputSide.bPoint, t); + } + if (inputSide.bezier == Bezier.二阶) { + outputSide.positions[i] = ComputeBezier(inputSide.aPoint, inputSide.aBezier, inputSide.bPoint, t); + } + if (inputSide.bezier == Bezier.三阶) { + outputSide.positions[i] = ComputeBezier(inputSide.aPoint, inputSide.aBezier, inputSide.bBezier, inputSide.bPoint, t); + } + } + + //线段 + for (int i = 0; i < inputSide.quotient - 1; i++) { + OutputLine line = new OutputLine(); + line.a = outputSide.positions[i]; + line.b = outputSide.positions[i + 1]; + line.origin = outputSide.length; + outputSide.lines[i] = line; + outputSide.length += Vector3.Distance(line.a, line.b); + } + } + } + #endregion + + #region 转换 + /// 转换作业数据 + private JobPolygonalBoundary DataPlateSideToJobSideSubdivision(DataPlateSide plateSide, int quotient) { + InputSide inputSide = new InputSide(); + inputSide.bezier = plateSide.bezier; + inputSide.aPoint = plateSide.aPoint.position; + inputSide.bPoint = plateSide.bPoint.position; + inputSide.aBezier = plateSide.aBezier; + inputSide.bBezier = plateSide.bBezier; + inputSide.quotient = quotient; + + OutputSide outputSide = new OutputSide(); + outputSide.positions = new NativeArray(quotient, Allocator.TempJob); + outputSide.lines = new NativeArray(quotient - 1, Allocator.TempJob); + + JobPolygonalBoundary jobPolygonalBoundary = new JobPolygonalBoundary(); + jobPolygonalBoundary.inputSide = inputSide; + jobPolygonalBoundary.outputSide = outputSide; + return jobPolygonalBoundary; + } + /// 转换托管数据 + private void OutputSideToDataPlateSide(OutputSide output, DataPlateSide plateSide) { + DataPlateSideBaking baking = plateSide.dataBaking; + baking.length = output.length; + baking.positions = output.positions.ToArray(); + DataPlateLine[] lines = new DataPlateLine[output.lines.Length]; + for (int i = 0; i < output.lines.Length; i++) { + lines[i] = OutputLineToDataPlateLine(output.lines[i]); + } + baking.lines = lines; + output.positions.Dispose(); + output.lines.Dispose(); + } + /// 转换托管数据 + public DataPlateLine OutputLineToDataPlateLine(OutputLine output) { + DataPlateLine line = new DataPlateLine(); + line.a = output.a; + line.b = output.b; + line.origin = output.origin; + return line; + } + #endregion + + #region 输入 + public struct InputSide { + /// 贝塞尔类型 + public Bezier bezier; + /// a点 + public Vector3 aPoint; + /// b点 + public Vector3 bPoint; + /// a点贝塞尔点 + public Vector3 aBezier; + /// b点贝塞尔点 + public Vector3 bBezier; + /// 细分数 + public int quotient; + } + #endregion + + #region 输出 + public struct OutputSide { + /// 总长度 + public float length; + /// + public NativeArray positions; + /// 线 + public NativeArray lines; + } + public struct OutputLine { + /// 线段起点a + public Vector3 a; + /// 线段终点b + public Vector3 b; + /// 边原点距离 + public float origin; + } + #endregion + + } + #endregion + + #region 顶点细分 + public class VertexSubdivision : UnitAlgorithm { + + #region 执行 + public void Compute(DataPlate plate) { + DataBorder border = plate.dataBaking.border; + //创建作业任务 + int maxIndex = border.GridWide * border.GridHigh; + JobVertex job = new JobVertex(); + job.input = DataPlateToInputInitialize(plate); + job.outputVertices = new NativeArray(maxIndex, Allocator.TempJob); + //执行作业 + JobHandle handle = job.Schedule(maxIndex, 32); + handle.Complete(); + //转换数据 + plate.dataBaking.vertexs = OutputVertexToDataPlateVertex(job.outputVertices); + //释放 + job.input.points.Dispose(); + job.outputVertices.Dispose(); + } + #endregion + + #region Jobs + [BurstCompile] + public struct JobVertex : IJobParallelFor { + /// 输入 + [ReadOnly] public InputInitialize input; + /// 输出 + public NativeArray outputVertices; + + public void Execute(int index) { + Vector2Int v2 = IndexToXY(index, input.wide); + Vector3 position = new Vector3(v2.x, v2.y) * input.interval + input.origin; + OutputVertex vertex = new OutputVertex(); + vertex.isValid = FindPlateInside(input.points, position); + vertex.position = position; + outputVertices[index] = vertex; + } + } + #endregion + + #region 转换 + private InputInitialize DataPlateToInputInitialize(DataPlate plate) { + DataBorder border = plate.dataBaking.border; + InputInitialize inputInitialize = new InputInitialize(); + inputInitialize.wide = border.GridWide; + inputInitialize.interval = border.smooth; + inputInitialize.origin = border.MinPoint; + inputInitialize.points = new NativeArray(border.points, Allocator.TempJob); + return inputInitialize; + } + private DataPlateVertex[] OutputVertexToDataPlateVertex(NativeArray outputVertices) { + DataPlateVertex[] array = new DataPlateVertex[outputVertices.Length]; + for (int i = 0; i < outputVertices.Length; i++) { + DataPlateVertex vertex = new DataPlateVertex(); + vertex.isValid = outputVertices[i].isValid; + vertex.position = outputVertices[i].position; + array[i] = vertex; + } + return array; + } + #endregion + + #region 输入 + public struct InputInitialize { + /// 网格宽 + public int wide; + /// 网格间隔 + public float interval; + /// 原点 + public Vector3 origin; + /// 多边形边缘点 + public NativeArray points; + } + #endregion + + #region 输出 + public struct OutputVertex { + /// 是否是有效顶点 + public bool isValid; + /// 位置 + public Vector3 position; + } + #endregion + + } + #endregion + + #region 边缘细分 + public class SideSubdivision : UnitAlgorithm { + + #region 执行 + public void Compute(DataPlate plate) { + int count = plate.plateSides.Count; + List plateSides = plate.plateSides; + //创建作业任务 + InputBorder border = DataPlateToInputBorder(plate); + NativeArray jobs = new NativeArray(count, Allocator.Temp); + NativeArray handles = new NativeArray(count, Allocator.Temp); + for (int i = 0; i < count; i++) { + jobs[i] = DataPlateSideToJobSideSubdivision(plateSides[i], border); + handles[i] = jobs[i].Schedule(); + } + //执行作业 + JobHandle.CompleteAll(handles); + //转换数据 + for (int i = 0; i < jobs.Length; i++) { + MergeSideVertex(jobs[i], plate); + } + } + #endregion + + #region Jobs + public struct JobSideSubdivision : IJob { + /// 输入边界 + [ReadOnly] public InputBorder inputBorder; + /// 输入边线 + [ReadOnly] public NativeArray inputLines; + /// 输出边点 + public NativeList outputSideVertexs; + + public void Execute() { + for (int x = 0; x < inputBorder.wide; x++) { + Vector3 a = new Vector3(inputBorder.minX + x * inputBorder.interval, inputBorder.minY - 1); + Vector3 b = new Vector3(inputBorder.minX + x * inputBorder.interval, inputBorder.maxY + 1); + Subdivision(a, b); + } + for (int y = 0; y < inputBorder.high; y++) { + Vector3 a = new Vector3(inputBorder.minX - 1, inputBorder.minY + y * inputBorder.interval); + Vector3 b = new Vector3(inputBorder.maxX + 1, inputBorder.minY + y * inputBorder.interval); + Subdivision(a, b); + } + } + public void Subdivision(Vector3 a, Vector3 b) { + for (int i = 0; i < inputLines.Length; i++) { + InputLine line = inputLines[i]; + if (!TryGetIntersectPoint(a, b, line.a, line.b, out Vector3 intersectPoint)) { continue; } + float distance = Vector3.Distance(line.a, intersectPoint) + line.origin; + OutputSideVertex sideVertex = new OutputSideVertex(); + sideVertex.origin = distance; + sideVertex.position = intersectPoint; + outputSideVertexs.Add(sideVertex); + } + } + } + #endregion + + #region 转换 + private InputBorder DataPlateToInputBorder(DataPlate plate) { + InputBorder inputBorder = new InputBorder(); + inputBorder.wide = plate.dataBaking.border.GridWide; + inputBorder.high = plate.dataBaking.border.GridHigh; + inputBorder.interval = plate.dataBaking.border.smooth; + inputBorder.minX = plate.dataBaking.border.minX; + inputBorder.maxX = plate.dataBaking.border.maxX; + inputBorder.minY = plate.dataBaking.border.minY; + inputBorder.maxY = plate.dataBaking.border.maxY; + inputBorder.origin = plate.dataBaking.border.MinPoint; + return inputBorder; + } + private JobSideSubdivision DataPlateSideToJobSideSubdivision(DataPlateSide plateSide, InputBorder border) { + DataPlateLine[] lines = plateSide.dataBaking.lines; + NativeArray inputLines = new NativeArray(lines.Length, Allocator.TempJob); + for (int i = 0; i < lines.Length; i++) { + InputLine line = new InputLine(); + line.a = lines[i].a; + line.b = lines[i].b; + line.origin = lines[i].origin; + inputLines[i] = line; + } + + JobSideSubdivision jobSideSubdivision = new JobSideSubdivision(); + jobSideSubdivision.inputBorder = border; + jobSideSubdivision.inputLines = inputLines; + jobSideSubdivision.outputSideVertexs = new NativeList(Allocator.TempJob); + return jobSideSubdivision; + } + private void MergeSideVertex(JobSideSubdivision job, DataPlate plate) { + DataPlateVertex[] plateVertexs = plate.dataBaking.vertexs; + float interval = job.inputBorder.interval; + Vector3 offset = job.inputBorder.origin - new Vector3(interval, interval, 0) * 0.1f; + for (int i = 0; i < job.outputSideVertexs.Length; i++) { + Vector3 position = job.outputSideVertexs[i].position; + Vector3 gridPosition = position - offset; + int vertexX = Mathf.FloorToInt(gridPosition.x / interval); + int vertexY = Mathf.FloorToInt(gridPosition.y / interval); + vertexX = Math.Clamp(vertexX, 0, job.inputBorder.wide - 1); + vertexY = Math.Clamp(vertexY, 0, job.inputBorder.high - 1); + int index = XYToIndex(new Vector2Int(vertexX, vertexY), job.inputBorder.wide); + + plateVertexs[index].isValid = true; + plateVertexs[index].position = position; + } + job.inputLines.Dispose(); + job.outputSideVertexs.Dispose(); + } + #endregion + + #region 输入 + public struct InputBorder { + /// 网格宽 + public int wide; + /// 网格高 + public int high; + /// 网格间隔 + public float interval; + /// minX + public float minX; + /// maxX + public float maxX; + /// minY + public float minY; + /// maxY + public float maxY; + /// 原点 + public Vector3 origin; + } + public struct InputLine { + /// 线段起点a + public Vector3 a; + /// 线段终点b + public Vector3 b; + /// 原始距离 + public float origin; + } + #endregion + + #region 输出 + public struct OutputSideVertex { + /// 到边起点的距离 + public float origin; + /// 位置 + public Vector3 position; + } + #endregion + + } + #endregion + + #region 绘制三角形 + public class DrawTriangle : UnitAlgorithm { + + #region 执行 + public void Compute(DataPlate plate) { + DataPlateVertex[] vertexs = plate.dataBaking.vertexs; + int maxIndex = vertexs.Length; + DataBorder border = plate.dataBaking.border; + //创建作业任务 + JobRhombus job = new JobRhombus(); + job.inputBorder = new InputBorder() { wide = border.GridWide, high = border.GridHigh }; + job.inputVertexs = DataPlateToInputVertex(vertexs); + job.outputVertexs = new NativeArray(maxIndex, Allocator.TempJob); + //执行作业 + JobHandle handle = job.Schedule(maxIndex, 32); + handle.Complete(); + //三角形合并 + plate.dataBaking.mesh = new Mesh(); + plate.dataBaking.mesh.vertices = Vertices(job.outputVertexs); + plate.dataBaking.mesh.uv = UV(job.outputVertexs); + plate.dataBaking.mesh.triangles = Triangles(job.outputVertexs); + plate.dataBaking.mesh.RecalculateBounds(); + plate.dataBaking.mesh.RecalculateNormals(); + //释放 + job.inputVertexs.Dispose(); + job.outputVertexs.Dispose(); + } + #endregion + + #region Jobs + [BurstCompile] + public struct JobRhombus : IJobParallelFor { + /// 输入边界 + public InputBorder inputBorder; + /// 输入网格 + [ReadOnly] public NativeArray inputVertexs; + /// 输出顶点 + public NativeArray outputVertexs; + + public struct ValidVertex { + /// 数组索引 + public int index; + /// 是否是有效顶点 + public bool isValid; + } + + public void Execute(int index) { + InputVertex input = inputVertexs[index]; + + Vector2Int xy = IndexToXY(index, inputBorder.wide); + + ValidVertex above = TryVertex(xy.x, xy.y + 1, inputBorder.wide, inputBorder.high); + ValidVertex below = TryVertex(xy.x, xy.y - 1, inputBorder.wide, inputBorder.high); + ValidVertex lefts = TryVertex(xy.x - 1, xy.y, inputBorder.wide, inputBorder.high); + ValidVertex right = TryVertex(xy.x + 1, xy.y, inputBorder.wide, inputBorder.high); + + ValidVertex leftsAbove = TryVertex(xy.x - 1, xy.y + 1, inputBorder.wide, inputBorder.high); + ValidVertex leftsBelow = TryVertex(xy.x - 1, xy.y - 1, inputBorder.wide, inputBorder.high); + ValidVertex rightAbove = TryVertex(xy.x + 1, xy.y + 1, inputBorder.wide, inputBorder.high); + ValidVertex rightBelow = TryVertex(xy.x + 1, xy.y - 1, inputBorder.wide, inputBorder.high); + + OutputVertex output = new OutputVertex { + isValid = input.isValid, + position = input.position + }; + + //默认绘制左上角 + output.a = new OutputTriangle { + isValid = above.isValid && lefts.isValid, + a = input.index, + c = lefts.index, + b = above.index + }; + //默认绘制右下角 + output.b = new OutputTriangle { + isValid = below.isValid && right.isValid, + a = input.index, + c = right.index, + b = below.index + }; + //如果右上角点不存在,则尝试绘制右上角 + output.c = new OutputTriangle { + isValid = !rightAbove.isValid && above.isValid && right.isValid, + a = input.index, + c = above.index, + b = right.index + }; + //如果左下角点不存在,则尝试绘制左下角 + output.d = new OutputTriangle { + isValid = !leftsBelow.isValid && below.isValid && lefts.isValid, + a = input.index, + c = below.index, + b = lefts.index + }; + outputVertexs[index] = output; + } + public ValidVertex TryVertex(int x, int y, int wide, int high) { + ValidVertex vertex = new ValidVertex() { index = -1, isValid = false }; + if (!TryXY(x, y, wide, high)) { return vertex; } + int index = XYToIndex(new Vector2Int(x, y), wide); + InputVertex input = inputVertexs[index]; + vertex.index = input.index; + vertex.isValid = input.isValid; + return vertex; + } + } + #endregion + + #region 转换 + private NativeArray DataPlateToInputVertex(DataPlateVertex[] vertexs) { + NativeArray InputVertexs = new NativeArray(vertexs.Length, Allocator.TempJob); + int index = 0; + for (int i = 0; i < vertexs.Length; i++) { + InputVertex vertex = new InputVertex(); + vertex.index = vertexs[i].isValid ? index : -1; + vertex.isValid = vertexs[i].isValid; + vertex.position = vertexs[i].position; + InputVertexs[i] = vertex; + if (vertexs[i].isValid) { index++; } + } + return InputVertexs; + } + private Vector3[] Vertices(NativeArray outputVertexs) { + List Vertices = new List(); + for (int i = 0; i < outputVertexs.Length; i++) { + if (!outputVertexs[i].isValid) { continue; } + Vertices.Add(outputVertexs[i].position); + } + return Vertices.ToArray(); + } + private Vector2[] UV(NativeArray outputVertexs) { + //展开uv (顶点去掉z坐标就是未缩放的平面UV) + List uv = new List(); + for (int i = 0; i < outputVertexs.Length; i++) { + if (!outputVertexs[i].isValid) { continue; } + uv.Add(new Vector2(outputVertexs[i].position.x, outputVertexs[i].position.y)); + } + return uv.ToArray(); + } + private int[] Triangles(NativeArray outputVertexs) { + List triangles = new List(); + for (int i = 0; i < outputVertexs.Length; i++) { + if (!outputVertexs[i].isValid) { continue; } + triangles.AddRange(Triangles(outputVertexs[i])); + } + return triangles.ToArray(); + } + private List Triangles(OutputVertex vertex) { + List triangles = new List(); + if (vertex.a.isValid) { triangles.AddRange(Triangles(vertex.a)); } + if (vertex.b.isValid) { triangles.AddRange(Triangles(vertex.b)); } + if (vertex.c.isValid) { triangles.AddRange(Triangles(vertex.c)); } + if (vertex.d.isValid) { triangles.AddRange(Triangles(vertex.d)); } + return triangles; + } + private List Triangles(OutputTriangle triangle) { + return new List() { triangle.a, triangle.b, triangle.c }; + } + #endregion + + #region 输入 + public struct InputBorder { + /// 网格宽 + public int wide; + /// 网格高 + public int high; + } + public struct InputVertex { + /// 数组索引 + public int index; + /// 是否是有效顶点 + public bool isValid; + /// 设计视图中位置 + public Vector3 position; + } + #endregion + + #region 输出 + public struct OutputVertex { + /// 是否是有效 + public bool isValid; + /// 顶点位置 + public Vector3 position; + /// 左上角 + public OutputTriangle a; + /// 右下角 + public OutputTriangle b; + /// 右上角 + public OutputTriangle c; + /// 左下角 + public OutputTriangle d; + } + public struct OutputTriangle { + /// 是否是有效 + public bool isValid; + /// a点索引 + public int a; + /// b点索引 + public int b; + /// c点索引 + public int c; + } + #endregion + + } + #endregion } diff --git a/Assets/ModuleCore/ModuleAlgorithm/AlgorithmSuture.cs b/Assets/ModuleCore/ModuleAlgorithm/AlgorithmSuture.cs new file mode 100644 index 0000000..017bb67 --- /dev/null +++ b/Assets/ModuleCore/ModuleAlgorithm/AlgorithmSuture.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +/// +/// 缝合边算法模块 +/// +public class AlgorithmSuture : ModuleAlgorithm { + /// 设计的缝合线 + public UnitAlgorithm SutureDesign = new UnitAlgorithmSutureDesign(); + /// 烘焙的缝合线 + public UnitAlgorithm SutureBaking = new UnitAlgorithmSutureBaking(); + + protected override void Awake() => ModuleCore.AlgorithmSuture = this; + + public override void Compute(DataSuture suture) { + //缝合边长 + float aLength = suture.a.plateSide.dataDesign.length; + float bLength = suture.b.plateSide.dataDesign.length; + suture.length = aLength < bLength ? aLength : bLength; + //设计缝合顶点 + SutureDesign.Compute(suture.a); + SutureDesign.Compute(suture.b); + //烘焙缝合顶点 + SutureBaking.Compute(suture.a); + SutureBaking.Compute(suture.b); + //缝合锚点 + suture.points = new List(); + suture.points.AddRange(Compute(suture.a, suture.b)); + suture.points.AddRange(Compute(suture.b, suture.a)); + } + private List Compute(DataSutureSide a, DataSutureSide b) { + DataSutureSideVertex[] vertexs = a.dataBaking.vertexs; + DataSutureSideVertex[] allVertexs = b.dataBaking.allVertexs; + List suturePoints = new List(); + for (int i = 0; i < vertexs.Length; i++) { + DataSutureSideVertex vertex = vertexs[i]; + for (int j = 0; j < allVertexs.Length; j++) { + DataSutureSideVertex anchor = allVertexs[j]; + if (anchor.MaxDistance < vertex.origin) { continue; } + DataSuturePoint suturePoint = new DataSuturePoint(); + suturePoint.distance = vertex.origin - anchor.origin; + suturePoint.vertex = vertex.a; + suturePoint.aAnchor = anchor.a; + suturePoint.bAnchor = anchor.b; + suturePoints.Add(suturePoint); + } + } + return suturePoints; + } +} diff --git a/Assets/ModuleCore/ModuleAlgorithm/AlgorithmSuture.cs.meta b/Assets/ModuleCore/ModuleAlgorithm/AlgorithmSuture.cs.meta new file mode 100644 index 0000000..dbdf29d --- /dev/null +++ b/Assets/ModuleCore/ModuleAlgorithm/AlgorithmSuture.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bc0a831375a5abe418c790ae74a19376 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ModuleCore/ModuleAlgorithm/AlgorithmSutureSide.cs b/Assets/ModuleCore/ModuleAlgorithm/AlgorithmSutureSide.cs index a085ed4..222d070 100644 --- a/Assets/ModuleCore/ModuleAlgorithm/AlgorithmSutureSide.cs +++ b/Assets/ModuleCore/ModuleAlgorithm/AlgorithmSutureSide.cs @@ -6,62 +6,62 @@ using UnityEngine; /// /// 缝合边算法模块 /// -public class AlgorithmSutureSide : ModuleAlgorithm { - public class VertexPosition : IComparable { - public Vector3 designPosition; - public Vector3 bakingPosition; - public float distance; - public int CompareTo(VertexPosition other) { - return other.distance >= distance ? 1 : -1; - } - } +//public class AlgorithmSutureSide : ModuleAlgorithm { +// public class VertexPosition : IComparable { +// public Vector3 designPosition; +// public Vector3 bakingPosition; +// public float distance; +// public int CompareTo(VertexPosition other) { +// return other.distance >= distance ? 1 : -1; +// } +// } - protected override void Awake() => ModuleCore.AlgorithmSutureSide = this; +// protected override void Awake() => ModuleCore.AlgorithmSutureSide = this; - public override void Compute(DataSutureSide data) { - //List vertexPositions = VertexPositions(data); - data.designPositions = VertexToDesignPositions(data).ToArray(); - data.bakingPositions = VertexToBakingPositions(data).ToArray(); - } +// public override void Compute(DataSutureSide data) { +// //List vertexPositions = VertexPositions(data); +// data.designPositions = VertexToDesignPositions(data).ToArray(); +// data.bakingPositions = VertexToBakingPositions(data).ToArray(); +// } - private List VertexPositions(DataSutureSide sutureSide) { - List vertexPositions = new List(); - for (int i = 0; i < sutureSide.Vertices.Length; i++) { - Vector3 design = sutureSide.Vertices[i].design; - Quaternion quaternion = Quaternion.Euler(sutureSide.PlateBakingEulerAngles); - Vector3 baking = quaternion * sutureSide.Vertices[i].design; - VertexPosition vertexPosition = new VertexPosition(); - vertexPosition.designPosition = design + sutureSide.PlateDesignPosition; - vertexPosition.bakingPosition = baking + sutureSide.PlateBakingPosition; - vertexPosition.distance = Vector3.Distance(design, sutureSide.side.aPoint.position); - vertexPositions.Add(vertexPosition); - } - //按距离从小到大排序 - vertexPositions.Sort(); - //是否颠倒 - if (sutureSide.isReversal) { vertexPositions.Reverse(); } - return vertexPositions; - } - private List VertexToDesignPositions(DataSutureSide data) { - //转换列表 - List positions = new List(); - for (int i = 0; i < data.Vertices.Length; i++) { - Vector3 position = data.Vertices[i].design + data.PlateDesignPosition; - positions.Add(position); - } - if (data.isReversal) { positions.Reverse(); } - return positions; - } - private List VertexToBakingPositions(DataSutureSide data) { - //转换列表 - List positions = new List(); - for (int i = 0; i < data.Vertices.Length; i++) { - Quaternion quaternion = Quaternion.Euler(data.PlateBakingEulerAngles); - Vector3 baking = quaternion * data.Vertices[i].design; - Vector3 position = baking + data.PlateBakingPosition; - positions.Add(position); - } - if (data.isReversal) { positions.Reverse(); } - return positions; - } -} +// private List VertexPositions(DataSutureSide sutureSide) { +// List vertexPositions = new List(); +// for (int i = 0; i < sutureSide.Vertices.Length; i++) { +// Vector3 design = sutureSide.Vertices[i].design; +// Quaternion quaternion = Quaternion.Euler(sutureSide.PlateBakingEulerAngles); +// Vector3 baking = quaternion * sutureSide.Vertices[i].design; +// VertexPosition vertexPosition = new VertexPosition(); +// vertexPosition.designPosition = design + sutureSide.PlateDesignPosition; +// vertexPosition.bakingPosition = baking + sutureSide.PlateBakingPosition; +// vertexPosition.distance = Vector3.Distance(design, sutureSide.side.aPoint.position); +// vertexPositions.Add(vertexPosition); +// } +// //按距离从小到大排序 +// vertexPositions.Sort(); +// //是否颠倒 +// if (sutureSide.isReversal) { vertexPositions.Reverse(); } +// return vertexPositions; +// } +// private List VertexToDesignPositions(DataSutureSide data) { +// //转换列表 +// List positions = new List(); +// for (int i = 0; i < data.Vertices.Length; i++) { +// Vector3 position = data.Vertices[i].design + data.PlateDesignPosition; +// positions.Add(position); +// } +// if (data.isReversal) { positions.Reverse(); } +// return positions; +// } +// private List VertexToBakingPositions(DataSutureSide data) { +// //转换列表 +// List positions = new List(); +// for (int i = 0; i < data.Vertices.Length; i++) { +// Quaternion quaternion = Quaternion.Euler(data.PlateBakingEulerAngles); +// Vector3 baking = quaternion * data.Vertices[i].design; +// Vector3 position = baking + data.PlateBakingPosition; +// positions.Add(position); +// } +// if (data.isReversal) { positions.Reverse(); } +// return positions; +// } +//} diff --git a/Assets/ModuleCore/ModuleAlgorithm/ResetBakingPolygon.cs b/Assets/ModuleCore/ModuleAlgorithm/ResetBakingPolygon.cs new file mode 100644 index 0000000..54767bd --- /dev/null +++ b/Assets/ModuleCore/ModuleAlgorithm/ResetBakingPolygon.cs @@ -0,0 +1,18 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class ResetBakingPolygon : MonoBehaviour +{ + // Start is called before the first frame update + void Start() + { + + } + + // Update is called once per frame + void Update() + { + + } +} diff --git a/Assets/ModuleCore/ModuleAlgorithm/ResetBakingPolygon.cs.meta b/Assets/ModuleCore/ModuleAlgorithm/ResetBakingPolygon.cs.meta new file mode 100644 index 0000000..acb0222 --- /dev/null +++ b/Assets/ModuleCore/ModuleAlgorithm/ResetBakingPolygon.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f24a4f73b9925a9478f58b089059ef1e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ModuleCore/ModuleAssets/AssetsPlate.cs b/Assets/ModuleCore/ModuleAssets/AssetsPlate.cs index 3ffd89b..ef90893 100644 --- a/Assets/ModuleCore/ModuleAssets/AssetsPlate.cs +++ b/Assets/ModuleCore/ModuleAssets/AssetsPlate.cs @@ -17,14 +17,14 @@ public class AssetsPlate : ModuleAssets { protected override void Awake() => ModuleCore.AssetsPlate = this; - public override void Add(DataPlate data) { - if (dataPlates.Contains(data)) { return; } - dataPlates.Add(data); + public override void Add(DataPlate plate) { + if (dataPlates.Contains(plate)) { return; } + dataPlates.Add(plate); //初始化参数 - data.designPosition = ViewCameraDesign.CameraPosition; - data.bakingPosition = ViewCameraDesign.CameraPosition; + plate.dataDesign.position = ViewCameraDesign.CameraPosition; + plate.dataBaking.position = ViewCameraDesign.CameraPosition; //生成可视化内容 - data.UpdateVisual(); + plate.UpdateVisual(); } public override void Remove(DataPlate data) { if (!dataPlates.Contains(data)) { return; } diff --git a/Assets/ModuleCore/ModuleBuilder/BuilderInsertPointToPoint.cs b/Assets/ModuleCore/ModuleBuilder/BuilderInsertPointToPoint.cs index 8b79a62..c5d862e 100644 --- a/Assets/ModuleCore/ModuleBuilder/BuilderInsertPointToPoint.cs +++ b/Assets/ModuleCore/ModuleBuilder/BuilderInsertPointToPoint.cs @@ -5,37 +5,37 @@ using UnityEngine; /// /// 插入点(DataInsertPoint) 转换 点(DataPoint) /// -public class BuilderInsertPointToPoint : ModuleBuilder { +//public class BuilderInsertPointToPoint : ModuleBuilder { - protected override void Awake() => ModuleCore.InsertPointToPoint = this; +// protected override void Awake() => ModuleCore.InsertPointToPoint = this; - public override DataPoint To(DataInsertPoint insertPoint) { - DataPlate plate = insertPoint.plate; - Vector3 position = insertPoint.position; - //创建新的点 - DataPoint point = new DataPoint(insertPoint.plate); - point.position = position; - //改变关联的边B点,重置贝塞尔曲线 - insertPoint.side.bPoint = point; - insertPoint.side.OneRankBezier(); - //创建新的边 - DataSide side = CreateDataSide(plate, point, insertPoint.bPoint); - //插入边 - int sideIndex = plate.sides.IndexOf(insertPoint.side); - plate.sides.Insert(sideIndex + 1, side); - //插入点 - int pointIndex = plate.points.IndexOf(insertPoint.aPoint); - plate.points.Insert(pointIndex + 1, point); - //更新数据 - plate.UpdateVisual(); - return point; - } +// public override DataPoint To(DataInsertPoint insertPoint) { +// DataPlate plate = insertPoint.plate; +// Vector3 position = insertPoint.position; +// //创建新的点 +// DataPoint point = new DataPoint(insertPoint.plate); +// point.position = position; +// //改变关联的边B点,重置贝塞尔曲线 +// insertPoint.side.bPoint = point; +// insertPoint.side.OneRankBezier(); +// //创建新的边 +// DataSide side = CreateDataSide(plate, point, insertPoint.bPoint); +// //插入边 +// int sideIndex = plate.sides.IndexOf(insertPoint.side); +// plate.sides.Insert(sideIndex + 1, side); +// //插入点 +// int pointIndex = plate.points.IndexOf(insertPoint.aPoint); +// plate.points.Insert(pointIndex + 1, point); +// //更新数据 +// plate.UpdateVisual(); +// return point; +// } - private DataSide CreateDataSide(DataPlate plate, DataPoint a, DataPoint b) { - DataSide side = new DataSide(plate); - side.aPoint = a; - side.bPoint = b; - side.OneRankBezier(); - return side; - } -} +// private DataSide CreateDataSide(DataPlate plate, DataPoint a, DataPoint b) { +// DataSide side = new DataSide(plate); +// side.aPoint = a; +// side.bPoint = b; +// side.OneRankBezier(); +// return side; +// } +//} diff --git a/Assets/ModuleCore/ModuleBuilder/BuilderPlatePresetsToPlate.cs b/Assets/ModuleCore/ModuleBuilder/BuilderPlatePresetsToPlate.cs index 7928f3c..b814154 100644 --- a/Assets/ModuleCore/ModuleBuilder/BuilderPlatePresetsToPlate.cs +++ b/Assets/ModuleCore/ModuleBuilder/BuilderPlatePresetsToPlate.cs @@ -11,24 +11,24 @@ public class BuilderPlatePresetsToPlate : ModuleBuilder ToDataPoint(DataPlate dataPlate, List list) { - List points = new List(); + private List ToDataPoint(DataPlate dataPlate, List list) { + List points = new List(); for (int i = 0; i < list.Count; i++) { - DataPoint point = new DataPoint(dataPlate); + DataPlatePoint point = new DataPlatePoint(dataPlate); point.position = list[i]; points.Add(point); } return points; } - private List ToDataSide(DataPlate dataPlate, List list) { - List sides = new List(); + private List ToDataSide(DataPlate dataPlate, List list) { + List sides = new List(); for (int i = 0; i < list.Count; i++) { - DataSide side = new DataSide(dataPlate); + DataPlateSide side = new DataPlateSide(dataPlate); side.aPoint = list.LoopIndex(i + 0); side.bPoint = list.LoopIndex(i + 1); side.OneRankBezier(); diff --git a/Assets/ModuleCore/ModuleCore.cs b/Assets/ModuleCore/ModuleCore.cs index a7b520b..984e710 100644 --- a/Assets/ModuleCore/ModuleCore.cs +++ b/Assets/ModuleCore/ModuleCore.cs @@ -46,37 +46,37 @@ public class ModuleCore : Module { public ModuleBuilder PlatePresetsToPlate; /// 板片数据(DataPlate) 转换 多边形数据(DataPolygon) public ModuleBuilder PlateToPolygon; - /// 插入点(DataInsertPoint) 转换 点(DataPoint) - public ModuleBuilder InsertPointToPoint; #endregion #region 可视模块 - /// 设计可视化内容生成模块 - public ModuleVisual VisualDesign; - /// 烘焙可视化内容生成模块 - public ModuleVisual VisualBaking; - /// 连接可视化内容生成模块 + /// 板片设计 可视化内容生成模块 + public ModuleVisual VisualPlateDesign; + /// 板片烘焙 可视化内容生成模块 + public ModuleVisual VisualPlateBaking; + /// 缝合设计 可视化内容生成模块 + public ModuleVisual VisualSutureDesign; + /// 缝合烘焙 可视化内容生成模块 + public ModuleVisual VisualSutureBaking; + /// 连接器 可视化内容生成模块 public ModuleVisual VisualConnector; #endregion #region 查询模块 /// 查询点模块 - public ModuleFind FindPoint; + public ModuleFind FindPoint; /// 查询边模块 - public ModuleFind FindSide; + public ModuleFind FindSide; /// 查询贝塞尔点模块 public ModuleFind FindBezier; #endregion #region 算法模块 - /// 计算位置到边上最近的点 - public ModuleAlgorithm AlgorithmSidePoint; /// 简单多边形算法模块 public ModuleAlgorithm AlgorithmSimplePolygon; /// 细分多边形算法模块 public ModuleAlgorithm AlgorithmSubdivisionPolygon; /// 缝合边算法模块 - public ModuleAlgorithm AlgorithmSutureSide; + public ModuleAlgorithm AlgorithmSuture; #endregion #region 事件定义 diff --git a/Assets/ModuleCore/ModuleFind/FindBezier.cs b/Assets/ModuleCore/ModuleFind/FindBezier.cs index 12ff0fd..06e1482 100644 --- a/Assets/ModuleCore/ModuleFind/FindBezier.cs +++ b/Assets/ModuleCore/ModuleFind/FindBezier.cs @@ -15,7 +15,7 @@ public class FindBezier : ModuleFind { public override bool Find(Vector3 position, out DataBezier bezier) { List plates = AssetsPlate.Datas; for (int i = 0; i < plates.Count; i++) { - Vector3 localPosition = position - plates[i].designPosition; + Vector3 localPosition = position - plates[i].dataDesign.position; bezier = Find(plates[i], localPosition); if (bezier != null) { return true; } } @@ -24,14 +24,14 @@ public class FindBezier : ModuleFind { /// 查询匹配的边 private DataBezier Find(DataPlate plate, Vector3 localPosition) { - for (int i = 0; i < plate.sides.Count; i++) { - DataBezier bezier = Find(plate.sides[i], localPosition); + for (int i = 0; i < plate.plateSides.Count; i++) { + DataBezier bezier = Find(plate.plateSides[i], localPosition); if (bezier != null) { return bezier; } } return null; } /// 查询匹配的边 - private DataBezier Find(DataSide side, Vector3 localPosition) { + private DataBezier Find(DataPlateSide side, Vector3 localPosition) { if (side.bezier == Bezier.一阶) { return null; } float aDis = Vector3.Distance(side.aBezier, localPosition); if (aDis < FindRange) { return new DataBezier() { isA = true, side = side }; } diff --git a/Assets/ModuleCore/ModuleFind/FindPoint.cs b/Assets/ModuleCore/ModuleFind/FindPoint.cs index d6ea319..f91e78f 100644 --- a/Assets/ModuleCore/ModuleFind/FindPoint.cs +++ b/Assets/ModuleCore/ModuleFind/FindPoint.cs @@ -5,17 +5,17 @@ using UnityEngine; /// /// 查找点 /// -public class FindPoint : ModuleFind { +public class FindPoint : ModuleFind { public readonly float FindRange = 0.01f; /// 板片资产 public ModuleAssets AssetsPlate => ModuleCore.AssetsPlate; protected override void Awake() => ModuleCore.FindPoint = this; - public override bool Find(Vector3 position, out DataPoint point) { + public override bool Find(Vector3 position, out DataPlatePoint point) { List plates = AssetsPlate.Datas; for (int i = 0; i < plates.Count; i++) { - Vector3 localPosition = position - plates[i].designPosition; + Vector3 localPosition = position - plates[i].dataDesign.position; point = Find(plates[i], localPosition); if (point != null) { return true; } } @@ -23,8 +23,8 @@ public class FindPoint : ModuleFind { } /// 查询匹配的点 - private DataPoint Find(DataPlate plate, Vector3 localPosition) { - List points = plate.points; + private DataPlatePoint Find(DataPlate plate, Vector3 localPosition) { + List points = plate.platePoints; for (int i = 0; i < points.Count; i++) { float distance = Vector3.Distance(points[i].position, localPosition); if (distance > FindRange) { continue; } diff --git a/Assets/ModuleCore/ModuleFind/FindSide.cs b/Assets/ModuleCore/ModuleFind/FindSide.cs index 53288ca..8874bb8 100644 --- a/Assets/ModuleCore/ModuleFind/FindSide.cs +++ b/Assets/ModuleCore/ModuleFind/FindSide.cs @@ -5,17 +5,17 @@ using UnityEngine; /// /// 查找边 /// -public class FindSide : ModuleFind { - public readonly float FindRange = 0.01f; +public class FindSide : ModuleFind { + public readonly float FindRange = 0.01f; /// 板片资产 public ModuleAssets AssetsPlate => ModuleCore.AssetsPlate; protected override void Awake() => ModuleCore.FindSide = this; - public override bool Find(Vector3 position, out DataSide side) { + public override bool Find(Vector3 position, out DataPlateSide side) { List plates = AssetsPlate.Datas; for (int i = 0; i < plates.Count; i++) { - Vector3 localPosition = position - plates[i].designPosition; + Vector3 localPosition = position - plates[i].dataDesign.position; side = Find(plates[i], localPosition); if (side != null) { return true; } } @@ -23,20 +23,20 @@ public class FindSide : ModuleFind { } /// 查询匹配的边 - private DataSide Find(DataPlate plate, Vector3 localPosition) { - for (int i = 0; i < plate.sides.Count; i++) { - DataSide side = Find(plate.sides[i], localPosition); + private DataPlateSide Find(DataPlate plate, Vector3 localPosition) { + for (int i = 0; i < plate.plateSides.Count; i++) { + DataPlateSide side = Find(plate.plateSides[i], localPosition); if (side != null) { return side; } } return null; } /// 查询匹配的边 - private DataSide Find(DataSide side, Vector3 localPosition) { - for (int i = 0; i < side.lines.Length; i++) { - Vector3 a = side.lines[i].a; - Vector3 b = side.lines[i].b; + private DataPlateSide Find(DataPlateSide side, Vector3 localPosition) { + DataPlateSideDesign design = side.dataDesign; + for (int i = 0; i < design.lines.Length; i++) { + Vector3 a = design.lines[i].a; + Vector3 b = design.lines[i].b; float distance = ProjectDistance(a, b, localPosition); - //Debug.Log($"{a} , {b} , {localPosition}"); if (distance < FindRange) { return side; } } return null; diff --git a/Assets/ModuleCore/ModuleVisual/VisualBaking.cs b/Assets/ModuleCore/ModuleVisual/VisualBaking.cs index c55faf9..c8bb3d9 100644 --- a/Assets/ModuleCore/ModuleVisual/VisualBaking.cs +++ b/Assets/ModuleCore/ModuleVisual/VisualBaking.cs @@ -2,45 +2,45 @@ using System.Collections; using System.Collections.Generic; using UnityEngine; -public class VisualBaking : ModuleVisual { - public Transform viewSpace; - public Transform platePrefab;//板片 - public Transform suturePrefab;//缝合 - public Transform sutureSidePrefab;//缝合边 +//public class VisualBaking : ModuleVisual { +// public Transform viewSpace; +// public Transform platePrefab;//板片 +// public Transform suturePrefab;//缝合 +// public Transform sutureSidePrefab;//缝合边 - protected override void Awake() => ModuleCore.VisualBaking = this; +// protected override void Awake() => ModuleCore.VisualBaking = this; - public override void UpdateVisual(DataPlate plate) { - //更新板片 - Create(ref plate.baking, platePrefab, viewSpace); - plate.baking.UpdateVisual(plate); - //子数据父对象 - Transform parent = plate.design.transform; - //更新线段 - plate.sides.ForEach(obj => UpdateVisual(obj, parent)); - } - public override void ReleaseVisual(DataPlate data) { - throw new System.NotImplementedException(); - } +// public override void UpdateVisual(DataPlate plate) { +// //更新板片 +// Create(ref plate.baking, platePrefab, viewSpace); +// plate.baking.UpdateVisual(plate); +// //子数据父对象 +// Transform parent = plate.design.transform; +// //更新线段 +// plate.sides.ForEach(obj => UpdateVisual(obj, parent)); +// } +// public override void ReleaseVisual(DataPlate data) { +// throw new System.NotImplementedException(); +// } - private void UpdateVisual(DataSide side, Transform parent) { - //Create(ref side.design, sidePrefab, parent); - //side.design.UpdateVisual(side); - //更新缝合线 - if (side.suture == null) { return; } - //side.suture.Update(); - UpdateVisual(side.suture, viewSpace); - } - /// 更新缝合数据 - private void UpdateVisual(DataSuture suture, Transform parent) { - Create(ref suture.baking, suturePrefab, parent); - UpdateVisual(suture.a, suture.baking.transform); - UpdateVisual(suture.b, suture.baking.transform); - suture.baking.UpdateVisual(suture); - } - /// 更新缝合边 - private void UpdateVisual(DataSutureSide sutureSide, Transform parent) { - Create(ref sutureSide.baking, sutureSidePrefab, parent); - sutureSide.baking.UpdateVisual(sutureSide); - } -} +// private void UpdateVisual(DataSide side, Transform parent) { +// //Create(ref side.design, sidePrefab, parent); +// //side.design.UpdateVisual(side); +// //更新缝合线 +// if (side.suture == null) { return; } +// //side.suture.Update(); +// UpdateVisual(side.suture, viewSpace); +// } +// /// 更新缝合数据 +// private void UpdateVisual(DataSuture suture, Transform parent) { +// Create(ref suture.baking, suturePrefab, parent); +// UpdateVisual(suture.a, suture.baking.transform); +// UpdateVisual(suture.b, suture.baking.transform); +// suture.baking.UpdateVisual(suture); +// } +// /// 更新缝合边 +// private void UpdateVisual(DataSutureSide sutureSide, Transform parent) { +// Create(ref sutureSide.baking, sutureSidePrefab, parent); +// sutureSide.baking.UpdateVisual(sutureSide); +// } +//} diff --git a/Assets/ModuleCore/ModuleVisual/VisualDesign.cs b/Assets/ModuleCore/ModuleVisual/VisualDesign.cs index 9322ff6..925d22e 100644 --- a/Assets/ModuleCore/ModuleVisual/VisualDesign.cs +++ b/Assets/ModuleCore/ModuleVisual/VisualDesign.cs @@ -5,53 +5,53 @@ using UnityEngine; /// /// 版片可视化模块 /// -public class VisualDesign : ModuleVisual { - public Transform viewSpace; - public Transform platePrefab;//板片 - public Transform pointPrefab;//点 - public Transform sidePrefab;//边 - public Transform suturePrefab;//缝合 - public Transform sutureSidePrefab;//缝合边 +//public class VisualDesign : ModuleVisual { +// public Transform viewSpace; +// public Transform platePrefab;//板片 +// public Transform pointPrefab;//点 +// public Transform sidePrefab;//边 +// public Transform suturePrefab;//缝合 +// public Transform sutureSidePrefab;//缝合边 - protected override void Awake() => ModuleCore.VisualDesign = this; +// protected override void Awake() => ModuleCore.VisualDesign = this; - public override void UpdateVisual(DataPlate plate) { - //更新板片 - Create(ref plate.design, platePrefab, viewSpace); - plate.design.UpdateVisual(plate); - //子数据父对象 - Transform parent = plate.design.transform; - //更新点 - plate.points.ForEach(obj => UpdateVisual(obj, parent)); - //更新线段 - plate.sides.ForEach(obj => UpdateVisual(obj, parent)); - } - public override void ReleaseVisual(DataPlate data) { - throw new System.NotImplementedException(); - } +// public override void UpdateVisual(DataPlate plate) { +// //更新板片 +// Create(ref plate.design, platePrefab, viewSpace); +// plate.design.UpdateVisual(plate); +// //子数据父对象 +// Transform parent = plate.design.transform; +// //更新点 +// plate.points.ForEach(obj => UpdateVisual(obj, parent)); +// //更新线段 +// plate.sides.ForEach(obj => UpdateVisual(obj, parent)); +// } +// public override void ReleaseVisual(DataPlate data) { +// throw new System.NotImplementedException(); +// } - private void UpdateVisual(DataPoint point, Transform parent) { - Create(ref point.visual, pointPrefab, parent); - point.visual.UpdateVisual(point); - } - private void UpdateVisual(DataSide side, Transform parent) { - Create(ref side.design, sidePrefab, parent); - side.design.UpdateVisual(side); - //更新缝合线 - if (side.suture == null) { return; } - side.suture.Update(); - UpdateVisual(side.suture, viewSpace); - } - /// 更新缝合数据 - private void UpdateVisual(DataSuture suture, Transform parent) { - Create(ref suture.design, suturePrefab, parent); - UpdateVisual(suture.a, suture.design.transform); - UpdateVisual(suture.b, suture.design.transform); - suture.design.UpdateVisual(suture); - } - /// 更新缝合边 - private void UpdateVisual(DataSutureSide sutureSide, Transform parent) { - Create(ref sutureSide.design, sutureSidePrefab, parent); - sutureSide.design.UpdateVisual(sutureSide); - } -} +// private void UpdateVisual(DataPoint point, Transform parent) { +// Create(ref point.visual, pointPrefab, parent); +// point.visual.UpdateVisual(point); +// } +// private void UpdateVisual(DataSide side, Transform parent) { +// Create(ref side.design, sidePrefab, parent); +// side.design.UpdateVisual(side); +// //更新缝合线 +// if (side.suture == null) { return; } +// side.suture.Update(); +// UpdateVisual(side.suture, viewSpace); +// } +// /// 更新缝合数据 +// private void UpdateVisual(DataSuture suture, Transform parent) { +// Create(ref suture.design, suturePrefab, parent); +// UpdateVisual(suture.a, suture.design.transform); +// UpdateVisual(suture.b, suture.design.transform); +// suture.design.UpdateVisual(suture); +// } +// /// 更新缝合边 +// private void UpdateVisual(DataSutureSide sutureSide, Transform parent) { +// Create(ref sutureSide.design, sutureSidePrefab, parent); +// sutureSide.design.UpdateVisual(sutureSide); +// } +//} diff --git a/Assets/ModuleCore/ModuleVisual/VisualPlateBaking.cs b/Assets/ModuleCore/ModuleVisual/VisualPlateBaking.cs new file mode 100644 index 0000000..41db98c --- /dev/null +++ b/Assets/ModuleCore/ModuleVisual/VisualPlateBaking.cs @@ -0,0 +1,46 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class VisualPlateBaking : ModuleVisual { + public Transform viewSpace; + public Transform platePrefab;//板片 + public Transform suturePrefab;//缝合 + public Transform sutureSidePrefab;//缝合边 + + protected override void Awake() => ModuleCore.VisualPlateBaking = this; + + public override void UpdateVisual(DataPlate plate) { + //更新板片 + Create(ref plate.bakingPrefab, platePrefab, viewSpace); + plate.bakingPrefab.UpdateVisual(plate); + //子数据父对象 + Transform parent = plate.designPrefab.transform; + //更新线段 + plate.plateSides.ForEach(obj => UpdateVisual(obj, parent)); + } + public override void ReleaseVisual(DataPlate data) { + throw new System.NotImplementedException(); + } + + private void UpdateVisual(DataPlateSide side, Transform parent) { + //Create(ref side.design, sidePrefab, parent); + //side.design.UpdateVisual(side); + //更新缝合线 + //if (side.suture == null) { return; } + //side.suture.Update(); + //UpdateVisual(side.suture, viewSpace); + } + /// 更新缝合数据 + private void UpdateVisual(DataSuture suture, Transform parent) { + Create(ref suture.baking, suturePrefab, parent); + UpdateVisual(suture.a, suture.baking.transform); + UpdateVisual(suture.b, suture.baking.transform); + suture.baking.UpdateVisual(suture); + } + /// 更新缝合边 + private void UpdateVisual(DataSutureSide sutureSide, Transform parent) { + Create(ref sutureSide.baking, sutureSidePrefab, parent); + sutureSide.baking.UpdateVisual(sutureSide); + } +} diff --git a/Assets/ModuleCore/ModuleVisual/VisualPlateBaking.cs.meta b/Assets/ModuleCore/ModuleVisual/VisualPlateBaking.cs.meta new file mode 100644 index 0000000..804c964 --- /dev/null +++ b/Assets/ModuleCore/ModuleVisual/VisualPlateBaking.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ef4a839345dfb344382e257d374ca3ed +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ModuleCore/ModuleVisual/VisualPlateDesign.cs b/Assets/ModuleCore/ModuleVisual/VisualPlateDesign.cs new file mode 100644 index 0000000..e9a4740 --- /dev/null +++ b/Assets/ModuleCore/ModuleVisual/VisualPlateDesign.cs @@ -0,0 +1,41 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +/// +/// 版片可视化模块 +/// +public class VisualPlateDesign : ModuleVisual { + public Transform viewSpace; + public Transform platePrefab;//板片 + public Transform pointPrefab;//点 + public Transform sidePrefab;//边 + + protected override void Awake() => ModuleCore.VisualPlateDesign = this; + + public override void UpdateVisual(DataPlate plate) { + //更新板片 + Create(ref plate.designPrefab, platePrefab, viewSpace); + plate.designPrefab.UpdateVisual(plate); + //子数据父对象 + Transform parent = plate.designPrefab.transform; + //更新点 + plate.platePoints.ForEach(obj => UpdateVisual(obj, parent)); + //更新线段 + plate.plateSides.ForEach(obj => UpdateVisual(obj, parent)); + } + public override void ReleaseVisual(DataPlate data) { + throw new System.NotImplementedException(); + } + + private void UpdateVisual(DataPlatePoint point, Transform parent) { + Create(ref point.visual, pointPrefab, parent); + point.visual.UpdateVisual(point); + } + private void UpdateVisual(DataPlateSide side, Transform parent) { + Create(ref side.designPrefab, sidePrefab, parent); + side.designPrefab.UpdateVisual(side); + //更新缝合线 + if (side.suture != null) { side.suture.UpdateVisual(); } + } +} diff --git a/Assets/ModuleCore/ModuleVisual/VisualPlateDesign.cs.meta b/Assets/ModuleCore/ModuleVisual/VisualPlateDesign.cs.meta new file mode 100644 index 0000000..5dcd794 --- /dev/null +++ b/Assets/ModuleCore/ModuleVisual/VisualPlateDesign.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f9827f83f79c2af42b2a06bdc3c80719 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ModuleCore/ModuleVisual/VisualSutureBaking.cs b/Assets/ModuleCore/ModuleVisual/VisualSutureBaking.cs new file mode 100644 index 0000000..63f9153 --- /dev/null +++ b/Assets/ModuleCore/ModuleVisual/VisualSutureBaking.cs @@ -0,0 +1,31 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +/// +/// 缝合烘焙可视化模块 +/// +public class VisualSutureBaking : ModuleVisual { + public Transform viewSpace; + public Transform suturePrefab;//缝合 + public Transform sutureSidePrefab;//缝合边 + + protected override void Awake() => ModuleCore.VisualSutureBaking = this; + + public override void UpdateVisual(DataSuture suture) { + Create(ref suture.baking, suturePrefab, viewSpace); + suture.baking.UpdateVisual(suture); + + UpdateVisual(suture.a, suture.baking.transform); + UpdateVisual(suture.b, suture.baking.transform); + } + public override void ReleaseVisual(DataSuture data) { + throw new System.NotImplementedException(); + } + + /// 更新缝合边 + private void UpdateVisual(DataSutureSide sutureSide, Transform parent) { + Create(ref sutureSide.baking, sutureSidePrefab, parent); + sutureSide.baking.UpdateVisual(sutureSide); + } +} diff --git a/Assets/ModuleCore/ModuleVisual/VisualSutureBaking.cs.meta b/Assets/ModuleCore/ModuleVisual/VisualSutureBaking.cs.meta new file mode 100644 index 0000000..462bb67 --- /dev/null +++ b/Assets/ModuleCore/ModuleVisual/VisualSutureBaking.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 06ff2a0f351be2d41aa7c8dfc23798e0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ModuleCore/ModuleVisual/VisualSutureDesign.cs b/Assets/ModuleCore/ModuleVisual/VisualSutureDesign.cs new file mode 100644 index 0000000..4114827 --- /dev/null +++ b/Assets/ModuleCore/ModuleVisual/VisualSutureDesign.cs @@ -0,0 +1,31 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +/// +/// 缝合设计可视化模块 +/// +public class VisualSutureDesign : ModuleVisual { + public Transform viewSpace; + public Transform suturePrefab;//缝合 + public Transform sutureSidePrefab;//缝合边 + + protected override void Awake() => ModuleCore.VisualSutureDesign = this; + + public override void UpdateVisual(DataSuture suture) { + Create(ref suture.design, suturePrefab, viewSpace); + suture.design.UpdateVisual(suture); + + UpdateVisual(suture.a, suture.design.transform); + UpdateVisual(suture.b, suture.design.transform); + } + public override void ReleaseVisual(DataSuture data) { + throw new System.NotImplementedException(); + } + + /// 更新缝合边 + private void UpdateVisual(DataSutureSide sutureSide, Transform parent) { + Create(ref sutureSide.design, sutureSidePrefab, parent); + sutureSide.design.UpdateVisual(sutureSide); + } +} diff --git a/Assets/ModuleCore/ModuleVisual/VisualSutureDesign.cs.meta b/Assets/ModuleCore/ModuleVisual/VisualSutureDesign.cs.meta new file mode 100644 index 0000000..2cc63d1 --- /dev/null +++ b/Assets/ModuleCore/ModuleVisual/VisualSutureDesign.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a43eabbe6a52df943b5157da8933dd33 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ModuleData/DataBezier.cs b/Assets/ModuleData/DataBezier.cs index 1b2cd40..cae4675 100644 --- a/Assets/ModuleData/DataBezier.cs +++ b/Assets/ModuleData/DataBezier.cs @@ -6,7 +6,7 @@ public class DataBezier { /// 是否是a public bool isA; /// 关联的边 - public DataSide side; + public DataPlateSide side; /// 位置 public Vector3 position => isA ? side.aBezier : side.bBezier; diff --git a/Assets/ModuleData/DataBorder.cs b/Assets/ModuleData/DataBorder.cs index 76c49cb..8298a84 100644 --- a/Assets/ModuleData/DataBorder.cs +++ b/Assets/ModuleData/DataBorder.cs @@ -2,21 +2,34 @@ using System.Collections; using System.Collections.Generic; using UnityEngine; -/// 2D边界数据 +/// 边界数据 public class DataBorder { + /// 网格细分 + public readonly float smooth = 0.01f; + /// minX public readonly float minX = 0; + /// maxX public readonly float maxX = 0; + /// minY public readonly float minY = 0; + /// maxY public readonly float maxY = 0; - /// 2D边界数据 - public DataBorder(float minX, float maxX, float minY, float maxY) { + /// 多边形边缘点 + public readonly Vector3[] points; + /// 边界数据 + public DataBorder(float minX, float maxX, float minY, float maxY, Vector3[] points) { this.minX = minX; this.maxX = maxX; this.minY = minY; this.maxY = maxY; + this.points = points; } /// 边界宽 public float Wide => maxX - minX; /// 边界高 public float High => maxY - minY; + /// 网格宽 + public int GridWide => Mathf.FloorToInt(Wide / smooth) + 1; + /// 网格高 + public int GridHigh => Mathf.FloorToInt(High / smooth) + 1; /// 最小点 public Vector3 MinPoint => new Vector3(minX, minY, 0); /// 最大点 diff --git a/Assets/ModuleData/DataPlate/DataPlate.cs b/Assets/ModuleData/DataPlate/DataPlate.cs index 5a5826d..33aaebf 100644 --- a/Assets/ModuleData/DataPlate/DataPlate.cs +++ b/Assets/ModuleData/DataPlate/DataPlate.cs @@ -7,18 +7,22 @@ public class DataPlate { /// 核心模块 private ModuleCore ModuleCore => ModuleCore.I; /// 设计可视化模块 - private ModuleVisual VisualDesign => ModuleCore.VisualDesign; + private ModuleVisual VisualDesign => ModuleCore.VisualPlateDesign; /// 烘焙可视化模块 - private ModuleVisual VisualBaking => ModuleCore.VisualBaking; + private ModuleVisual VisualBaking => ModuleCore.VisualPlateBaking; /// 简单多边形算法模块 private ModuleAlgorithm AlgorithmSimplePolygon => ModuleCore.AlgorithmSimplePolygon; /// 细分多边形算法模块 private ModuleAlgorithm AlgorithmSubdivisionPolygon => ModuleCore.AlgorithmSubdivisionPolygon; + public DataPlate() { + dataDesign = new DataPlateDesign(this); + } + public void UpdateVisual(bool recalculate = true) { if (recalculate) { //简单多边形计算 - //AlgorithmSimplePolygon.Compute(this); + AlgorithmSimplePolygon.Compute(this); //细分多边形计算 AlgorithmSubdivisionPolygon.Compute(this); } @@ -29,42 +33,55 @@ public class DataPlate { } #region 核心数据 - /// 边缘平滑度 - public float smooth = 0.01f; - /// 板片设计视图的位置(本地坐标系) - public Vector3 designPosition; - /// 板片烘焙视图的位置(本地坐标系) - public Vector3 bakingPosition; - /// 板片烘焙视图的旋转(本地坐标系) - public Vector3 bakingEulerAngles; /// - public List points = new List(); + public List platePoints = new List(); /// - public List sides = new List(); + public List plateSides = new List(); #endregion #region 次要数据 - /// 边界数据 - public DataBorder border; - /// 边缘点 - public List edgePoints; - /// 设计网格 - public Mesh designMesh; - - /// 三角形数据 - public List triangles; - - /// 顶点网格 - public GridTool vertexGrid; + /// 设计缓存数据 + public DataPlateDesign dataDesign; + /// 烘焙缓存数据 + public DataPlateBaking dataBaking = new DataPlateBaking(); #endregion #region 可视化数据 /// 可视化对象 - public ModulePrefab design; + public ModulePrefab designPrefab; /// 可视化对象 - public ModulePrefab baking; + public ModulePrefab bakingPrefab; /// 安排点 public FixedArrange arrange; #endregion +} +/// 设计缓存数据 +public class DataPlateDesign { + /// 板片 + public readonly DataPlate plate; + /// 设计缓存数据 + public DataPlateDesign(DataPlate plate) => this.plate = plate; + + /// 板片的位置 + public Vector3 position; + /// 网格 + public Mesh mesh; + /// 边缘点 + public Vector3[] points; + /// 三角形数据 + public List triangles; +} +/// 烘焙缓存数据 +public class DataPlateBaking { + /// 网格 + public Mesh mesh; + /// 板片的位置 + public Vector3 position; + /// 板片的旋转 + public Vector3 eulerAngles; + /// 边界数据 + public DataBorder border; + /// 全部顶点 + public DataPlateVertex[] vertexs; } \ No newline at end of file diff --git a/Assets/ModuleData/DataPlate/DataPlateLine.cs b/Assets/ModuleData/DataPlate/DataPlateLine.cs new file mode 100644 index 0000000..07b3c71 --- /dev/null +++ b/Assets/ModuleData/DataPlate/DataPlateLine.cs @@ -0,0 +1,17 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +/// 线段 +public class DataPlateLine { + /// 线段起点a + public Vector3 a; + /// 线段终点b + public Vector3 b; + /// 原始距离 + public float origin; + /// 线段距离 + public float Distance => Vector3.Distance(a, b); + /// 线段方向 + public Vector3 Direction => b - a; +} diff --git a/Assets/ModuleData/DataPlate/DataPlateLine.cs.meta b/Assets/ModuleData/DataPlate/DataPlateLine.cs.meta new file mode 100644 index 0000000..7baaa57 --- /dev/null +++ b/Assets/ModuleData/DataPlate/DataPlateLine.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c7e8d3e741e703d49b33431b75a3a001 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ModuleData/DataPlate/DataPlatePoint.cs b/Assets/ModuleData/DataPlate/DataPlatePoint.cs new file mode 100644 index 0000000..4411cc7 --- /dev/null +++ b/Assets/ModuleData/DataPlate/DataPlatePoint.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class DataPlatePoint { + /// 绑定的板片 + public readonly DataPlate plate; + /// 初始化 + public DataPlatePoint(DataPlate plate) => this.plate = plate; + + #region 核心数据 + /// 设计点位置(本地坐标系) + public Vector3 position; + #endregion + + #region 可视化数据 + /// 可视化对象 + public ModulePrefab visual; + #endregion +} diff --git a/Assets/ModuleData/DataPlate/DataPlatePoint.cs.meta b/Assets/ModuleData/DataPlate/DataPlatePoint.cs.meta new file mode 100644 index 0000000..494e3e4 --- /dev/null +++ b/Assets/ModuleData/DataPlate/DataPlatePoint.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6c2af0d32eea37f408900226b81e8e8a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ModuleData/DataPlate/DataPlateSide.cs b/Assets/ModuleData/DataPlate/DataPlateSide.cs new file mode 100644 index 0000000..5e7f689 --- /dev/null +++ b/Assets/ModuleData/DataPlate/DataPlateSide.cs @@ -0,0 +1,62 @@ +using System.Collections; +using System.Collections.Generic; +using Unity.Collections; +using UnityEngine; + +public enum Bezier { + 一阶 = 0, 二阶 = 1, 三阶 = 2 +} +/// +public class DataPlateSide { + /// 绑定的板片 + public readonly DataPlate plate; + /// 初始化 + public DataPlateSide(DataPlate plate) => this.plate = plate; + + #region 核心数据 + /// 贝塞尔曲线阶数 + public Bezier bezier; + /// 起点 + public DataPlatePoint aPoint; + /// 终点 + public DataPlatePoint bPoint; + /// 贝塞尔曲线前(-) + public Vector3 aBezier; + /// 贝塞尔曲线后(+) + public Vector3 bBezier; + #endregion + + #region 次要数据 + /// 缝合数据 + public DataSuture suture; + /// 设计缓存数据 + public DataPlateSideDesign dataDesign = new DataPlateSideDesign(); + /// 烘焙缓存数据 + public DataPlateSideBaking dataBaking = new DataPlateSideBaking(); + #endregion + + #region 可视化内容 + /// 可视化边缘线 + public ModulePrefab designPrefab; + #endregion +} +/// 设计缓存数据 +public class DataPlateSideDesign { + /// 总长度 + public float length; + /// + public Vector3[] positions = new Vector3[0]; + /// 线 + public DataPlateLine[] lines = new DataPlateLine[0]; +} +/// 烘焙缓存数据 +public class DataPlateSideBaking { + /// 总长度 + public float length; + /// + public Vector3[] positions = new Vector3[0]; + /// 线 + public DataPlateLine[] lines = new DataPlateLine[0]; + /// 关联的网格顶点 + public DataPlateVertex[] vertexs = new DataPlateVertex[0]; +} \ No newline at end of file diff --git a/Assets/ModuleData/DataPlate/DataPlateSide.cs.meta b/Assets/ModuleData/DataPlate/DataPlateSide.cs.meta new file mode 100644 index 0000000..5b0bc68 --- /dev/null +++ b/Assets/ModuleData/DataPlate/DataPlateSide.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d0a57f0098d07ca4da0ca6e08c25662c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ModuleData/DataPlate/DataPlateVertex.cs b/Assets/ModuleData/DataPlate/DataPlateVertex.cs new file mode 100644 index 0000000..5dd55e3 --- /dev/null +++ b/Assets/ModuleData/DataPlate/DataPlateVertex.cs @@ -0,0 +1,28 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class DataPlateVertex { + /// 是否是有效顶点 + public bool isValid; + /// 设计视图中位置 + public Vector3 position; + + /// + public DataPlateVertex above; + /// + public DataPlateVertex below; + /// + public DataPlateVertex left; + /// + public DataPlateVertex right; + + /// 左上 + public DataPlateVertex leftAbove; + /// 左下 + public DataPlateVertex leftBelow; + /// 右上 + public DataPlateVertex rightAbove; + /// 右下 + public DataPlateVertex rightBelow; +} diff --git a/Assets/ModuleData/DataPlate/DataPlateVertex.cs.meta b/Assets/ModuleData/DataPlate/DataPlateVertex.cs.meta new file mode 100644 index 0000000..5a6ab0b --- /dev/null +++ b/Assets/ModuleData/DataPlate/DataPlateVertex.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9842037a7f0169b4bb8a4b70047f7739 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ModuleData/DataPlate/DataSide.cs b/Assets/ModuleData/DataPlate/DataSide.cs index 71540cb..b1cbfaf 100644 --- a/Assets/ModuleData/DataPlate/DataSide.cs +++ b/Assets/ModuleData/DataPlate/DataSide.cs @@ -2,9 +2,9 @@ using System.Collections; using System.Collections.Generic; using UnityEngine; -public enum Bezier { - 一阶 = 0, 二阶 = 1, 三阶 = 2 -} +//public enum Bezier { +// 一阶 = 0, 二阶 = 1, 三阶 = 2 +//} public class DataSide { /// 绑定的板片 public readonly DataPlate plate; diff --git a/Assets/ModuleData/DataSuture/DataSuture.cs b/Assets/ModuleData/DataSuture/DataSuture.cs index fbbcbaa..53442fd 100644 --- a/Assets/ModuleData/DataSuture/DataSuture.cs +++ b/Assets/ModuleData/DataSuture/DataSuture.cs @@ -5,24 +5,33 @@ using UnityEngine; public class DataSuture { /// 核心模块 private ModuleCore ModuleCore => ModuleCore.I; - /// 简单多边形算法模块 - private ModuleAlgorithm AlgorithmSutureSide => ModuleCore.AlgorithmSutureSide; + /// 设计可视化模块 + private ModuleVisual VisualDesign => ModuleCore.VisualSutureDesign; + /// 烘焙可视化模块 + private ModuleVisual VisualBaking => ModuleCore.VisualSutureBaking; + /// 缝合线算法模块 + private ModuleAlgorithm AlgorithmSuture => ModuleCore.AlgorithmSuture; public readonly DataSutureSide a; public readonly DataSutureSide b; - public DataSuture(DataSide aSide, DataSide bSide) { + public DataSuture(DataPlateSide aSide, DataPlateSide bSide) { a = new DataSutureSide(aSide, this); b = new DataSutureSide(bSide, this); - Update(); + UpdateVisual(); } - public void Update() { - AlgorithmSutureSide.Compute(a); - AlgorithmSutureSide.Compute(b); + public void UpdateVisual() { + AlgorithmSuture.Compute(this); + VisualDesign.UpdateVisual(this); + VisualBaking.UpdateVisual(this); } + #region 次要数据 /// 缝合长度 - public float length => this.SutureLength(); + public float length; + /// 缝合点 + public List points; + #endregion #region 可视化内容 /// 可视化内容 diff --git a/Assets/ModuleData/DataSuture/DataSuturePoint.cs b/Assets/ModuleData/DataSuture/DataSuturePoint.cs new file mode 100644 index 0000000..6378f69 --- /dev/null +++ b/Assets/ModuleData/DataSuture/DataSuturePoint.cs @@ -0,0 +1,14 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class DataSuturePoint { + /// aAnchor到vertex的距离 + public float distance; + /// 绑定的顶点 + public DataPlateVertex vertex; + /// 锚点a + public DataPlateVertex aAnchor; + /// 锚点b + public DataPlateVertex bAnchor; +} diff --git a/Assets/ModuleData/DataSuture/DataSuturePoint.cs.meta b/Assets/ModuleData/DataSuture/DataSuturePoint.cs.meta new file mode 100644 index 0000000..a36a95c --- /dev/null +++ b/Assets/ModuleData/DataSuture/DataSuturePoint.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fab08a6f4689d1c4b94d2fd7f05fedbe +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ModuleData/DataSuture/DataSutureSide.cs b/Assets/ModuleData/DataSuture/DataSutureSide.cs index a125b12..a139263 100644 --- a/Assets/ModuleData/DataSuture/DataSutureSide.cs +++ b/Assets/ModuleData/DataSuture/DataSutureSide.cs @@ -7,12 +7,12 @@ using UnityEngine; /// public class DataSutureSide { /// 关联的边 - public readonly DataSide side; + public readonly DataPlateSide plateSide; /// 关联的缝合数据 public readonly DataSuture suture; /// 缝合边 - public DataSutureSide(DataSide side, DataSuture suture) { - this.side = side; + public DataSutureSide(DataPlateSide side, DataSuture suture) { + this.plateSide = side; this.suture = suture; } @@ -22,32 +22,10 @@ public class DataSutureSide { #endregion #region 次要数据 - - /// 边最大长度 - public float MaxLength => side.length; - /// 边缘顶点数据 - public DataVertex[] Vertices => side.vertices; - /// 设计视图板片位置 - public Vector3 PlateDesignPosition => side.plate.designPosition; - /// 烘焙视图板片位置 - public Vector3 PlateBakingPosition => side.plate.bakingPosition; - /// 烘焙视图板片位置 - public Vector3 PlateBakingEulerAngles => side.plate.bakingEulerAngles; - - /// 设计视图顶点位置 - public Vector3[] designPositions; - /// 设计视图A点位置 - public Vector3 DesignPosintA => designPositions[0]; - /// 设计视图B点位置 - public Vector3 DesignPosintB => designPositions[designPositions.Length - 1]; - - /// 烘焙视图顶点位置 - public Vector3[] bakingPositions; - /// 烘焙视图A点位置 - public Vector3 BakingPosintA => bakingPositions[0]; - /// 烘焙视图B点位置 - public Vector3 BakingPosintB => bakingPositions[bakingPositions.Length - 1]; - + /// 设计缓存数据 + public DataSutureSideDesign dataDesign = new DataSutureSideDesign(); + /// 烘焙缓存数据 + public DataSutureSideBaking dataBaking = new DataSutureSideBaking(); #endregion #region 可视化数据 @@ -57,3 +35,43 @@ public class DataSutureSide { public ModulePrefab baking; #endregion } +/// 设计缓存数据 +public class DataSutureSideDesign { + /// 位置列表 + public Vector3[] positions; + /// A点位置 + public Vector3 PointA => positions[0]; + /// B点位置 + public Vector3 PointB => positions[positions.Length - 1]; +} +/// 烘焙缓存数据 +public class DataSutureSideBaking { + /// 位置列表 + public Vector3[] positions; + /// 全部顶点列表 + public DataSutureSideVertex[] allVertexs; + /// 关联的顶点列表 + public DataSutureSideVertex[] vertexs; + /// A点位置 + public Vector3 PointA => positions[0]; + /// B点位置 + public Vector3 PointB => positions[positions.Length - 1]; +} +public class DataSutureSideVertex { + /// 边起点到a点的距离 + public float origin; + /// a点 + public DataPlateVertex a; + /// a点的下一个点 + public DataPlateVertex b; + /// 缝合边顶点 + public DataSutureSideVertex(float origin, DataPlateVertex a, DataPlateVertex b) { + this.origin = origin; + this.a = a; + this.b = b; + } + /// 最大距离 origin + a - b + public float MaxDistance => origin + Distance; + /// 分段距离 a-b + public float Distance => Vector3.Distance(a.position, b.position); +} \ No newline at end of file diff --git a/Assets/ModuleData/DataTriangle.cs b/Assets/ModuleData/DataTriangle.cs index 253399f..59d0d42 100644 --- a/Assets/ModuleData/DataTriangle.cs +++ b/Assets/ModuleData/DataTriangle.cs @@ -6,6 +6,7 @@ public struct DataTriangle { public Vector3 a; public Vector3 b; public Vector3 c; + public override string ToString() { return $"{a} , {b} , {c}"; } diff --git a/Assets/ModulePrefab/PrefabPlateBaking.cs b/Assets/ModulePrefab/PrefabPlateBaking.cs index 8af07ec..479d2ca 100644 --- a/Assets/ModulePrefab/PrefabPlateBaking.cs +++ b/Assets/ModulePrefab/PrefabPlateBaking.cs @@ -12,10 +12,10 @@ public class PrefabPlateBaking : ModulePrefab { public override void UpdateVisual(DataPlate plate) { this.plate = plate; - transform.localPosition = plate.bakingPosition; - transform.localEulerAngles = plate.bakingEulerAngles; - - meshFilter.mesh = plate.designMesh; - meshCollider.sharedMesh = plate.designMesh; + DataPlateBaking baking = plate.dataBaking; + //transform.localPosition = baking.position; + //transform.localEulerAngles = baking.eulerAngles; + meshFilter.mesh = baking.mesh; + meshCollider.sharedMesh = baking.mesh; } } diff --git a/Assets/ModulePrefab/PrefabPlateDesign.cs b/Assets/ModulePrefab/PrefabPlateDesign.cs index ea2c6d7..be15782 100644 --- a/Assets/ModulePrefab/PrefabPlateDesign.cs +++ b/Assets/ModulePrefab/PrefabPlateDesign.cs @@ -12,9 +12,10 @@ public class PrefabPlateDesign : ModulePrefab { public override void UpdateVisual(DataPlate plate) { this.plate = plate; - transform.localPosition = plate.designPosition; - meshFilter.mesh = plate.designMesh; - meshCollider.sharedMesh = plate.designMesh; + DataPlateDesign design = plate.dataDesign; + transform.localPosition = design.position; + meshFilter.mesh = design.mesh; + meshCollider.sharedMesh = design.mesh; } } diff --git a/Assets/ModulePrefab/PrefabPoint.cs b/Assets/ModulePrefab/PrefabPoint.cs index cb59be3..91df555 100644 --- a/Assets/ModulePrefab/PrefabPoint.cs +++ b/Assets/ModulePrefab/PrefabPoint.cs @@ -2,12 +2,12 @@ using System.Collections; using System.Collections.Generic; using UnityEngine; -public class PrefabPoint : ModulePrefab { - private DataPoint point; +public class PrefabPoint : ModulePrefab { + private DataPlatePoint point; - public override DataPoint Value => point; + public override DataPlatePoint Value => point; - public override void UpdateVisual(DataPoint point) { + public override void UpdateVisual(DataPlatePoint point) { this.point = point; transform.localPosition = point.position; } diff --git a/Assets/ModulePrefab/PrefabSide.cs b/Assets/ModulePrefab/PrefabSide.cs index f92a4c7..dbcec12 100644 --- a/Assets/ModulePrefab/PrefabSide.cs +++ b/Assets/ModulePrefab/PrefabSide.cs @@ -3,20 +3,20 @@ using System.Collections; using System.Collections.Generic; using UnityEngine; -public class PrefabSide : ModulePrefab { +public class PrefabSide : ModulePrefab { public Transform aPoint; public Transform bPoint; public LineRenderer lineRenderer; public LineRenderer aBezier; public LineRenderer bBezier; - private DataSide side; + private DataPlateSide side; #region 引用模块 /// 设计UI输入模块 public ModuleUIInput UIInputDesign => ModuleCore.I.UIInputDesign; #endregion - public override DataSide Value => side; + public override DataPlateSide Value => side; private void Awake() { UIInputDesign.OnChangeInput += UIInputDesign_OnChangeInput; @@ -34,11 +34,12 @@ public class PrefabSide : ModulePrefab { aBezier.gameObject.SetActive(false); bBezier.gameObject.SetActive(false); } - public override void UpdateVisual(DataSide side) { + public override void UpdateVisual(DataPlateSide side) { this.side = side; - lineRenderer.positionCount = side.positions.Length; - lineRenderer.SetPositions(side.positions); + DataPlateSideDesign design = side.dataDesign; + lineRenderer.positionCount = design.positions.Length; + lineRenderer.SetPositions(design.positions); Type type = UIInputDesign.Current.GetType(); if (type != typeof(DesignBezier)) { ActiveGameObject(false); return; } diff --git a/Assets/ModulePrefab/PrefabSutureBaking.cs b/Assets/ModulePrefab/PrefabSutureBaking.cs index e67b2a5..b027967 100644 --- a/Assets/ModulePrefab/PrefabSutureBaking.cs +++ b/Assets/ModulePrefab/PrefabSutureBaking.cs @@ -14,10 +14,12 @@ public class PrefabSutureBaking : ModulePrefab { public override void UpdateVisual(DataSuture suture) { this.suture = suture; - aLineRenderer.SetPosition(0, suture.a.BakingPosintA); - aLineRenderer.SetPosition(1, suture.b.BakingPosintA); + DataSutureSideBaking aBaking = suture.a.dataBaking; + DataSutureSideBaking bBaking = suture.b.dataBaking; + aLineRenderer.SetPosition(0, aBaking.PointA); + aLineRenderer.SetPosition(1, bBaking.PointA); - bLineRenderer.SetPosition(0, suture.a.BakingPosintB); - bLineRenderer.SetPosition(1, suture.b.BakingPosintB); + bLineRenderer.SetPosition(0, aBaking.PointB); + bLineRenderer.SetPosition(1, bBaking.PointB); } } diff --git a/Assets/ModulePrefab/PrefabSutureDesign.cs b/Assets/ModulePrefab/PrefabSutureDesign.cs index a4c1e5b..132af21 100644 --- a/Assets/ModulePrefab/PrefabSutureDesign.cs +++ b/Assets/ModulePrefab/PrefabSutureDesign.cs @@ -14,10 +14,12 @@ public class PrefabSutureDesign : ModulePrefab { public override void UpdateVisual(DataSuture suture) { this.suture = suture; - aLineRenderer.SetPosition(0, suture.a.DesignPosintA); - aLineRenderer.SetPosition(1, suture.b.DesignPosintA); + DataSutureSideDesign aDesign = suture.a.dataDesign; + DataSutureSideDesign bDesign = suture.b.dataDesign; + aLineRenderer.SetPosition(0, aDesign.PointA); + aLineRenderer.SetPosition(1, bDesign.PointA); - bLineRenderer.SetPosition(0, suture.a.DesignPosintB); - bLineRenderer.SetPosition(1, suture.b.DesignPosintB); + bLineRenderer.SetPosition(0, aDesign.PointB); + bLineRenderer.SetPosition(1, bDesign.PointB); } } diff --git a/Assets/ModulePrefab/PrefabSutureSideBaking.cs b/Assets/ModulePrefab/PrefabSutureSideBaking.cs index e056dec..8504900 100644 --- a/Assets/ModulePrefab/PrefabSutureSideBaking.cs +++ b/Assets/ModulePrefab/PrefabSutureSideBaking.cs @@ -12,7 +12,8 @@ public class PrefabSutureSideBaking : ModulePrefab { public override void UpdateVisual(DataSutureSide sutureSide) { this.sutureSide = sutureSide; - lineRenderer.positionCount = sutureSide.bakingPositions.Length; - lineRenderer.SetPositions(sutureSide.bakingPositions); + DataSutureSideBaking baking = sutureSide.dataBaking; + lineRenderer.positionCount = baking.positions.Length; + lineRenderer.SetPositions(baking.positions); } } diff --git a/Assets/ModulePrefab/PrefabSutureSideDesign.cs b/Assets/ModulePrefab/PrefabSutureSideDesign.cs index 0ee3bb3..ae5f52f 100644 --- a/Assets/ModulePrefab/PrefabSutureSideDesign.cs +++ b/Assets/ModulePrefab/PrefabSutureSideDesign.cs @@ -12,7 +12,8 @@ public class PrefabSutureSideDesign : ModulePrefab { public override void UpdateVisual(DataSutureSide sutureSide) { this.sutureSide = sutureSide; - lineRenderer.positionCount = sutureSide.designPositions.Length; - lineRenderer.SetPositions(sutureSide.designPositions); + DataSutureSideDesign design = sutureSide.dataDesign; + lineRenderer.positionCount = design.positions.Length; + lineRenderer.SetPositions(design.positions); } } diff --git a/Assets/ModuleTools/DataSideTool.cs b/Assets/ModuleTools/DataSideTool.cs index a64e91b..897a4aa 100644 --- a/Assets/ModuleTools/DataSideTool.cs +++ b/Assets/ModuleTools/DataSideTool.cs @@ -3,30 +3,30 @@ using System.Collections.Generic; using UnityEngine; public static class DataSideTool { - public static void SetBezierPositionA(this DataSide side, Vector3 position) { + public static void SetBezierPositionA(this DataPlateSide side, Vector3 position) { if (side.bezier == Bezier.一阶) { return; } if (side.bezier == Bezier.二阶) { side.bBezier = position; } side.aBezier = position; } - public static void SetBezierPositionB(this DataSide side, Vector3 position) { + public static void SetBezierPositionB(this DataPlateSide side, Vector3 position) { if (side.bezier == Bezier.一阶) { return; } if (side.bezier == Bezier.二阶) { side.aBezier = position; } side.bBezier = position; } - public static void OneRankBezier(this DataSide side) { + public static void OneRankBezier(this DataPlateSide side) { side.bezier = Bezier.一阶; } - public static void TwoRankBezier(this DataSide side) { + public static void TwoRankBezier(this DataPlateSide side) { side.bezier = Bezier.二阶; - DataPoint a = side.aPoint; - DataPoint b = side.bPoint; + DataPlatePoint a = side.aPoint; + DataPlatePoint b = side.bPoint; side.aBezier = a.position + (b.position - a.position) * 0.5f; side.bBezier = a.position + (b.position - a.position) * 0.5f; } - public static void ThreeRankBezier(this DataSide side) { + public static void ThreeRankBezier(this DataPlateSide side) { side.bezier = Bezier.三阶; - DataPoint a = side.aPoint; - DataPoint b = side.bPoint; + DataPlatePoint a = side.aPoint; + DataPlatePoint b = side.bPoint; side.aBezier = a.position + (b.position - a.position) * 0.3f; side.bBezier = a.position + (b.position - a.position) * 0.7f; } diff --git a/Assets/ModuleTools/DataSutureTool.cs b/Assets/ModuleTools/DataSutureTool.cs index 0e0e34b..874573c 100644 --- a/Assets/ModuleTools/DataSutureTool.cs +++ b/Assets/ModuleTools/DataSutureTool.cs @@ -3,10 +3,10 @@ using System.Collections.Generic; using UnityEngine; public static class DataSutureTool { - public static float SutureLength(this DataSuture suture) { - if (suture.a.MaxLength < suture.b.MaxLength) { - return suture.a.MaxLength; - } - else { return suture.b.MaxLength; } - } + //public static float SutureLength(this DataSuture suture) { + // if (suture.a.MaxLength < suture.b.MaxLength) { + // return suture.a.MaxLength; + // } + // else { return suture.b.MaxLength; } + //} } diff --git a/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmBakingVertex.cs b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmBakingVertex.cs new file mode 100644 index 0000000..3812020 --- /dev/null +++ b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmBakingVertex.cs @@ -0,0 +1,151 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +/// +/// 烘焙顶点计算 +/// +public class UnitAlgorithmBakingVertex : UnitAlgorithm { + + /// 烘焙顶点计算 + public UnitAlgorithmBakingVertex() { } + + public void Compute(DataPlateBaking plateBaking) { + DataBorder border = plateBaking.border; + Vector3[] points = border.points; + + //计算内部顶点 + //plateBaking.grid = new GridTool(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 plateSides = plateBaking.plate.plateSides; + //边缘所有的线段 + //for (int i = 0; i < plateSides.Count; i++) { + //Compute(plateSides[i], border.GridWide, border.GridHigh, border, border.smooth, plateBaking.grid); + //} + } + /// 向网格和边缘写入顶点数据 + private void Compute(DataPlateSide side, int wide, int high, DataBorder border, float smooth, GridTool grid) { + DataPlateLine[] lines = side.dataBaking.lines; + List sideVertices = new List(); + //计算水平线段顶点 + 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 vertices = new List(); + for (int i = 0; i < sideVertices.Count; i++) { + vertices.Add(sideVertices[i].vertex); + } + //side.vertices = vertices.ToArray(); + } + /// 向网格写入边缘顶点数据 + private DataPlateVertex Compute(Vector3 a, Vector3 b, DataPlateLine line, float smooth, DataBorder border, GridTool 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 { + public float distance; + public DataPlateVertex vertex; + + public int CompareTo(SideVertex other) { + return other.distance >= distance ? 1 : -1; + } + } + + /// 转角法查询位置是否在板片内 + 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; + } + /// + /// 计算AB与CD两条线段的交点. + /// + /// A点 + /// B点 + /// C点 + /// D点 + /// AB与CD的交点 + /// 是否相交 true:相交 false:未相交 + 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; + } +} diff --git a/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmBakingVertex.cs.meta b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmBakingVertex.cs.meta new file mode 100644 index 0000000..41bfdc9 --- /dev/null +++ b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmBakingVertex.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e8b300a54238da848b5628cef749aeb2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmBezier.cs b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmBezier.cs index aea12bd..3721ceb 100644 --- a/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmBezier.cs +++ b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmBezier.cs @@ -11,6 +11,32 @@ public class UnitAlgorithmBezier : UnitAlgorithm { /// 贝塞尔算法 public UnitAlgorithmBezier() { } + public void Compute(DataPlate data) { + List points = new List(); + 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 { //输出 public float length; public List positions = new List(); - public List lines = new List(); - } - - public void Compute(DataPlate data) { - List points = new List(); - for (int i = 0; i < data.sides.Count; i++) { - Compute(data.sides[i]); - points.AddRange(data.sides[i].positions); + public List lines = new List(); + /// 计算曲线细分点 + public void Compute() { + //细分点 + if (bezier == Bezier.一阶) { positions = new List { aPoint, bPoint }; } + if (bezier == Bezier.二阶) { positions = Compute(aPoint, aBezier, bPoint); } + if (bezier == Bezier.三阶) { positions = Compute(aPoint, aBezier, bBezier, bPoint); } + //线段 + lines = new List(); + 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(); - } - - /// 计算曲线细分点 - private void Compute(DataBezier data) { - //细分点 - if (data.bezier == Bezier.一阶) { - data.positions = Compute(data.aPoint, data.bPoint); + /// 二阶贝塞尔线段 + private List Compute(Vector3 a, Vector3 b, Vector3 c) { + List points = new List(); + //方向,距离 + 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); + /// 三阶贝塞尔线段 + private List Compute(Vector3 a, Vector3 b, Vector3 c, Vector3 d) { + List points = new List(); + //方向,距离 + 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(); - 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; - } - } - /// 二阶贝塞尔线段 - private List Compute(Vector3 aPoint, Vector3 bPoint) { - return new List { aPoint, bPoint }; - } - /// 二阶贝塞尔线段 - private List Compute(Vector3 a, Vector3 b, Vector3 c, float smooth) { - List points = new List(); - //方向,距离 - 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; - } - /// 三阶贝塞尔线段 - private List Compute(Vector3 a, Vector3 b, Vector3 c, Vector3 d, float smooth) { - List points = new List(); - //方向,距离 - 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; } /// 商数 diff --git a/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmBorder.cs b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmBorder.cs index 79561f8..07b56a0 100644 --- a/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmBorder.cs +++ b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmBorder.cs @@ -1,28 +1,35 @@ using System.Collections; using System.Collections.Generic; +using System.Linq; using UnityEngine; /// /// 散点边界算法 /// -public class UnitAlgorithmBorder : UnitAlgorithm { +public class UnitAlgorithmBorder : UnitAlgorithm { /// 散点边界算法 public UnitAlgorithmBorder() { } - public void Compute(DataPlate plate) { - List edgePoints = new List(plate.edgePoints); - plate.border = Border(edgePoints); + public void Compute(DataPlateBaking plateBaking) { + //List plateSides = plateBaking.plate.plateSides; + + //List points = new List(); + //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 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); } } diff --git a/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmEarCutting.cs b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmEarCutting.cs index c4addb6..d3516fc 100644 --- a/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmEarCutting.cs +++ b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmEarCutting.cs @@ -6,7 +6,7 @@ using UnityEngine; /// /// 多边形耳切法 /// -public class UnitAlgorithmEarCutting : UnitAlgorithm { +public class UnitAlgorithmEarCutting : UnitAlgorithm { /// 多边形耳切法 public UnitAlgorithmEarCutting() { } @@ -17,27 +17,27 @@ public class UnitAlgorithmEarCutting : UnitAlgorithm { public Vector3 cPoint;//+1 } - public void Compute(DataPlate data) { - List points = new List(data.edgePoints); + public void Compute(DataPlateDesign plateDesign) { + List points = new List(plateDesign.points); //判断散列点排序方向 - Vector3[] allArray = points.ToArray(); - bool isClockWise = IsClockWise(allArray); + Vector3[] allPoints = plateDesign.points; + bool isClockWise = IsClockWise(allPoints); //耳切法生成三角形 List triangles = new List(); - ComputeAuriculare(triangles, points, allArray, isClockWise); - data.triangles = triangles; + ComputeAuriculare(triangles, points, allPoints, isClockWise); + plateDesign.triangles = triangles; } #region 函数 /// 循环计算有效的耳点 - public static void ComputeAuriculare(List triangles, List edgePoints, Vector3[] allArray, bool isClockWise) { - List temp = ComputeAuriculare(edgePoints, allArray, isClockWise); + public static void ComputeAuriculare(List triangles, List edgePoints, Vector3[] allPoints, bool isClockWise) { + List temp = ComputeAuriculare(edgePoints, allPoints, isClockWise); if (temp.Count == 0) { return; } triangles.AddRange(temp); - ComputeAuriculare(triangles, edgePoints, allArray, isClockWise); + ComputeAuriculare(triangles, edgePoints, allPoints, isClockWise); } /// 计算一个有效的耳点 - public static List ComputeAuriculare(List edgePoints, Vector3[] allArray, bool isClockWise) { + public static List ComputeAuriculare(List edgePoints, Vector3[] allPoints, bool isClockWise) { Vector3[] array = edgePoints.ToArray(); List polygons = new List(); for (int i = 0; i < array.Length; i++) { @@ -45,7 +45,7 @@ public class UnitAlgorithmEarCutting : UnitAlgorithm { // 等于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); diff --git a/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmEdgePoint.cs b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmEdgePoint.cs index 74691e6..44d3862 100644 --- a/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmEdgePoint.cs +++ b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmEdgePoint.cs @@ -35,7 +35,7 @@ public class UnitAlgorithmEdgePoint : UnitAlgorithm { #region 函数 /// 二阶贝塞尔线段 - public List CreateLine(DataPoint aPoint, DataPoint bPoint, Vector3 b, float smooth) { + public List CreateLine(DataPlatePoint aPoint, DataPlatePoint bPoint, Vector3 b, float smooth) { List points = new List(); //方向,距离 Vector2 direction = (bPoint.position - aPoint.position).normalized; @@ -53,7 +53,7 @@ public class UnitAlgorithmEdgePoint : UnitAlgorithm { return points; } /// 三阶贝塞尔线段 - public List CreateLine(DataPoint aPoint, DataPoint bPoint, float smooth) { + public List CreateLine(DataPlatePoint aPoint, DataPlatePoint bPoint, float smooth) { List points = new List(); //方向,距离 Vector2 direction = (bPoint.position - aPoint.position).normalized; diff --git a/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmJobsSideSubdivision.cs b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmJobsSideSubdivision.cs new file mode 100644 index 0000000..bef47bc --- /dev/null +++ b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmJobsSideSubdivision.cs @@ -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; + +/// +/// 贝塞尔算法 边缘细分 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; + } +} diff --git a/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmJobsSideSubdivision.cs.meta b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmJobsSideSubdivision.cs.meta new file mode 100644 index 0000000..a41d505 --- /dev/null +++ b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmJobsSideSubdivision.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 39a35ef3408d163469eb7c66d1df96ac +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmMergeTriangle.cs b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmMergeTriangle.cs index db010ea..910f6e0 100644 --- a/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmMergeTriangle.cs +++ b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmMergeTriangle.cs @@ -10,12 +10,12 @@ using UnityEngine; /// /// 三角形合并网格 /// -public class UnitAlgorithmMergeTriangle : UnitAlgorithm { +public class UnitAlgorithmMergeTriangle : UnitAlgorithm, UnitAlgorithm { /// 三角形合并网格 public UnitAlgorithmMergeTriangle() { } - public void Compute(DataPlate data) { - List polygons = data.triangles; + public void Compute(DataPlateDesign plateDesign) { + List polygons = plateDesign.triangles; //三角形合并 List vertices = vertices = MergeVertices(polygons); List triangles = JobFindTriangleIndex(polygons, vertices); @@ -23,12 +23,28 @@ public class UnitAlgorithmMergeTriangle : UnitAlgorithm { List uv = new List(); 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 polygons = plateBaking.triangles; + ////三角形合并 + //List vertices = vertices = MergeVertices(polygons); + //List triangles = JobFindTriangleIndex(polygons, vertices); + ////展开uv (顶点去掉z坐标就是未缩放的平面UV) + //List uv = new List(); + //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(); } /// 合并顶点 private List MergeVertices(List polygons) { @@ -54,7 +70,7 @@ public class UnitAlgorithmMergeTriangle : UnitAlgorithm { 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 triangles = new List(); diff --git a/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmRhombus.cs b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmRhombus.cs index 749b99f..a031c79 100644 --- a/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmRhombus.cs +++ b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmRhombus.cs @@ -5,55 +5,58 @@ using UnityEngine; /// /// 菱形绘制三角形算法 /// -public class UnitAlgorithmRhombus : UnitAlgorithm { +public class UnitAlgorithmRhombus : UnitAlgorithm { - public void Compute(DataPlate data) { + public void Compute(DataPlateBaking plateBaking) { List triangles = new List(); - data.vertexGrid.Loop((x, y) => { - DataVertex vertex = data.vertexGrid.Get(x, y); - if (!vertex.isValid) { return; } + List vertexs = new List(); + //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(); } /// 校验性获取网格上的点 - private void TryGet(GridTool grid, int x, int y, ref DataVertex vertex) { + private void TryGet(GridTool 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; } } /// 创建三角形 - 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; } } diff --git a/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmSutureBaking.cs b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmSutureBaking.cs new file mode 100644 index 0000000..9b18839 --- /dev/null +++ b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmSutureBaking.cs @@ -0,0 +1,64 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +/// +/// 烘焙的缝合线 +/// +public class UnitAlgorithmSutureBaking : UnitAlgorithm { + /// 烘焙的缝合线 + public UnitAlgorithmSutureBaking() { } + + public void Compute(DataSutureSide sutureSide) { + AllVertexs(sutureSide); + //缝合范围内的顶点 + SetVertex(sutureSide); + //顶点转换位置 + SetPositions(sutureSide); + } + /// 顶点距离数据 + private List GetVertex(DataPlateVertex[] vertexsArray, bool isReversal) { + float length = 0; + List vertexs = new List(); + List sideVertexs = new List(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; + } + /// 全部顶点 + private void AllVertexs(DataSutureSide sutureSide) { + DataPlateVertex[] vertexsArray = sutureSide.plateSide.dataBaking.vertexs; + List allVertexs = GetVertex(vertexsArray, false); + sutureSide.dataBaking.allVertexs = allVertexs.ToArray(); + } + /// 缝合范围内的顶点 + private void SetVertex(DataSutureSide sutureSide) { + //全部顶点 + List allVertexs = GetVertex(sutureSide.plateSide.dataBaking.vertexs, sutureSide.isReversal); + //缝合范围内的顶点 + float maxLength = sutureSide.suture.length; + List vertexs = new List(); + for (int i = 0; i < allVertexs.Count; i++) { + if (allVertexs[i].origin <= maxLength) { vertexs.Add(allVertexs[i]); } + } + sutureSide.dataBaking.vertexs = vertexs.ToArray(); + } + /// 顶点转换位置 + private void SetPositions(DataSutureSide sutureSide) { + Vector3 platePosition = sutureSide.plateSide.plate.dataBaking.position; + Vector3 plateEulerAngles = sutureSide.plateSide.plate.dataBaking.eulerAngles; + List positions = new List(); + 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(); + } +} + diff --git a/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmSutureBaking.cs.meta b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmSutureBaking.cs.meta new file mode 100644 index 0000000..4ef1daa --- /dev/null +++ b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmSutureBaking.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9735cc247f76e0b42b50f8b7956d3c8a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmSutureDesign.cs b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmSutureDesign.cs new file mode 100644 index 0000000..7900e38 --- /dev/null +++ b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmSutureDesign.cs @@ -0,0 +1,52 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +/// +/// 设计的缝合线 +/// +public class UnitAlgorithmSutureDesign : UnitAlgorithm { + /// 设计的缝合线 + 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 sidePositions = new List(sutureSide.plateSide.dataDesign.positions); + + float length = 0; + List lines = new List(); + 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 positions = new List(); + 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(); + } +} diff --git a/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmSutureDesign.cs.meta b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmSutureDesign.cs.meta new file mode 100644 index 0000000..d25174c --- /dev/null +++ b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmSutureDesign.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b98adb17aebd36b4ab5dfe90020fb902 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmVertex.cs b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmVertex.cs index 60d09ca..f5bf92b 100644 --- a/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmVertex.cs +++ b/Assets/ModuleUnit/UnitAlgorithm/UnitAlgorithmVertex.cs @@ -6,97 +6,95 @@ using UnityEngine; /// /// 顶点算法 /// -public class UnitAlgorithmVertex : UnitAlgorithm { +public class UnitAlgorithmVertex : UnitAlgorithm { public class SideVertex : IComparable { 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 edgePoints = new List(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(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(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 plateSides = plateBaking.plate.plateSides; + //for (int i = 0; i < plateSides.Count; i++) { + // SubdivideSideVertex(plateBaking, plateSides[i]); + //} } - /// 向网格和边缘写入顶点数据 - private void Compute(DataSide side, int wide, int high, DataBorder border, float smooth, GridTool grid) { - DataLine[] lines = side.lines; - List sideVertices = new List(); + 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 sideVertexs = new List(); + 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 vertices = new List(); - 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 vertexs = new List(); + 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(); - } - /// 向网格写入边缘顶点数据 - private DataVertex Compute(Vector3 a, Vector3 b, DataLine line, float smooth, DataBorder border, GridTool 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(); } /// 转角法查询位置是否在板片内 - public static bool FindPlateInside(List 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); diff --git a/Assets/ModuleUnit/UnitFind.meta b/Assets/ModuleUnit/UnitFind.meta new file mode 100644 index 0000000..83d32ee --- /dev/null +++ b/Assets/ModuleUnit/UnitFind.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3105cf897e8dcb6408a9d5b207fa348e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ModuleUnit/UnitFind/FindSideIntersectPoint.cs b/Assets/ModuleUnit/UnitFind/FindSideIntersectPoint.cs new file mode 100644 index 0000000..2802840 --- /dev/null +++ b/Assets/ModuleUnit/UnitFind/FindSideIntersectPoint.cs @@ -0,0 +1,74 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +/// +/// 查询边交点 +/// +public class FindSideIntersectPoint : UnitFind { + public readonly float FindRange = 0.01f; + /// 板片资产 + public ModuleAssets AssetsPlate => ModuleCore.I.AssetsPlate; + + /// 查询边交点 + public FindSideIntersectPoint() { } + + public bool Find(Vector3 position, out SideIntersectPoint sip) { + sip = new SideIntersectPoint(); + List plates = AssetsPlate.Datas; + for (int i = 0; i < plates.Count; i++) { + Vector3 localPosition = position - plates[i].dataDesign.position; + sip.side = Find(plates[i], localPosition, out sip.intersectPoint); + sip.intersectPoint += plates[i].dataDesign.position; + if (sip.side != null) { return true; } + } + return false; + } + /// 查询匹配的边 + private DataPlateSide Find(DataPlate plate, Vector3 localPosition, out Vector3 intersectPoint) { + intersectPoint = Vector3.zero; + for (int i = 0; i < plate.plateSides.Count; i++) { + DataPlateSide side = Find(plate.plateSides[i], localPosition, out intersectPoint); + if (side != null) { return side; } + } + return null; + } + /// 查询匹配的边 + private DataPlateSide Find(DataPlateSide side, Vector3 localPosition, out Vector3 intersectPoint) { + intersectPoint = Vector3.zero; + for (int i = 0; i < side.dataDesign.lines.Length; i++) { + Vector3 a = side.dataDesign.lines[i].a; + Vector3 b = side.dataDesign.lines[i].b; + float distance = ProjectDistance(a, b, localPosition, out intersectPoint); + if (distance < FindRange) { return side; } + } + return null; + } + + /// + /// 向量投影法 + /// 计算点c到线段ab最近的点 + /// + /// + /// + /// + /// 如果不在线段上返回 float.MaxValue + public static float ProjectDistance(Vector3 a, Vector3 b, Vector3 c, out Vector3 intersectPoint) { + Vector3 ab = b - a; + Vector3 ac = c - a; + Vector3 p = Vector3.Project(ac, ab); + intersectPoint = p + a; + if (ab.normalized != p.normalized) { return float.MaxValue; } + if (ab.magnitude < p.magnitude) { return float.MaxValue; } + return Vector3.Distance(c, p + a); + } +} +/// +/// 边交点 +/// +public class SideIntersectPoint { + /// 匹配的边 + public DataPlateSide side; + /// 交点 + public Vector3 intersectPoint; +} \ No newline at end of file diff --git a/Assets/ModuleUnit/UnitFind/FindSideIntersectPoint.cs.meta b/Assets/ModuleUnit/UnitFind/FindSideIntersectPoint.cs.meta new file mode 100644 index 0000000..f0852bf --- /dev/null +++ b/Assets/ModuleUnit/UnitFind/FindSideIntersectPoint.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 368e1bf20f25d424f8ed16d00323b8b8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ModuleUnit/UnitFind/UnitFind.cs b/Assets/ModuleUnit/UnitFind/UnitFind.cs new file mode 100644 index 0000000..f0eea95 --- /dev/null +++ b/Assets/ModuleUnit/UnitFind/UnitFind.cs @@ -0,0 +1,8 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public interface UnitFind { + /// 查询 + public bool Find(Vector3 position, out Data data); +} diff --git a/Assets/ModuleUnit/UnitFind/UnitFind.cs.meta b/Assets/ModuleUnit/UnitFind/UnitFind.cs.meta new file mode 100644 index 0000000..b08f85f --- /dev/null +++ b/Assets/ModuleUnit/UnitFind/UnitFind.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 77073523d35e8fb4bb758404278690c5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ModuleUnit/UnitMouseInput/BakingMobilePlate.cs b/Assets/ModuleUnit/UnitMouseInput/BakingMobilePlate.cs index 3b50997..a4d911a 100644 --- a/Assets/ModuleUnit/UnitMouseInput/BakingMobilePlate.cs +++ b/Assets/ModuleUnit/UnitMouseInput/BakingMobilePlate.cs @@ -17,15 +17,15 @@ public class BakingMobilePlate : UnitMouseInput { if (!ViewCamera.ScreenToWorldObject(data.ScreenPosition, out platePrefab)) { return; } mousePosition = data.ScreenPosition; originalPosition = platePrefab.transform.localPosition; - platePrefab.Value.bakingPosition = originalPosition; + platePrefab.Value.dataBaking.position = originalPosition; ModuleCore.BakingMobilePlate(platePrefab.Value); } public override void MouseDrag(DataMouseInput data) { if (platePrefab == null) { return; } if (ViewCamera.ScreenToWorldObjectParent(data.ScreenPosition, out arrange, Arrange)) { platePrefab.Value.arrange = arrange; - platePrefab.Value.bakingPosition = arrange.transform.localPosition; - platePrefab.Value.bakingEulerAngles = arrange.transform.localEulerAngles; + platePrefab.Value.dataBaking.position = arrange.transform.localPosition; + platePrefab.Value.dataBaking.eulerAngles = arrange.transform.localEulerAngles; } else { Mobile(data.WorldPosition); } platePrefab.Value.UpdateVisual(false); @@ -41,6 +41,6 @@ public class BakingMobilePlate : UnitMouseInput { Vector3 offset = current - original; Vector3 up = ViewCamera.Up * offset.y; Vector3 right = ViewCamera.Right * offset.x; - platePrefab.Value.bakingPosition = originalPosition - up - right; + platePrefab.Value.dataBaking.position = originalPosition - up - right; } } diff --git a/Assets/ModuleUnit/UnitMouseInput/DesignBezier.cs b/Assets/ModuleUnit/UnitMouseInput/DesignBezier.cs index 30e6a4d..c4a2027 100644 --- a/Assets/ModuleUnit/UnitMouseInput/DesignBezier.cs +++ b/Assets/ModuleUnit/UnitMouseInput/DesignBezier.cs @@ -6,10 +6,10 @@ public class DesignBezier : UnitMouseInput { /// 设计视图相机模块 public ModuleViewCamera ViewCamera => ModuleCore.ViewCameraDesign; /// 查询点算法模块 - public ModuleFind FindSide => ModuleCore.FindSide; + public ModuleFind FindSide => ModuleCore.FindSide; public override void MouseDown(DataMouseInput data) { - if (!FindSide.Find(data.WorldPosition, out DataSide side)) { return; } + if (!FindSide.Find(data.WorldPosition, out DataPlateSide side)) { return; } if (side.bezier == Bezier.一阶) { side.TwoRankBezier(); side.plate.UpdateVisual(); return; } if (side.bezier == Bezier.二阶) { side.ThreeRankBezier(); side.plate.UpdateVisual(); return; } if (side.bezier == Bezier.三阶) { side.OneRankBezier(); side.plate.UpdateVisual(); return; } diff --git a/Assets/ModuleUnit/UnitMouseInput/DesignInsert.cs b/Assets/ModuleUnit/UnitMouseInput/DesignInsert.cs index f3e1912..d580bdc 100644 --- a/Assets/ModuleUnit/UnitMouseInput/DesignInsert.cs +++ b/Assets/ModuleUnit/UnitMouseInput/DesignInsert.cs @@ -3,28 +3,33 @@ using System.Collections.Generic; using UnityEngine; public class DesignInsert : UnitMouseInput { - /// 板片资产 - public ModuleAssets AssetsPlate => ModuleCore.AssetsPlate; - /// 查询边算法模块 - public ModuleFind FindSide => ModuleCore.FindSide; - /// 计算位置到边上最近的点 - public ModuleAlgorithm AlgorithmSidePoint => ModuleCore.AlgorithmSidePoint; - /// 插入点数据转换板片上的点 - public ModuleBuilder InsertPointToPoint => ModuleCore.InsertPointToPoint; + /// 查询边交点 + public UnitFind find = new FindSideIntersectPoint(); public override void MouseDown(DataMouseInput data) { - if (!FindSide.Find(data.WorldPosition, out DataSide side)) { return; } + if (!find.Find(data.WorldPosition, out SideIntersectPoint sip)) { return; } + Insert(sip.side, sip.side.plate, sip.side.aPoint, sip.side.bPoint, sip.intersectPoint); + } - DataIntersect intersect = new DataIntersect(side, data.WorldPosition); - AlgorithmSidePoint.Compute(intersect); - if (!intersect.isIntersect) { return; } - - DataInsertPoint insertPoint = new DataInsertPoint(); - insertPoint.position = intersect.intersectPoint - side.plate.designPosition; - insertPoint.plate = side.plate; - insertPoint.aPoint = side.aPoint; - insertPoint.bPoint = side.bPoint; - insertPoint.side = side; - InsertPointToPoint.To(insertPoint); + private void Insert(DataPlateSide side, DataPlate plate, DataPlatePoint aPoint, DataPlatePoint bPoint, Vector3 position) { + //创建新的点 + DataPlatePoint newPoint = new DataPlatePoint(plate); + newPoint.position = position - plate.dataDesign.position; + //改变关联的边B点,重置贝塞尔曲线 + side.bPoint = newPoint; + side.OneRankBezier(); + //创建新的边 + DataPlateSide newSide = new DataPlateSide(plate); + newSide.aPoint = newPoint; + newSide.bPoint = bPoint; + newSide.OneRankBezier(); + //插入边 + int sideIndex = plate.plateSides.IndexOf(side); + plate.plateSides.Insert(sideIndex + 1, newSide); + //插入点 + int pointIndex = plate.platePoints.IndexOf(aPoint); + plate.platePoints.Insert(pointIndex + 1, newPoint); + //更新数据 + plate.UpdateVisual(); } } diff --git a/Assets/ModuleUnit/UnitMouseInput/DesignMobile.cs b/Assets/ModuleUnit/UnitMouseInput/DesignMobile.cs index 242dc15..c1055a2 100644 --- a/Assets/ModuleUnit/UnitMouseInput/DesignMobile.cs +++ b/Assets/ModuleUnit/UnitMouseInput/DesignMobile.cs @@ -11,7 +11,7 @@ public class DesignMobile : UnitMouseInput { private DataBezier bezier; private Vector3 mousePosition; private Vector3 originalPosition; - private ModulePrefab prefabPoint; + private ModulePrefab prefabPoint; private ModulePrefab prefabPlate; public override void MouseDown(DataMouseInput data) { @@ -61,10 +61,10 @@ public class DesignMobile : UnitMouseInput { //板片 private void RecordPlate(Vector3 screenPosition) { mousePosition = screenPosition; - originalPosition = prefabPlate.Value.designPosition; + originalPosition = prefabPlate.Value.dataDesign.position; } private void MobilePlate(Vector3 offset) { - prefabPlate.Value.designPosition = originalPosition + offset; + prefabPlate.Value.dataDesign.position = originalPosition + offset; prefabPlate.Value.UpdateVisual(false); } //相机 diff --git a/Assets/ModuleUnit/UnitMouseInput/DesignSuture.cs b/Assets/ModuleUnit/UnitMouseInput/DesignSuture.cs index 1f3d778..a3eac79 100644 --- a/Assets/ModuleUnit/UnitMouseInput/DesignSuture.cs +++ b/Assets/ModuleUnit/UnitMouseInput/DesignSuture.cs @@ -3,29 +3,30 @@ using System.Collections.Generic; using UnityEngine; public class DesignSuture : UnitMouseInput { - /// 设计视图相机模块 - public ModuleViewCamera ViewCamera => ModuleCore.ViewCameraDesign; - /// 查询点算法模块 - public ModuleFind FindSide => ModuleCore.FindSide; - /// 计算位置到边上最近的点 - public ModuleAlgorithm AlgorithmSidePoint => ModuleCore.AlgorithmSidePoint; + /// 查询边交点 + public UnitFind find = new FindSideIntersectPoint(); /// 连接可视化内容生成模块 public ModuleVisual VisualConnector => ModuleCore.VisualConnector; - private DataSide aSide; - private DataSide bSide; + private DataPlateSide aSide; + private DataPlateSide bSide; private DataConnector connector; public override void MouseDown(DataMouseInput data) { - if (!FindSide.Find(data.WorldPosition, out aSide)) { return; } - if (!Intersect(aSide, data.WorldPosition, out Vector3 intersectPoint)) { return; } connector = new DataConnector(); - connector.aPoint = intersectPoint; - connector.bPoint = intersectPoint; + connector.aPoint = data.WorldPosition; + if (!find.Find(data.WorldPosition, out SideIntersectPoint sip)) { return; } + connector.aPoint = sip.intersectPoint; + aSide = sip.side; } public override void MouseDrag(DataMouseInput data) { - if (aSide == null) { return; } - connector.bPoint = GetPosition(data); + if (connector == null) { return; } + connector.bPoint = data.WorldPosition; + if (find.Find(data.WorldPosition, out SideIntersectPoint sip)) { + connector.bPoint = sip.intersectPoint; + bSide = sip.side; + } + else { connector.bPoint = data.WorldPosition; } VisualConnector.UpdateVisual(connector); } public override void MouseRelease(DataMouseInput data) { @@ -41,16 +42,16 @@ public class DesignSuture : UnitMouseInput { aSide.plate.UpdateVisual(); } - private Vector3 GetPosition(DataMouseInput data) { - if (!FindSide.Find(data.WorldPosition, out bSide)) { return data.WorldPosition; } - if (aSide == bSide) { return data.WorldPosition; } - if (Intersect(bSide, data.WorldPosition, out Vector3 intersectPoint)) { return intersectPoint; } - else { return data.WorldPosition; } - } - private bool Intersect(DataSide side, Vector3 position, out Vector3 intersectPoint) { - DataIntersect intersect = new DataIntersect(side, position); - AlgorithmSidePoint.Compute(intersect); - intersectPoint = intersect.intersectPoint; - return intersect.isIntersect; - } + //private Vector3 GetPosition(DataMouseInput data) { + // if (!FindSide.Find(data.WorldPosition, out bSide)) { return data.WorldPosition; } + // if (aSide == bSide) { return data.WorldPosition; } + // if (Intersect(bSide, data.WorldPosition, out Vector3 intersectPoint)) { return intersectPoint; } + // else { return data.WorldPosition; } + //} + //private bool Intersect(DataSide side, Vector3 position, out Vector3 intersectPoint) { + //DataIntersect intersect = new DataIntersect(side, position); + //AlgorithmSidePoint.Compute(intersect); + //intersectPoint = intersect.intersectPoint; + //return intersect.isIntersect; + //} } diff --git a/Assets/ModuleUnit/UnitMouseInput/DesignSutureReversal.cs b/Assets/ModuleUnit/UnitMouseInput/DesignSutureReversal.cs index 6d3b762..d095227 100644 --- a/Assets/ModuleUnit/UnitMouseInput/DesignSutureReversal.cs +++ b/Assets/ModuleUnit/UnitMouseInput/DesignSutureReversal.cs @@ -6,14 +6,14 @@ public class DesignSutureReversal : UnitMouseInput { /// 设计视图相机模块 public ModuleViewCamera ViewCamera => ModuleCore.ViewCameraDesign; /// 查询点算法模块 - public ModuleFind FindSide => ModuleCore.FindSide; + public ModuleFind FindSide => ModuleCore.FindSide; public override void MouseDown(DataMouseInput data) { - if (!FindSide.Find(data.WorldPosition, out DataSide side)) { return; } - if (side.suture.a.side == side) { + if (!FindSide.Find(data.WorldPosition, out DataPlateSide side)) { return; } + if (side.suture.a.plateSide == side) { side.suture.a.isReversal = !side.suture.a.isReversal; } - if (side.suture.b.side == side) { + if (side.suture.b.plateSide == side) { side.suture.b.isReversal = !side.suture.b.isReversal; } side.plate.UpdateVisual(); diff --git a/Packages/manifest.json b/Packages/manifest.json index 2f0858a..9684e00 100644 --- a/Packages/manifest.json +++ b/Packages/manifest.json @@ -3,6 +3,7 @@ "com.muhua.tools": "https://github.com/MuHua-123/MuHua-Tools.git?path=Packages/Tools", "com.muhua.uicontrol": "https://github.com/MuHua-123/MuHua-UIControl.git?path=Packages/UIControl", "com.unity.collab-proxy": "2.5.2", + "com.unity.collections": "1.2.4", "com.unity.feature.development": "1.0.1", "com.unity.render-pipelines.universal": "14.0.11", "com.unity.textmeshpro": "3.0.6", diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index 0447914..9cbeed0 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -30,6 +30,16 @@ "dependencies": {}, "url": "https://packages.unity.cn" }, + "com.unity.collections": { + "version": "1.2.4", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.burst": "1.6.6", + "com.unity.test-framework": "1.1.31" + }, + "url": "https://packages.unity.cn" + }, "com.unity.editorcoroutines": { "version": "1.0.0", "depth": 1, diff --git a/ProjectSettings/ShaderGraphSettings.asset b/ProjectSettings/ShaderGraphSettings.asset new file mode 100644 index 0000000..9b43acd --- /dev/null +++ b/ProjectSettings/ShaderGraphSettings.asset @@ -0,0 +1,17 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &1 +MonoBehaviour: + m_ObjectHideFlags: 53 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: de02f9e1d18f588468e474319d09a723, type: 3} + m_Name: + m_EditorClassIdentifier: + shaderVariantLimit: 128 + customInterpolatorErrorThreshold: 32 + customInterpolatorWarningThreshold: 16