This commit is contained in:
MuHua-123
2024-11-29 18:10:02 +08:00
parent 84243e75a8
commit 698464b9d7
81 changed files with 3073 additions and 671 deletions
@@ -5,41 +5,41 @@ using UnityEngine;
/// <summary> /// <summary>
/// 计算位置到边上最近的点 /// 计算位置到边上最近的点
/// </summary> /// </summary>
public class AlgorithmSidePoint : ModuleAlgorithm<DataIntersect> { //public class AlgorithmSidePoint : ModuleAlgorithm<DataIntersect> {
protected override void Awake() => ModuleCore.AlgorithmSidePoint = this; // protected override void Awake() => ModuleCore.AlgorithmSidePoint = this;
public override void Compute(DataIntersect data) { // public override void Compute(DataIntersect data) {
Vector3 position = data.position - data.side.plate.designPosition; // Vector3 position = data.position - data.side.plate.designPosition;
for (int i = 0; i < data.side.lines.Length; i++) { // for (int i = 0; i < data.side.lines.Length; i++) {
DataLine line = data.side.lines[i]; // DataLine line = data.side.lines[i];
if (!Compute(line, position, out Vector3 intersectPoint)) { continue; } // if (!Compute(line, position, out Vector3 intersectPoint)) { continue; }
data.isIntersect = true; // data.isIntersect = true;
data.intersectPoint = intersectPoint + data.side.plate.designPosition; // data.intersectPoint = intersectPoint + data.side.plate.designPosition;
return; // return;
} // }
} // }
/// <summary> 查询匹配的边 </summary> // /// <summary> 查询匹配的边 </summary>
private bool Compute(DataLine line, Vector3 position, out Vector3 intersectPoint) { // private bool Compute(DataLine line, Vector3 position, out Vector3 intersectPoint) {
return ProjectDistance(line.a, line.b, position, out intersectPoint); // return ProjectDistance(line.a, line.b, position, out intersectPoint);
} // }
/// <summary> // /// <summary>
/// 向量投影法 // /// 向量投影法
/// 计算点c到线段ab最近的点 // /// 计算点c到线段ab最近的点
/// </summary> // /// </summary>
/// <param name="a"></param> // /// <param name="a"></param>
/// <param name="b"></param> // /// <param name="b"></param>
/// <param name="c"></param> // /// <param name="c"></param>
/// <returns>如果不在线段上返回 false</returns> // /// <returns>如果不在线段上返回 false</returns>
public static bool ProjectDistance(Vector3 a, Vector3 b, Vector3 c, out Vector3 intersectPoint) { // public static bool ProjectDistance(Vector3 a, Vector3 b, Vector3 c, out Vector3 intersectPoint) {
Vector3 ab = b - a; // Vector3 ab = b - a;
Vector3 ac = c - a; // Vector3 ac = c - a;
Vector3 p = Vector3.Project(ac, ab.normalized); // Vector3 p = Vector3.Project(ac, ab.normalized);
intersectPoint = p + a; // intersectPoint = p + a;
if (ab.normalized != p.normalized) { return false; } // if (ab.normalized != p.normalized) { return false; }
if (ab.magnitude < p.magnitude) { return false; } // if (ab.magnitude < p.magnitude) { return false; }
return true; // return true;
} // }
} //}
@@ -6,18 +6,18 @@ using UnityEngine;
/// 散列点生成简单多边形算法 /// 散列点生成简单多边形算法
/// </summary> /// </summary>
public class AlgorithmSimplePolygon : ModuleAlgorithm<DataPlate> { public class AlgorithmSimplePolygon : ModuleAlgorithm<DataPlate> {
private UnitAlgorithm<DataPlate> AlgorithmSideSubdivision = new UnitAlgorithmBezier(); private UnitAlgorithm<DataPlateDesign> AlgorithmSideSubdivision = new UnitAlgorithmJobsSideSubdivision();
private UnitAlgorithm<DataPlate> AlgorithmTriangle = new UnitAlgorithmEarCutting(); private UnitAlgorithm<DataPlateDesign> AlgorithmTriangle = new UnitAlgorithmEarCutting();
private UnitAlgorithm<DataPlate> AlgorithmMergeTriangle = new UnitAlgorithmMergeTriangle(); private UnitAlgorithm<DataPlateDesign> AlgorithmMergeTriangle = new UnitAlgorithmMergeTriangle();
protected override void Awake() => ModuleCore.AlgorithmSimplePolygon = this; protected override void Awake() => ModuleCore.AlgorithmSimplePolygon = this;
public override void Compute(DataPlate data) { public override void Compute(DataPlate plate) {
//遍历计算边(DataSide)上的细分点(positions)和线(lines) //遍历计算边(DataSide)上的细分点(positions)和线(lines)
AlgorithmSideSubdivision.Compute(data); AlgorithmSideSubdivision.Compute(plate.dataDesign);
//计算三角面 //计算三角面
AlgorithmTriangle.Compute(data); AlgorithmTriangle.Compute(plate.dataDesign);
//三角面列表转换网格 //三角面列表转换网格
AlgorithmMergeTriangle.Compute(data); AlgorithmMergeTriangle.Compute(plate.dataDesign);
} }
} }
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,53 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
/// <summary>
/// 缝合边算法模块
/// </summary>
public class AlgorithmSuture : ModuleAlgorithm<DataSuture> {
/// <summary> 设计的缝合线 </summary>
public UnitAlgorithm<DataSutureSide> SutureDesign = new UnitAlgorithmSutureDesign();
/// <summary> 烘焙的缝合线 </summary>
public UnitAlgorithm<DataSutureSide> 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<DataSuturePoint>();
suture.points.AddRange(Compute(suture.a, suture.b));
suture.points.AddRange(Compute(suture.b, suture.a));
}
private List<DataSuturePoint> Compute(DataSutureSide a, DataSutureSide b) {
DataSutureSideVertex[] vertexs = a.dataBaking.vertexs;
DataSutureSideVertex[] allVertexs = b.dataBaking.allVertexs;
List<DataSuturePoint> suturePoints = new List<DataSuturePoint>();
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;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bc0a831375a5abe418c790ae74a19376
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -6,62 +6,62 @@ using UnityEngine;
/// <summary> /// <summary>
/// 缝合边算法模块 /// 缝合边算法模块
/// </summary> /// </summary>
public class AlgorithmSutureSide : ModuleAlgorithm<DataSutureSide> { //public class AlgorithmSutureSide : ModuleAlgorithm<DataSutureSide> {
public class VertexPosition : IComparable<VertexPosition> { // public class VertexPosition : IComparable<VertexPosition> {
public Vector3 designPosition; // public Vector3 designPosition;
public Vector3 bakingPosition; // public Vector3 bakingPosition;
public float distance; // public float distance;
public int CompareTo(VertexPosition other) { // public int CompareTo(VertexPosition other) {
return other.distance >= distance ? 1 : -1; // 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) { // public override void Compute(DataSutureSide data) {
//List<VertexPosition> vertexPositions = VertexPositions(data); // //List<VertexPosition> vertexPositions = VertexPositions(data);
data.designPositions = VertexToDesignPositions(data).ToArray(); // data.designPositions = VertexToDesignPositions(data).ToArray();
data.bakingPositions = VertexToBakingPositions(data).ToArray(); // data.bakingPositions = VertexToBakingPositions(data).ToArray();
} // }
private List<VertexPosition> VertexPositions(DataSutureSide sutureSide) { // private List<VertexPosition> VertexPositions(DataSutureSide sutureSide) {
List<VertexPosition> vertexPositions = new List<VertexPosition>(); // List<VertexPosition> vertexPositions = new List<VertexPosition>();
for (int i = 0; i < sutureSide.Vertices.Length; i++) { // for (int i = 0; i < sutureSide.Vertices.Length; i++) {
Vector3 design = sutureSide.Vertices[i].design; // Vector3 design = sutureSide.Vertices[i].design;
Quaternion quaternion = Quaternion.Euler(sutureSide.PlateBakingEulerAngles); // Quaternion quaternion = Quaternion.Euler(sutureSide.PlateBakingEulerAngles);
Vector3 baking = quaternion * sutureSide.Vertices[i].design; // Vector3 baking = quaternion * sutureSide.Vertices[i].design;
VertexPosition vertexPosition = new VertexPosition(); // VertexPosition vertexPosition = new VertexPosition();
vertexPosition.designPosition = design + sutureSide.PlateDesignPosition; // vertexPosition.designPosition = design + sutureSide.PlateDesignPosition;
vertexPosition.bakingPosition = baking + sutureSide.PlateBakingPosition; // vertexPosition.bakingPosition = baking + sutureSide.PlateBakingPosition;
vertexPosition.distance = Vector3.Distance(design, sutureSide.side.aPoint.position); // vertexPosition.distance = Vector3.Distance(design, sutureSide.side.aPoint.position);
vertexPositions.Add(vertexPosition); // vertexPositions.Add(vertexPosition);
} // }
//按距离从小到大排序 // //按距离从小到大排序
vertexPositions.Sort(); // vertexPositions.Sort();
//是否颠倒 // //是否颠倒
if (sutureSide.isReversal) { vertexPositions.Reverse(); } // if (sutureSide.isReversal) { vertexPositions.Reverse(); }
return vertexPositions; // return vertexPositions;
} // }
private List<Vector3> VertexToDesignPositions(DataSutureSide data) { // private List<Vector3> VertexToDesignPositions(DataSutureSide data) {
//转换列表 // //转换列表
List<Vector3> positions = new List<Vector3>(); // List<Vector3> positions = new List<Vector3>();
for (int i = 0; i < data.Vertices.Length; i++) { // for (int i = 0; i < data.Vertices.Length; i++) {
Vector3 position = data.Vertices[i].design + data.PlateDesignPosition; // Vector3 position = data.Vertices[i].design + data.PlateDesignPosition;
positions.Add(position); // positions.Add(position);
} // }
if (data.isReversal) { positions.Reverse(); } // if (data.isReversal) { positions.Reverse(); }
return positions; // return positions;
} // }
private List<Vector3> VertexToBakingPositions(DataSutureSide data) { // private List<Vector3> VertexToBakingPositions(DataSutureSide data) {
//转换列表 // //转换列表
List<Vector3> positions = new List<Vector3>(); // List<Vector3> positions = new List<Vector3>();
for (int i = 0; i < data.Vertices.Length; i++) { // for (int i = 0; i < data.Vertices.Length; i++) {
Quaternion quaternion = Quaternion.Euler(data.PlateBakingEulerAngles); // Quaternion quaternion = Quaternion.Euler(data.PlateBakingEulerAngles);
Vector3 baking = quaternion * data.Vertices[i].design; // Vector3 baking = quaternion * data.Vertices[i].design;
Vector3 position = baking + data.PlateBakingPosition; // Vector3 position = baking + data.PlateBakingPosition;
positions.Add(position); // positions.Add(position);
} // }
if (data.isReversal) { positions.Reverse(); } // if (data.isReversal) { positions.Reverse(); }
return positions; // return positions;
} // }
} //}
@@ -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()
{
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f24a4f73b9925a9478f58b089059ef1e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -17,14 +17,14 @@ public class AssetsPlate : ModuleAssets<DataPlate> {
protected override void Awake() => ModuleCore.AssetsPlate = this; protected override void Awake() => ModuleCore.AssetsPlate = this;
public override void Add(DataPlate data) { public override void Add(DataPlate plate) {
if (dataPlates.Contains(data)) { return; } if (dataPlates.Contains(plate)) { return; }
dataPlates.Add(data); dataPlates.Add(plate);
//初始化参数 //初始化参数
data.designPosition = ViewCameraDesign.CameraPosition; plate.dataDesign.position = ViewCameraDesign.CameraPosition;
data.bakingPosition = ViewCameraDesign.CameraPosition; plate.dataBaking.position = ViewCameraDesign.CameraPosition;
//生成可视化内容 //生成可视化内容
data.UpdateVisual(); plate.UpdateVisual();
} }
public override void Remove(DataPlate data) { public override void Remove(DataPlate data) {
if (!dataPlates.Contains(data)) { return; } if (!dataPlates.Contains(data)) { return; }
@@ -5,37 +5,37 @@ using UnityEngine;
/// <summary> /// <summary>
/// 插入点(DataInsertPoint) 转换 点(DataPoint) /// 插入点(DataInsertPoint) 转换 点(DataPoint)
/// </summary> /// </summary>
public class BuilderInsertPointToPoint : ModuleBuilder<DataInsertPoint, DataPoint> { //public class BuilderInsertPointToPoint : ModuleBuilder<DataInsertPoint, DataPoint> {
protected override void Awake() => ModuleCore.InsertPointToPoint = this; // protected override void Awake() => ModuleCore.InsertPointToPoint = this;
public override DataPoint To(DataInsertPoint insertPoint) { // public override DataPoint To(DataInsertPoint insertPoint) {
DataPlate plate = insertPoint.plate; // DataPlate plate = insertPoint.plate;
Vector3 position = insertPoint.position; // Vector3 position = insertPoint.position;
//创建新的点 // //创建新的点
DataPoint point = new DataPoint(insertPoint.plate); // DataPoint point = new DataPoint(insertPoint.plate);
point.position = position; // point.position = position;
//改变关联的边B点,重置贝塞尔曲线 // //改变关联的边B点,重置贝塞尔曲线
insertPoint.side.bPoint = point; // insertPoint.side.bPoint = point;
insertPoint.side.OneRankBezier(); // insertPoint.side.OneRankBezier();
//创建新的边 // //创建新的边
DataSide side = CreateDataSide(plate, point, insertPoint.bPoint); // DataSide side = CreateDataSide(plate, point, insertPoint.bPoint);
//插入边 // //插入边
int sideIndex = plate.sides.IndexOf(insertPoint.side); // int sideIndex = plate.sides.IndexOf(insertPoint.side);
plate.sides.Insert(sideIndex + 1, side); // plate.sides.Insert(sideIndex + 1, side);
//插入点 // //插入点
int pointIndex = plate.points.IndexOf(insertPoint.aPoint); // int pointIndex = plate.points.IndexOf(insertPoint.aPoint);
plate.points.Insert(pointIndex + 1, point); // plate.points.Insert(pointIndex + 1, point);
//更新数据 // //更新数据
plate.UpdateVisual(); // plate.UpdateVisual();
return point; // return point;
} // }
private DataSide CreateDataSide(DataPlate plate, DataPoint a, DataPoint b) { // private DataSide CreateDataSide(DataPlate plate, DataPoint a, DataPoint b) {
DataSide side = new DataSide(plate); // DataSide side = new DataSide(plate);
side.aPoint = a; // side.aPoint = a;
side.bPoint = b; // side.bPoint = b;
side.OneRankBezier(); // side.OneRankBezier();
return side; // return side;
} // }
} //}
@@ -11,24 +11,24 @@ public class BuilderPlatePresetsToPlate : ModuleBuilder<DataPlatePresets, DataPl
public override DataPlate To(DataPlatePresets origin) { public override DataPlate To(DataPlatePresets origin) {
DataPlate dataPlate = new DataPlate(); DataPlate dataPlate = new DataPlate();
dataPlate.points = ToDataPoint(dataPlate, origin.designPoints); dataPlate.platePoints = ToDataPoint(dataPlate, origin.designPoints);
dataPlate.sides = ToDataSide(dataPlate, dataPlate.points); dataPlate.plateSides = ToDataSide(dataPlate, dataPlate.platePoints);
return dataPlate; return dataPlate;
} }
private List<DataPoint> ToDataPoint(DataPlate dataPlate, List<Vector3> list) { private List<DataPlatePoint> ToDataPoint(DataPlate dataPlate, List<Vector3> list) {
List<DataPoint> points = new List<DataPoint>(); List<DataPlatePoint> points = new List<DataPlatePoint>();
for (int i = 0; i < list.Count; i++) { for (int i = 0; i < list.Count; i++) {
DataPoint point = new DataPoint(dataPlate); DataPlatePoint point = new DataPlatePoint(dataPlate);
point.position = list[i]; point.position = list[i];
points.Add(point); points.Add(point);
} }
return points; return points;
} }
private List<DataSide> ToDataSide(DataPlate dataPlate, List<DataPoint> list) { private List<DataPlateSide> ToDataSide(DataPlate dataPlate, List<DataPlatePoint> list) {
List<DataSide> sides = new List<DataSide>(); List<DataPlateSide> sides = new List<DataPlateSide>();
for (int i = 0; i < list.Count; i++) { 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.aPoint = list.LoopIndex(i + 0);
side.bPoint = list.LoopIndex(i + 1); side.bPoint = list.LoopIndex(i + 1);
side.OneRankBezier(); side.OneRankBezier();
+12 -12
View File
@@ -46,37 +46,37 @@ public class ModuleCore : Module<ModuleCore> {
public ModuleBuilder<DataPlatePresets, DataPlate> PlatePresetsToPlate; public ModuleBuilder<DataPlatePresets, DataPlate> PlatePresetsToPlate;
/// <summary> 板片数据(DataPlate) 转换 多边形数据(DataPolygon) </summary> /// <summary> 板片数据(DataPlate) 转换 多边形数据(DataPolygon) </summary>
public ModuleBuilder<DataPlate, DataPolygon> PlateToPolygon; public ModuleBuilder<DataPlate, DataPolygon> PlateToPolygon;
/// <summary> 插入点(DataInsertPoint) 转换 点(DataPoint) </summary>
public ModuleBuilder<DataInsertPoint, DataPoint> InsertPointToPoint;
#endregion #endregion
#region #region
/// <summary> 设计可视化内容生成模块 </summary> /// <summary> 板片设计 可视化内容生成模块 </summary>
public ModuleVisual<DataPlate> VisualDesign; public ModuleVisual<DataPlate> VisualPlateDesign;
/// <summary> 烘焙可视化内容生成模块 </summary> /// <summary> 板片烘焙 可视化内容生成模块 </summary>
public ModuleVisual<DataPlate> VisualBaking; public ModuleVisual<DataPlate> VisualPlateBaking;
/// <summary> 连接可视化内容生成模块 </summary> /// <summary> 缝合设计 可视化内容生成模块 </summary>
public ModuleVisual<DataSuture> VisualSutureDesign;
/// <summary> 缝合烘焙 可视化内容生成模块 </summary>
public ModuleVisual<DataSuture> VisualSutureBaking;
/// <summary> 连接器 可视化内容生成模块 </summary>
public ModuleVisual<DataConnector> VisualConnector; public ModuleVisual<DataConnector> VisualConnector;
#endregion #endregion
#region #region
/// <summary> 查询点模块 </summary> /// <summary> 查询点模块 </summary>
public ModuleFind<DataPoint> FindPoint; public ModuleFind<DataPlatePoint> FindPoint;
/// <summary> 查询边模块 </summary> /// <summary> 查询边模块 </summary>
public ModuleFind<DataSide> FindSide; public ModuleFind<DataPlateSide> FindSide;
/// <summary> 查询贝塞尔点模块 </summary> /// <summary> 查询贝塞尔点模块 </summary>
public ModuleFind<DataBezier> FindBezier; public ModuleFind<DataBezier> FindBezier;
#endregion #endregion
#region #region
/// <summary> 计算位置到边上最近的点 </summary>
public ModuleAlgorithm<DataIntersect> AlgorithmSidePoint;
/// <summary> 简单多边形算法模块 </summary> /// <summary> 简单多边形算法模块 </summary>
public ModuleAlgorithm<DataPlate> AlgorithmSimplePolygon; public ModuleAlgorithm<DataPlate> AlgorithmSimplePolygon;
/// <summary> 细分多边形算法模块 </summary> /// <summary> 细分多边形算法模块 </summary>
public ModuleAlgorithm<DataPlate> AlgorithmSubdivisionPolygon; public ModuleAlgorithm<DataPlate> AlgorithmSubdivisionPolygon;
/// <summary> 缝合边算法模块 </summary> /// <summary> 缝合边算法模块 </summary>
public ModuleAlgorithm<DataSutureSide> AlgorithmSutureSide; public ModuleAlgorithm<DataSuture> AlgorithmSuture;
#endregion #endregion
#region #region
+4 -4
View File
@@ -15,7 +15,7 @@ public class FindBezier : ModuleFind<DataBezier> {
public override bool Find(Vector3 position, out DataBezier bezier) { public override bool Find(Vector3 position, out DataBezier bezier) {
List<DataPlate> plates = AssetsPlate.Datas; List<DataPlate> plates = AssetsPlate.Datas;
for (int i = 0; i < plates.Count; i++) { 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); bezier = Find(plates[i], localPosition);
if (bezier != null) { return true; } if (bezier != null) { return true; }
} }
@@ -24,14 +24,14 @@ public class FindBezier : ModuleFind<DataBezier> {
/// <summary> 查询匹配的边 </summary> /// <summary> 查询匹配的边 </summary>
private DataBezier Find(DataPlate plate, Vector3 localPosition) { private DataBezier Find(DataPlate plate, Vector3 localPosition) {
for (int i = 0; i < plate.sides.Count; i++) { for (int i = 0; i < plate.plateSides.Count; i++) {
DataBezier bezier = Find(plate.sides[i], localPosition); DataBezier bezier = Find(plate.plateSides[i], localPosition);
if (bezier != null) { return bezier; } if (bezier != null) { return bezier; }
} }
return null; return null;
} }
/// <summary> 查询匹配的边 </summary> /// <summary> 查询匹配的边 </summary>
private DataBezier Find(DataSide side, Vector3 localPosition) { private DataBezier Find(DataPlateSide side, Vector3 localPosition) {
if (side.bezier == Bezier.) { return null; } if (side.bezier == Bezier.) { return null; }
float aDis = Vector3.Distance(side.aBezier, localPosition); float aDis = Vector3.Distance(side.aBezier, localPosition);
if (aDis < FindRange) { return new DataBezier() { isA = true, side = side }; } if (aDis < FindRange) { return new DataBezier() { isA = true, side = side }; }
+5 -5
View File
@@ -5,17 +5,17 @@ using UnityEngine;
/// <summary> /// <summary>
/// 查找点 /// 查找点
/// </summary> /// </summary>
public class FindPoint : ModuleFind<DataPoint> { public class FindPoint : ModuleFind<DataPlatePoint> {
public readonly float FindRange = 0.01f; public readonly float FindRange = 0.01f;
/// <summary> 板片资产 </summary> /// <summary> 板片资产 </summary>
public ModuleAssets<DataPlate> AssetsPlate => ModuleCore.AssetsPlate; public ModuleAssets<DataPlate> AssetsPlate => ModuleCore.AssetsPlate;
protected override void Awake() => ModuleCore.FindPoint = this; 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<DataPlate> plates = AssetsPlate.Datas; List<DataPlate> plates = AssetsPlate.Datas;
for (int i = 0; i < plates.Count; i++) { 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); point = Find(plates[i], localPosition);
if (point != null) { return true; } if (point != null) { return true; }
} }
@@ -23,8 +23,8 @@ public class FindPoint : ModuleFind<DataPoint> {
} }
/// <summary> 查询匹配的点 </summary> /// <summary> 查询匹配的点 </summary>
private DataPoint Find(DataPlate plate, Vector3 localPosition) { private DataPlatePoint Find(DataPlate plate, Vector3 localPosition) {
List<DataPoint> points = plate.points; List<DataPlatePoint> points = plate.platePoints;
for (int i = 0; i < points.Count; i++) { for (int i = 0; i < points.Count; i++) {
float distance = Vector3.Distance(points[i].position, localPosition); float distance = Vector3.Distance(points[i].position, localPosition);
if (distance > FindRange) { continue; } if (distance > FindRange) { continue; }
+12 -12
View File
@@ -5,17 +5,17 @@ using UnityEngine;
/// <summary> /// <summary>
/// 查找边 /// 查找边
/// </summary> /// </summary>
public class FindSide : ModuleFind<DataSide> { public class FindSide : ModuleFind<DataPlateSide> {
public readonly float FindRange = 0.01f; public readonly float FindRange = 0.01f;
/// <summary> 板片资产 </summary> /// <summary> 板片资产 </summary>
public ModuleAssets<DataPlate> AssetsPlate => ModuleCore.AssetsPlate; public ModuleAssets<DataPlate> AssetsPlate => ModuleCore.AssetsPlate;
protected override void Awake() => ModuleCore.FindSide = this; 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<DataPlate> plates = AssetsPlate.Datas; List<DataPlate> plates = AssetsPlate.Datas;
for (int i = 0; i < plates.Count; i++) { 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); side = Find(plates[i], localPosition);
if (side != null) { return true; } if (side != null) { return true; }
} }
@@ -23,20 +23,20 @@ public class FindSide : ModuleFind<DataSide> {
} }
/// <summary> 查询匹配的边 </summary> /// <summary> 查询匹配的边 </summary>
private DataSide Find(DataPlate plate, Vector3 localPosition) { private DataPlateSide Find(DataPlate plate, Vector3 localPosition) {
for (int i = 0; i < plate.sides.Count; i++) { for (int i = 0; i < plate.plateSides.Count; i++) {
DataSide side = Find(plate.sides[i], localPosition); DataPlateSide side = Find(plate.plateSides[i], localPosition);
if (side != null) { return side; } if (side != null) { return side; }
} }
return null; return null;
} }
/// <summary> 查询匹配的边 </summary> /// <summary> 查询匹配的边 </summary>
private DataSide Find(DataSide side, Vector3 localPosition) { private DataPlateSide Find(DataPlateSide side, Vector3 localPosition) {
for (int i = 0; i < side.lines.Length; i++) { DataPlateSideDesign design = side.dataDesign;
Vector3 a = side.lines[i].a; for (int i = 0; i < design.lines.Length; i++) {
Vector3 b = side.lines[i].b; Vector3 a = design.lines[i].a;
Vector3 b = design.lines[i].b;
float distance = ProjectDistance(a, b, localPosition); float distance = ProjectDistance(a, b, localPosition);
//Debug.Log($"{a} , {b} , {localPosition}");
if (distance < FindRange) { return side; } if (distance < FindRange) { return side; }
} }
return null; return null;
+39 -39
View File
@@ -2,45 +2,45 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
public class VisualBaking : ModuleVisual<DataPlate> { //public class VisualBaking : ModuleVisual<DataPlate> {
public Transform viewSpace; // public Transform viewSpace;
public Transform platePrefab;//板片 // public Transform platePrefab;//板片
public Transform suturePrefab;//缝合 // public Transform suturePrefab;//缝合
public Transform sutureSidePrefab;//缝合边 // public Transform sutureSidePrefab;//缝合边
protected override void Awake() => ModuleCore.VisualBaking = this; // protected override void Awake() => ModuleCore.VisualBaking = this;
public override void UpdateVisual(DataPlate plate) { // public override void UpdateVisual(DataPlate plate) {
//更新板片 // //更新板片
Create(ref plate.baking, platePrefab, viewSpace); // Create(ref plate.baking, platePrefab, viewSpace);
plate.baking.UpdateVisual(plate); // plate.baking.UpdateVisual(plate);
//子数据父对象 // //子数据父对象
Transform parent = plate.design.transform; // Transform parent = plate.design.transform;
//更新线段 // //更新线段
plate.sides.ForEach(obj => UpdateVisual(obj, parent)); // plate.sides.ForEach(obj => UpdateVisual(obj, parent));
} // }
public override void ReleaseVisual(DataPlate data) { // public override void ReleaseVisual(DataPlate data) {
throw new System.NotImplementedException(); // throw new System.NotImplementedException();
} // }
private void UpdateVisual(DataSide side, Transform parent) { // private void UpdateVisual(DataSide side, Transform parent) {
//Create(ref side.design, sidePrefab, parent); // //Create(ref side.design, sidePrefab, parent);
//side.design.UpdateVisual(side); // //side.design.UpdateVisual(side);
//更新缝合线 // //更新缝合线
if (side.suture == null) { return; } // if (side.suture == null) { return; }
//side.suture.Update(); // //side.suture.Update();
UpdateVisual(side.suture, viewSpace); // UpdateVisual(side.suture, viewSpace);
} // }
/// <summary> 更新缝合数据 </summary> // /// <summary> 更新缝合数据 </summary>
private void UpdateVisual(DataSuture suture, Transform parent) { // private void UpdateVisual(DataSuture suture, Transform parent) {
Create(ref suture.baking, suturePrefab, parent); // Create(ref suture.baking, suturePrefab, parent);
UpdateVisual(suture.a, suture.baking.transform); // UpdateVisual(suture.a, suture.baking.transform);
UpdateVisual(suture.b, suture.baking.transform); // UpdateVisual(suture.b, suture.baking.transform);
suture.baking.UpdateVisual(suture); // suture.baking.UpdateVisual(suture);
} // }
/// <summary> 更新缝合边 </summary> // /// <summary> 更新缝合边 </summary>
private void UpdateVisual(DataSutureSide sutureSide, Transform parent) { // private void UpdateVisual(DataSutureSide sutureSide, Transform parent) {
Create(ref sutureSide.baking, sutureSidePrefab, parent); // Create(ref sutureSide.baking, sutureSidePrefab, parent);
sutureSide.baking.UpdateVisual(sutureSide); // sutureSide.baking.UpdateVisual(sutureSide);
} // }
} //}
+47 -47
View File
@@ -5,53 +5,53 @@ using UnityEngine;
/// <summary> /// <summary>
/// 版片可视化模块 /// 版片可视化模块
/// </summary> /// </summary>
public class VisualDesign : ModuleVisual<DataPlate> { //public class VisualDesign : ModuleVisual<DataPlate> {
public Transform viewSpace; // public Transform viewSpace;
public Transform platePrefab;//板片 // public Transform platePrefab;//板片
public Transform pointPrefab;//点 // public Transform pointPrefab;//点
public Transform sidePrefab;//边 // public Transform sidePrefab;//边
public Transform suturePrefab;//缝合 // public Transform suturePrefab;//缝合
public Transform sutureSidePrefab;//缝合边 // public Transform sutureSidePrefab;//缝合边
protected override void Awake() => ModuleCore.VisualDesign = this; // protected override void Awake() => ModuleCore.VisualDesign = this;
public override void UpdateVisual(DataPlate plate) { // public override void UpdateVisual(DataPlate plate) {
//更新板片 // //更新板片
Create(ref plate.design, platePrefab, viewSpace); // Create(ref plate.design, platePrefab, viewSpace);
plate.design.UpdateVisual(plate); // plate.design.UpdateVisual(plate);
//子数据父对象 // //子数据父对象
Transform parent = plate.design.transform; // Transform parent = plate.design.transform;
//更新点 // //更新点
plate.points.ForEach(obj => UpdateVisual(obj, parent)); // plate.points.ForEach(obj => UpdateVisual(obj, parent));
//更新线段 // //更新线段
plate.sides.ForEach(obj => UpdateVisual(obj, parent)); // plate.sides.ForEach(obj => UpdateVisual(obj, parent));
} // }
public override void ReleaseVisual(DataPlate data) { // public override void ReleaseVisual(DataPlate data) {
throw new System.NotImplementedException(); // throw new System.NotImplementedException();
} // }
private void UpdateVisual(DataPoint point, Transform parent) { // private void UpdateVisual(DataPoint point, Transform parent) {
Create(ref point.visual, pointPrefab, parent); // Create(ref point.visual, pointPrefab, parent);
point.visual.UpdateVisual(point); // point.visual.UpdateVisual(point);
} // }
private void UpdateVisual(DataSide side, Transform parent) { // private void UpdateVisual(DataSide side, Transform parent) {
Create(ref side.design, sidePrefab, parent); // Create(ref side.design, sidePrefab, parent);
side.design.UpdateVisual(side); // side.design.UpdateVisual(side);
//更新缝合线 // //更新缝合线
if (side.suture == null) { return; } // if (side.suture == null) { return; }
side.suture.Update(); // side.suture.Update();
UpdateVisual(side.suture, viewSpace); // UpdateVisual(side.suture, viewSpace);
} // }
/// <summary> 更新缝合数据 </summary> // /// <summary> 更新缝合数据 </summary>
private void UpdateVisual(DataSuture suture, Transform parent) { // private void UpdateVisual(DataSuture suture, Transform parent) {
Create(ref suture.design, suturePrefab, parent); // Create(ref suture.design, suturePrefab, parent);
UpdateVisual(suture.a, suture.design.transform); // UpdateVisual(suture.a, suture.design.transform);
UpdateVisual(suture.b, suture.design.transform); // UpdateVisual(suture.b, suture.design.transform);
suture.design.UpdateVisual(suture); // suture.design.UpdateVisual(suture);
} // }
/// <summary> 更新缝合边 </summary> // /// <summary> 更新缝合边 </summary>
private void UpdateVisual(DataSutureSide sutureSide, Transform parent) { // private void UpdateVisual(DataSutureSide sutureSide, Transform parent) {
Create(ref sutureSide.design, sutureSidePrefab, parent); // Create(ref sutureSide.design, sutureSidePrefab, parent);
sutureSide.design.UpdateVisual(sutureSide); // sutureSide.design.UpdateVisual(sutureSide);
} // }
} //}
@@ -0,0 +1,46 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class VisualPlateBaking : ModuleVisual<DataPlate> {
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);
}
/// <summary> 更新缝合数据 </summary>
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);
}
/// <summary> 更新缝合边 </summary>
private void UpdateVisual(DataSutureSide sutureSide, Transform parent) {
Create(ref sutureSide.baking, sutureSidePrefab, parent);
sutureSide.baking.UpdateVisual(sutureSide);
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ef4a839345dfb344382e257d374ca3ed
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,41 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 版片可视化模块
/// </summary>
public class VisualPlateDesign : ModuleVisual<DataPlate> {
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(); }
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f9827f83f79c2af42b2a06bdc3c80719
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,31 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 缝合烘焙可视化模块
/// </summary>
public class VisualSutureBaking : ModuleVisual<DataSuture> {
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();
}
/// <summary> 更新缝合边 </summary>
private void UpdateVisual(DataSutureSide sutureSide, Transform parent) {
Create(ref sutureSide.baking, sutureSidePrefab, parent);
sutureSide.baking.UpdateVisual(sutureSide);
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 06ff2a0f351be2d41aa7c8dfc23798e0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,31 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 缝合设计可视化模块
/// </summary>
public class VisualSutureDesign : ModuleVisual<DataSuture> {
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();
}
/// <summary> 更新缝合边 </summary>
private void UpdateVisual(DataSutureSide sutureSide, Transform parent) {
Create(ref sutureSide.design, sutureSidePrefab, parent);
sutureSide.design.UpdateVisual(sutureSide);
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a43eabbe6a52df943b5157da8933dd33
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+1 -1
View File
@@ -6,7 +6,7 @@ public class DataBezier {
/// <summary> 是否是a </summary> /// <summary> 是否是a </summary>
public bool isA; public bool isA;
/// <summary> 关联的边 </summary> /// <summary> 关联的边 </summary>
public DataSide side; public DataPlateSide side;
/// <summary> 位置 </summary> /// <summary> 位置 </summary>
public Vector3 position => isA ? side.aBezier : side.bBezier; public Vector3 position => isA ? side.aBezier : side.bBezier;
+16 -3
View File
@@ -2,21 +2,34 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
/// <summary> 2D边界数据 </summary> /// <summary> 边界数据 </summary>
public class DataBorder { public class DataBorder {
/// <summary> 网格细分 </summary>
public readonly float smooth = 0.01f;
/// <summary> minX </summary>
public readonly float minX = 0; public readonly float minX = 0;
/// <summary> maxX </summary>
public readonly float maxX = 0; public readonly float maxX = 0;
/// <summary> minY </summary>
public readonly float minY = 0; public readonly float minY = 0;
/// <summary> maxY </summary>
public readonly float maxY = 0; public readonly float maxY = 0;
/// <summary> 2D边界数据 </summary> /// <summary> 多边形边缘点 </summary>
public DataBorder(float minX, float maxX, float minY, float maxY) { public readonly Vector3[] points;
/// <summary> 边界数据 </summary>
public DataBorder(float minX, float maxX, float minY, float maxY, Vector3[] points) {
this.minX = minX; this.maxX = maxX; this.minX = minX; this.maxX = maxX;
this.minY = minY; this.maxY = maxY; this.minY = minY; this.maxY = maxY;
this.points = points;
} }
/// <summary> 边界宽 </summary> /// <summary> 边界宽 </summary>
public float Wide => maxX - minX; public float Wide => maxX - minX;
/// <summary> 边界高 </summary> /// <summary> 边界高 </summary>
public float High => maxY - minY; public float High => maxY - minY;
/// <summary> 网格宽 </summary>
public int GridWide => Mathf.FloorToInt(Wide / smooth) + 1;
/// <summary> 网格高 </summary>
public int GridHigh => Mathf.FloorToInt(High / smooth) + 1;
/// <summary> 最小点 </summary> /// <summary> 最小点 </summary>
public Vector3 MinPoint => new Vector3(minX, minY, 0); public Vector3 MinPoint => new Vector3(minX, minY, 0);
/// <summary> 最大点 </summary> /// <summary> 最大点 </summary>
+44 -27
View File
@@ -7,18 +7,22 @@ public class DataPlate {
/// <summary> 核心模块 </summary> /// <summary> 核心模块 </summary>
private ModuleCore ModuleCore => ModuleCore.I; private ModuleCore ModuleCore => ModuleCore.I;
/// <summary> 设计可视化模块 </summary> /// <summary> 设计可视化模块 </summary>
private ModuleVisual<DataPlate> VisualDesign => ModuleCore.VisualDesign; private ModuleVisual<DataPlate> VisualDesign => ModuleCore.VisualPlateDesign;
/// <summary> 烘焙可视化模块 </summary> /// <summary> 烘焙可视化模块 </summary>
private ModuleVisual<DataPlate> VisualBaking => ModuleCore.VisualBaking; private ModuleVisual<DataPlate> VisualBaking => ModuleCore.VisualPlateBaking;
/// <summary> 简单多边形算法模块 </summary> /// <summary> 简单多边形算法模块 </summary>
private ModuleAlgorithm<DataPlate> AlgorithmSimplePolygon => ModuleCore.AlgorithmSimplePolygon; private ModuleAlgorithm<DataPlate> AlgorithmSimplePolygon => ModuleCore.AlgorithmSimplePolygon;
/// <summary> 细分多边形算法模块 </summary> /// <summary> 细分多边形算法模块 </summary>
private ModuleAlgorithm<DataPlate> AlgorithmSubdivisionPolygon => ModuleCore.AlgorithmSubdivisionPolygon; private ModuleAlgorithm<DataPlate> AlgorithmSubdivisionPolygon => ModuleCore.AlgorithmSubdivisionPolygon;
public DataPlate() {
dataDesign = new DataPlateDesign(this);
}
public void UpdateVisual(bool recalculate = true) { public void UpdateVisual(bool recalculate = true) {
if (recalculate) { if (recalculate) {
//简单多边形计算 //简单多边形计算
//AlgorithmSimplePolygon.Compute(this); AlgorithmSimplePolygon.Compute(this);
//细分多边形计算 //细分多边形计算
AlgorithmSubdivisionPolygon.Compute(this); AlgorithmSubdivisionPolygon.Compute(this);
} }
@@ -29,42 +33,55 @@ public class DataPlate {
} }
#region #region
/// <summary> 边缘平滑度 </summary>
public float smooth = 0.01f;
/// <summary> 板片设计视图的位置(本地坐标系) </summary>
public Vector3 designPosition;
/// <summary> 板片烘焙视图的位置(本地坐标系) </summary>
public Vector3 bakingPosition;
/// <summary> 板片烘焙视图的旋转(本地坐标系) </summary>
public Vector3 bakingEulerAngles;
/// <summary> 点 </summary> /// <summary> 点 </summary>
public List<DataPoint> points = new List<DataPoint>(); public List<DataPlatePoint> platePoints = new List<DataPlatePoint>();
/// <summary> 边 </summary> /// <summary> 边 </summary>
public List<DataSide> sides = new List<DataSide>(); public List<DataPlateSide> plateSides = new List<DataPlateSide>();
#endregion #endregion
#region #region
/// <summary> 边界数据 </summary> /// <summary> 设计缓存数据 </summary>
public DataBorder border; public DataPlateDesign dataDesign;
/// <summary> 边缘点 </summary> /// <summary> 烘焙缓存数据 </summary>
public List<Vector3> edgePoints; public DataPlateBaking dataBaking = new DataPlateBaking();
/// <summary> 设计网格 </summary>
public Mesh designMesh;
/// <summary> 三角形数据 </summary>
public List<DataTriangle> triangles;
/// <summary> 顶点网格 </summary>
public GridTool<DataVertex> vertexGrid;
#endregion #endregion
#region #region
/// <summary> 可视化对象 </summary> /// <summary> 可视化对象 </summary>
public ModulePrefab<DataPlate> design; public ModulePrefab<DataPlate> designPrefab;
/// <summary> 可视化对象 </summary> /// <summary> 可视化对象 </summary>
public ModulePrefab<DataPlate> baking; public ModulePrefab<DataPlate> bakingPrefab;
/// <summary> 安排点 </summary> /// <summary> 安排点 </summary>
public FixedArrange arrange; public FixedArrange arrange;
#endregion #endregion
}
/// <summary> 设计缓存数据 </summary>
public class DataPlateDesign {
/// <summary> 板片 </summary>
public readonly DataPlate plate;
/// <summary> 设计缓存数据 </summary>
public DataPlateDesign(DataPlate plate) => this.plate = plate;
/// <summary> 板片的位置 </summary>
public Vector3 position;
/// <summary> 网格 </summary>
public Mesh mesh;
/// <summary> 边缘点 </summary>
public Vector3[] points;
/// <summary> 三角形数据 </summary>
public List<DataTriangle> triangles;
}
/// <summary> 烘焙缓存数据 </summary>
public class DataPlateBaking {
/// <summary> 网格 </summary>
public Mesh mesh;
/// <summary> 板片的位置 </summary>
public Vector3 position;
/// <summary> 板片的旋转 </summary>
public Vector3 eulerAngles;
/// <summary> 边界数据 </summary>
public DataBorder border;
/// <summary> 全部顶点 </summary>
public DataPlateVertex[] vertexs;
} }
@@ -0,0 +1,17 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary> 线段 </summary>
public class DataPlateLine {
/// <summary> 线段起点a </summary>
public Vector3 a;
/// <summary> 线段终点b </summary>
public Vector3 b;
/// <summary> 原始距离 </summary>
public float origin;
/// <summary> 线段距离 </summary>
public float Distance => Vector3.Distance(a, b);
/// <summary> 线段方向 </summary>
public Vector3 Direction => b - a;
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c7e8d3e741e703d49b33431b75a3a001
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,21 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DataPlatePoint {
/// <summary> 绑定的板片 </summary>
public readonly DataPlate plate;
/// <summary> 初始化 </summary>
public DataPlatePoint(DataPlate plate) => this.plate = plate;
#region
/// <summary> 设计点位置(本地坐标系) </summary>
public Vector3 position;
#endregion
#region
/// <summary> 可视化对象 </summary>
public ModulePrefab<DataPlatePoint> visual;
#endregion
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6c2af0d32eea37f408900226b81e8e8a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,62 @@
using System.Collections;
using System.Collections.Generic;
using Unity.Collections;
using UnityEngine;
public enum Bezier {
= 0, = 1, = 2
}
/// <summary> 边 </summary>
public class DataPlateSide {
/// <summary> 绑定的板片 </summary>
public readonly DataPlate plate;
/// <summary> 初始化 </summary>
public DataPlateSide(DataPlate plate) => this.plate = plate;
#region
/// <summary> 贝塞尔曲线阶数 </summary>
public Bezier bezier;
/// <summary> 起点 </summary>
public DataPlatePoint aPoint;
/// <summary> 终点 </summary>
public DataPlatePoint bPoint;
/// <summary> 贝塞尔曲线前(-) </summary>
public Vector3 aBezier;
/// <summary> 贝塞尔曲线后(+) </summary>
public Vector3 bBezier;
#endregion
#region
/// <summary> 缝合数据 </summary>
public DataSuture suture;
/// <summary> 设计缓存数据 </summary>
public DataPlateSideDesign dataDesign = new DataPlateSideDesign();
/// <summary> 烘焙缓存数据 </summary>
public DataPlateSideBaking dataBaking = new DataPlateSideBaking();
#endregion
#region
/// <summary> 可视化边缘线 </summary>
public ModulePrefab<DataPlateSide> designPrefab;
#endregion
}
/// <summary> 设计缓存数据 </summary>
public class DataPlateSideDesign {
/// <summary> 总长度 </summary>
public float length;
/// <summary> 点 </summary>
public Vector3[] positions = new Vector3[0];
/// <summary> 线 </summary>
public DataPlateLine[] lines = new DataPlateLine[0];
}
/// <summary> 烘焙缓存数据 </summary>
public class DataPlateSideBaking {
/// <summary> 总长度 </summary>
public float length;
/// <summary> 点 </summary>
public Vector3[] positions = new Vector3[0];
/// <summary> 线 </summary>
public DataPlateLine[] lines = new DataPlateLine[0];
/// <summary> 关联的网格顶点 </summary>
public DataPlateVertex[] vertexs = new DataPlateVertex[0];
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d0a57f0098d07ca4da0ca6e08c25662c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,28 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DataPlateVertex {
/// <summary> 是否是有效顶点 </summary>
public bool isValid;
/// <summary> 设计视图中位置 </summary>
public Vector3 position;
/// <summary> 上 </summary>
public DataPlateVertex above;
/// <summary> 下 </summary>
public DataPlateVertex below;
/// <summary> 左 </summary>
public DataPlateVertex left;
/// <summary> 右 </summary>
public DataPlateVertex right;
/// <summary> 左上 </summary>
public DataPlateVertex leftAbove;
/// <summary> 左下 </summary>
public DataPlateVertex leftBelow;
/// <summary> 右上 </summary>
public DataPlateVertex rightAbove;
/// <summary> 右下 </summary>
public DataPlateVertex rightBelow;
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9842037a7f0169b4bb8a4b70047f7739
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+3 -3
View File
@@ -2,9 +2,9 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
public enum Bezier { //public enum Bezier {
= 0, = 1, = 2 // 一阶 = 0, 二阶 = 1, 三阶 = 2
} //}
public class DataSide { public class DataSide {
/// <summary> 绑定的板片 </summary> /// <summary> 绑定的板片 </summary>
public readonly DataPlate plate; public readonly DataPlate plate;
+17 -8
View File
@@ -5,24 +5,33 @@ using UnityEngine;
public class DataSuture { public class DataSuture {
/// <summary> 核心模块 </summary> /// <summary> 核心模块 </summary>
private ModuleCore ModuleCore => ModuleCore.I; private ModuleCore ModuleCore => ModuleCore.I;
/// <summary> 简单多边形算法模块 </summary> /// <summary> 设计可视化模块 </summary>
private ModuleAlgorithm<DataSutureSide> AlgorithmSutureSide => ModuleCore.AlgorithmSutureSide; private ModuleVisual<DataSuture> VisualDesign => ModuleCore.VisualSutureDesign;
/// <summary> 烘焙可视化模块 </summary>
private ModuleVisual<DataSuture> VisualBaking => ModuleCore.VisualSutureBaking;
/// <summary> 缝合线算法模块 </summary>
private ModuleAlgorithm<DataSuture> AlgorithmSuture => ModuleCore.AlgorithmSuture;
public readonly DataSutureSide a; public readonly DataSutureSide a;
public readonly DataSutureSide b; public readonly DataSutureSide b;
public DataSuture(DataSide aSide, DataSide bSide) { public DataSuture(DataPlateSide aSide, DataPlateSide bSide) {
a = new DataSutureSide(aSide, this); a = new DataSutureSide(aSide, this);
b = new DataSutureSide(bSide, this); b = new DataSutureSide(bSide, this);
Update(); UpdateVisual();
} }
public void Update() { public void UpdateVisual() {
AlgorithmSutureSide.Compute(a); AlgorithmSuture.Compute(this);
AlgorithmSutureSide.Compute(b); VisualDesign.UpdateVisual(this);
VisualBaking.UpdateVisual(this);
} }
#region
/// <summary> 缝合长度 </summary> /// <summary> 缝合长度 </summary>
public float length => this.SutureLength(); public float length;
/// <summary> 缝合点 </summary>
public List<DataSuturePoint> points;
#endregion
#region #region
/// <summary> 可视化内容 </summary> /// <summary> 可视化内容 </summary>
@@ -0,0 +1,14 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DataSuturePoint {
/// <summary> aAnchor到vertex的距离 </summary>
public float distance;
/// <summary> 绑定的顶点 </summary>
public DataPlateVertex vertex;
/// <summary> 锚点a </summary>
public DataPlateVertex aAnchor;
/// <summary> 锚点b </summary>
public DataPlateVertex bAnchor;
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fab08a6f4689d1c4b94d2fd7f05fedbe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+47 -29
View File
@@ -7,12 +7,12 @@ using UnityEngine;
/// </summary> /// </summary>
public class DataSutureSide { public class DataSutureSide {
/// <summary> 关联的边 </summary> /// <summary> 关联的边 </summary>
public readonly DataSide side; public readonly DataPlateSide plateSide;
/// <summary> 关联的缝合数据 </summary> /// <summary> 关联的缝合数据 </summary>
public readonly DataSuture suture; public readonly DataSuture suture;
/// <summary> 缝合边 </summary> /// <summary> 缝合边 </summary>
public DataSutureSide(DataSide side, DataSuture suture) { public DataSutureSide(DataPlateSide side, DataSuture suture) {
this.side = side; this.plateSide = side;
this.suture = suture; this.suture = suture;
} }
@@ -22,32 +22,10 @@ public class DataSutureSide {
#endregion #endregion
#region #region
/// <summary> 设计缓存数据 </summary>
/// <summary> 边最大长度 </summary> public DataSutureSideDesign dataDesign = new DataSutureSideDesign();
public float MaxLength => side.length; /// <summary> 烘焙缓存数据 </summary>
/// <summary> 边缘顶点数据 </summary> public DataSutureSideBaking dataBaking = new DataSutureSideBaking();
public DataVertex[] Vertices => side.vertices;
/// <summary> 设计视图板片位置 </summary>
public Vector3 PlateDesignPosition => side.plate.designPosition;
/// <summary> 烘焙视图板片位置 </summary>
public Vector3 PlateBakingPosition => side.plate.bakingPosition;
/// <summary> 烘焙视图板片位置 </summary>
public Vector3 PlateBakingEulerAngles => side.plate.bakingEulerAngles;
/// <summary> 设计视图顶点位置 </summary>
public Vector3[] designPositions;
/// <summary> 设计视图A点位置 </summary>
public Vector3 DesignPosintA => designPositions[0];
/// <summary> 设计视图B点位置 </summary>
public Vector3 DesignPosintB => designPositions[designPositions.Length - 1];
/// <summary> 烘焙视图顶点位置 </summary>
public Vector3[] bakingPositions;
/// <summary> 烘焙视图A点位置 </summary>
public Vector3 BakingPosintA => bakingPositions[0];
/// <summary> 烘焙视图B点位置 </summary>
public Vector3 BakingPosintB => bakingPositions[bakingPositions.Length - 1];
#endregion #endregion
#region #region
@@ -57,3 +35,43 @@ public class DataSutureSide {
public ModulePrefab<DataSutureSide> baking; public ModulePrefab<DataSutureSide> baking;
#endregion #endregion
} }
/// <summary> 设计缓存数据 </summary>
public class DataSutureSideDesign {
/// <summary> 位置列表 </summary>
public Vector3[] positions;
/// <summary> A点位置 </summary>
public Vector3 PointA => positions[0];
/// <summary> B点位置 </summary>
public Vector3 PointB => positions[positions.Length - 1];
}
/// <summary> 烘焙缓存数据 </summary>
public class DataSutureSideBaking {
/// <summary> 位置列表 </summary>
public Vector3[] positions;
/// <summary> 全部顶点列表 </summary>
public DataSutureSideVertex[] allVertexs;
/// <summary> 关联的顶点列表 </summary>
public DataSutureSideVertex[] vertexs;
/// <summary> A点位置 </summary>
public Vector3 PointA => positions[0];
/// <summary> B点位置 </summary>
public Vector3 PointB => positions[positions.Length - 1];
}
public class DataSutureSideVertex {
/// <summary> 边起点到a点的距离 </summary>
public float origin;
/// <summary> a点 </summary>
public DataPlateVertex a;
/// <summary> a点的下一个点 </summary>
public DataPlateVertex b;
/// <summary> 缝合边顶点 </summary>
public DataSutureSideVertex(float origin, DataPlateVertex a, DataPlateVertex b) {
this.origin = origin;
this.a = a;
this.b = b;
}
/// <summary> 最大距离 origin + a - b </summary>
public float MaxDistance => origin + Distance;
/// <summary> 分段距离 a-b </summary>
public float Distance => Vector3.Distance(a.position, b.position);
}
+1
View File
@@ -6,6 +6,7 @@ public struct DataTriangle {
public Vector3 a; public Vector3 a;
public Vector3 b; public Vector3 b;
public Vector3 c; public Vector3 c;
public override string ToString() { public override string ToString() {
return $"{a} , {b} , {c}"; return $"{a} , {b} , {c}";
} }
+5 -5
View File
@@ -12,10 +12,10 @@ public class PrefabPlateBaking : ModulePrefab<DataPlate> {
public override void UpdateVisual(DataPlate plate) { public override void UpdateVisual(DataPlate plate) {
this.plate = plate; this.plate = plate;
transform.localPosition = plate.bakingPosition; DataPlateBaking baking = plate.dataBaking;
transform.localEulerAngles = plate.bakingEulerAngles; //transform.localPosition = baking.position;
//transform.localEulerAngles = baking.eulerAngles;
meshFilter.mesh = plate.designMesh; meshFilter.mesh = baking.mesh;
meshCollider.sharedMesh = plate.designMesh; meshCollider.sharedMesh = baking.mesh;
} }
} }
+4 -3
View File
@@ -12,9 +12,10 @@ public class PrefabPlateDesign : ModulePrefab<DataPlate> {
public override void UpdateVisual(DataPlate plate) { public override void UpdateVisual(DataPlate plate) {
this.plate = plate; this.plate = plate;
transform.localPosition = plate.designPosition; DataPlateDesign design = plate.dataDesign;
meshFilter.mesh = plate.designMesh; transform.localPosition = design.position;
meshCollider.sharedMesh = plate.designMesh; meshFilter.mesh = design.mesh;
meshCollider.sharedMesh = design.mesh;
} }
} }
+4 -4
View File
@@ -2,12 +2,12 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
public class PrefabPoint : ModulePrefab<DataPoint> { public class PrefabPoint : ModulePrefab<DataPlatePoint> {
private DataPoint point; 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; this.point = point;
transform.localPosition = point.position; transform.localPosition = point.position;
} }
+7 -6
View File
@@ -3,20 +3,20 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
public class PrefabSide : ModulePrefab<DataSide> { public class PrefabSide : ModulePrefab<DataPlateSide> {
public Transform aPoint; public Transform aPoint;
public Transform bPoint; public Transform bPoint;
public LineRenderer lineRenderer; public LineRenderer lineRenderer;
public LineRenderer aBezier; public LineRenderer aBezier;
public LineRenderer bBezier; public LineRenderer bBezier;
private DataSide side; private DataPlateSide side;
#region #region
/// <summary> 设计UI输入模块 </summary> /// <summary> 设计UI输入模块 </summary>
public ModuleUIInput<UnitMouseInput> UIInputDesign => ModuleCore.I.UIInputDesign; public ModuleUIInput<UnitMouseInput> UIInputDesign => ModuleCore.I.UIInputDesign;
#endregion #endregion
public override DataSide Value => side; public override DataPlateSide Value => side;
private void Awake() { private void Awake() {
UIInputDesign.OnChangeInput += UIInputDesign_OnChangeInput; UIInputDesign.OnChangeInput += UIInputDesign_OnChangeInput;
@@ -34,11 +34,12 @@ public class PrefabSide : ModulePrefab<DataSide> {
aBezier.gameObject.SetActive(false); aBezier.gameObject.SetActive(false);
bBezier.gameObject.SetActive(false); bBezier.gameObject.SetActive(false);
} }
public override void UpdateVisual(DataSide side) { public override void UpdateVisual(DataPlateSide side) {
this.side = side; this.side = side;
lineRenderer.positionCount = side.positions.Length; DataPlateSideDesign design = side.dataDesign;
lineRenderer.SetPositions(side.positions); lineRenderer.positionCount = design.positions.Length;
lineRenderer.SetPositions(design.positions);
Type type = UIInputDesign.Current.GetType(); Type type = UIInputDesign.Current.GetType();
if (type != typeof(DesignBezier)) { ActiveGameObject(false); return; } if (type != typeof(DesignBezier)) { ActiveGameObject(false); return; }
+6 -4
View File
@@ -14,10 +14,12 @@ public class PrefabSutureBaking : ModulePrefab<DataSuture> {
public override void UpdateVisual(DataSuture suture) { public override void UpdateVisual(DataSuture suture) {
this.suture = suture; this.suture = suture;
aLineRenderer.SetPosition(0, suture.a.BakingPosintA); DataSutureSideBaking aBaking = suture.a.dataBaking;
aLineRenderer.SetPosition(1, suture.b.BakingPosintA); DataSutureSideBaking bBaking = suture.b.dataBaking;
aLineRenderer.SetPosition(0, aBaking.PointA);
aLineRenderer.SetPosition(1, bBaking.PointA);
bLineRenderer.SetPosition(0, suture.a.BakingPosintB); bLineRenderer.SetPosition(0, aBaking.PointB);
bLineRenderer.SetPosition(1, suture.b.BakingPosintB); bLineRenderer.SetPosition(1, bBaking.PointB);
} }
} }
+6 -4
View File
@@ -14,10 +14,12 @@ public class PrefabSutureDesign : ModulePrefab<DataSuture> {
public override void UpdateVisual(DataSuture suture) { public override void UpdateVisual(DataSuture suture) {
this.suture = suture; this.suture = suture;
aLineRenderer.SetPosition(0, suture.a.DesignPosintA); DataSutureSideDesign aDesign = suture.a.dataDesign;
aLineRenderer.SetPosition(1, suture.b.DesignPosintA); DataSutureSideDesign bDesign = suture.b.dataDesign;
aLineRenderer.SetPosition(0, aDesign.PointA);
aLineRenderer.SetPosition(1, bDesign.PointA);
bLineRenderer.SetPosition(0, suture.a.DesignPosintB); bLineRenderer.SetPosition(0, aDesign.PointB);
bLineRenderer.SetPosition(1, suture.b.DesignPosintB); bLineRenderer.SetPosition(1, bDesign.PointB);
} }
} }
@@ -12,7 +12,8 @@ public class PrefabSutureSideBaking : ModulePrefab<DataSutureSide> {
public override void UpdateVisual(DataSutureSide sutureSide) { public override void UpdateVisual(DataSutureSide sutureSide) {
this.sutureSide = sutureSide; this.sutureSide = sutureSide;
lineRenderer.positionCount = sutureSide.bakingPositions.Length; DataSutureSideBaking baking = sutureSide.dataBaking;
lineRenderer.SetPositions(sutureSide.bakingPositions); lineRenderer.positionCount = baking.positions.Length;
lineRenderer.SetPositions(baking.positions);
} }
} }
@@ -12,7 +12,8 @@ public class PrefabSutureSideDesign : ModulePrefab<DataSutureSide> {
public override void UpdateVisual(DataSutureSide sutureSide) { public override void UpdateVisual(DataSutureSide sutureSide) {
this.sutureSide = sutureSide; this.sutureSide = sutureSide;
lineRenderer.positionCount = sutureSide.designPositions.Length; DataSutureSideDesign design = sutureSide.dataDesign;
lineRenderer.SetPositions(sutureSide.designPositions); lineRenderer.positionCount = design.positions.Length;
lineRenderer.SetPositions(design.positions);
} }
} }
+9 -9
View File
@@ -3,30 +3,30 @@ using System.Collections.Generic;
using UnityEngine; using UnityEngine;
public static class DataSideTool { 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.) { return; }
if (side.bezier == Bezier.) { side.bBezier = position; } if (side.bezier == Bezier.) { side.bBezier = position; }
side.aBezier = 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.) { return; }
if (side.bezier == Bezier.) { side.aBezier = position; } if (side.bezier == Bezier.) { side.aBezier = position; }
side.bBezier = position; side.bBezier = position;
} }
public static void OneRankBezier(this DataSide side) { public static void OneRankBezier(this DataPlateSide side) {
side.bezier = Bezier.; side.bezier = Bezier.;
} }
public static void TwoRankBezier(this DataSide side) { public static void TwoRankBezier(this DataPlateSide side) {
side.bezier = Bezier.; side.bezier = Bezier.;
DataPoint a = side.aPoint; DataPlatePoint a = side.aPoint;
DataPoint b = side.bPoint; DataPlatePoint b = side.bPoint;
side.aBezier = a.position + (b.position - a.position) * 0.5f; side.aBezier = a.position + (b.position - a.position) * 0.5f;
side.bBezier = 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.; side.bezier = Bezier.;
DataPoint a = side.aPoint; DataPlatePoint a = side.aPoint;
DataPoint b = side.bPoint; DataPlatePoint b = side.bPoint;
side.aBezier = a.position + (b.position - a.position) * 0.3f; side.aBezier = a.position + (b.position - a.position) * 0.3f;
side.bBezier = a.position + (b.position - a.position) * 0.7f; side.bBezier = a.position + (b.position - a.position) * 0.7f;
} }
+6 -6
View File
@@ -3,10 +3,10 @@ using System.Collections.Generic;
using UnityEngine; using UnityEngine;
public static class DataSutureTool { public static class DataSutureTool {
public static float SutureLength(this DataSuture suture) { //public static float SutureLength(this DataSuture suture) {
if (suture.a.MaxLength < suture.b.MaxLength) { // if (suture.a.MaxLength < suture.b.MaxLength) {
return suture.a.MaxLength; // return suture.a.MaxLength;
} // }
else { return suture.b.MaxLength; } // else { return suture.b.MaxLength; }
} //}
} }
@@ -0,0 +1,151 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 烘焙顶点计算
/// </summary>
public class UnitAlgorithmBakingVertex : UnitAlgorithm<DataPlateBaking> {
/// <summary> 烘焙顶点计算 </summary>
public UnitAlgorithmBakingVertex() { }
public void Compute(DataPlateBaking plateBaking) {
DataBorder border = plateBaking.border;
Vector3[] points = border.points;
//计算内部顶点
//plateBaking.grid = new GridTool<DataPlateVertex>(border.GridWide, border.GridHigh, (x, y) => {
// Vector3 position = border.MinPoint + new Vector3(x * border.smooth, y * border.smooth);
// DataPlateVertex vertex = new DataPlateVertex();
// vertex.isValid = FindPlateInside(points, position);
// vertex.position = position;
// return vertex;
//});
//List<DataPlateSide> plateSides = plateBaking.plate.plateSides;
//边缘所有的线段
//for (int i = 0; i < plateSides.Count; i++) {
//Compute(plateSides[i], border.GridWide, border.GridHigh, border, border.smooth, plateBaking.grid);
//}
}
/// <summary> 向网格和边缘写入顶点数据 </summary>
private void Compute(DataPlateSide side, int wide, int high, DataBorder border, float smooth, GridTool<DataPlateVertex> grid) {
DataPlateLine[] lines = side.dataBaking.lines;
List<SideVertex> sideVertices = new List<SideVertex>();
//计算水平线段顶点
for (int x = 0; x < wide; x++) {
Vector3 a = new Vector3(border.minX + x * smooth, border.minY - 1);
Vector3 b = new Vector3(border.minX + x * smooth, border.maxY + 1);
for (int i = 0; i < lines.Length; i++) {
DataPlateVertex vertex = Compute(a, b, lines[i], smooth, border, grid);
if (vertex == null) { continue; }
float distance = Vector3.Distance(lines[i].a, vertex.position) + lines[i].origin;
SideVertex sideVertex = new SideVertex();
sideVertex.distance = distance;
sideVertex.vertex = vertex;
sideVertices.Add(sideVertex);
}
}
//计算垂直线段顶点
for (int y = 0; y < high; y++) {
Vector3 a = new Vector3(border.minX - 1, border.minY + y * smooth);
Vector3 b = new Vector3(border.maxX + 1, border.minY + y * smooth);
for (int i = 0; i < lines.Length; i++) {
DataPlateVertex vertex = Compute(a, b, lines[i], smooth, border, grid);
if (vertex == null) { continue; }
float distance = Vector3.Distance(lines[i].a, vertex.position) + lines[i].origin;
SideVertex sideVertex = new SideVertex();
sideVertex.distance = distance;
sideVertex.vertex = vertex;
sideVertices.Add(sideVertex);
}
}
sideVertices.Sort();
List<DataPlateVertex> vertices = new List<DataPlateVertex>();
for (int i = 0; i < sideVertices.Count; i++) {
vertices.Add(sideVertices[i].vertex);
}
//side.vertices = vertices.ToArray();
}
/// <summary> 向网格写入边缘顶点数据 </summary>
private DataPlateVertex Compute(Vector3 a, Vector3 b, DataPlateLine line, float smooth, DataBorder border, GridTool<DataPlateVertex> grid) {
//计算交点
if (!TryGetIntersectPoint(a, b, line.a, line.b, out Vector3 IntersectPoint)) { return null; }
//计算顶点xy
Vector3 offset = new Vector3(smooth, smooth, 0) * 0.3f;
Vector3 position = IntersectPoint - border.MinPoint + offset;
int vertexX = Mathf.FloorToInt(position.x / smooth);
int vertexY = Mathf.FloorToInt(position.y / smooth);
//填充数据
DataPlateVertex vertex = grid.Get(vertexX, vertexY);
vertex.isValid = true;
vertex.position = IntersectPoint;
return vertex;
}
public class SideVertex : IComparable<SideVertex> {
public float distance;
public DataPlateVertex vertex;
public int CompareTo(SideVertex other) {
return other.distance >= distance ? 1 : -1;
}
}
/// <summary> 转角法查询位置是否在板片内 </summary>
public static bool FindPlateInside(Vector3[] points, Vector3 position) {
double angles = 0;
for (int i = 0; i < points.Length; i++) {
Vector3 a = points.LoopIndex(i + 0) - position;
Vector3 b = points.LoopIndex(i + 1) - position;
float angle = Vector2.SignedAngle(a, b);
angles += angle;
}
int normal = (int)(angles * 1000);
return normal > 1000;
}
/// <summary>
/// 计算AB与CD两条线段的交点.
/// </summary>
/// <param name="a">A点</param>
/// <param name="b">B点</param>
/// <param name="c">C点</param>
/// <param name="d">D点</param>
/// <param name="intersectPos">AB与CD的交点</param>
/// <returns>是否相交 true:相交 false:未相交</returns>
private bool TryGetIntersectPoint(Vector3 a, Vector3 b, Vector3 c, Vector3 d, out Vector3 intersectPos) {
intersectPos = Vector3.zero;
Vector3 ab = b - a;
Vector3 ca = a - c;
Vector3 cd = d - c;
Vector3 v1 = Vector3.Cross(ca, cd);
// 不共面
if (Mathf.Abs(Vector3.Dot(v1, ab)) > 1e-6) { return false; }
// 平行
if (Vector3.Cross(ab, cd).sqrMagnitude <= 1e-6) { return false; }
Vector3 ad = d - a;
Vector3 cb = b - c;
// 快速排斥
if (Mathf.Min(a.x, b.x) > Mathf.Max(c.x, d.x) || Mathf.Max(a.x, b.x) < Mathf.Min(c.x, d.x)
|| Mathf.Min(a.y, b.y) > Mathf.Max(c.y, d.y) || Mathf.Max(a.y, b.y) < Mathf.Min(c.y, d.y)
|| Mathf.Min(a.z, b.z) > Mathf.Max(c.z, d.z) || Mathf.Max(a.z, b.z) < Mathf.Min(c.z, d.z)) {
return false;
}
// 跨立试验
if (Vector3.Dot(Vector3.Cross(-ca, ab), Vector3.Cross(ab, ad)) > 0
&& Vector3.Dot(Vector3.Cross(ca, cd), Vector3.Cross(cd, cb)) > 0) {
Vector3 v2 = Vector3.Cross(cd, ab);
float ratio = Vector3.Dot(v1, v2) / v2.sqrMagnitude;
intersectPos = a + ab * ratio;
return true;
}
return false;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e8b300a54238da848b5628cef749aeb2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -11,6 +11,32 @@ public class UnitAlgorithmBezier : UnitAlgorithm<DataPlate> {
/// <summary> 贝塞尔算法 </summary> /// <summary> 贝塞尔算法 </summary>
public UnitAlgorithmBezier() { } public UnitAlgorithmBezier() { }
public void Compute(DataPlate data) {
List<Vector3> points = new List<Vector3>();
for (int i = 0; i < data.plateSides.Count; i++) {
Compute(data.plateSides[i]);
//points.AddRange(data.plateSides[i].positions);
}
//去除重复边缘点
points = points.Distinct().ToList();
//data.edgePoints = points;
}
public void Compute(DataPlateSide data) {
DataBezier dataBezier = new DataBezier();
dataBezier.bezier = data.bezier;
//dataBezier.smooth = data.plate.smooth;
dataBezier.aPoint = data.aPoint.position;
dataBezier.bPoint = data.bPoint.position;
dataBezier.aBezier = data.aBezier;
dataBezier.bBezier = data.bBezier;
dataBezier.Compute();
//data.length = dataBezier.length;
//data.positions = dataBezier.positions.ToArray();
//data.lines = dataBezier.lines.ToArray();
}
public class DataBezier { public class DataBezier {
//输入 //输入
public float smooth; public float smooth;
@@ -22,97 +48,57 @@ public class UnitAlgorithmBezier : UnitAlgorithm<DataPlate> {
//输出 //输出
public float length; public float length;
public List<Vector3> positions = new List<Vector3>(); public List<Vector3> positions = new List<Vector3>();
public List<DataLine> lines = new List<DataLine>(); public List<DataPlateLine> lines = new List<DataPlateLine>();
} /// <summary> 计算曲线细分点 </summary>
public void Compute() {
public void Compute(DataPlate data) { //细分点
List<Vector3> points = new List<Vector3>(); if (bezier == Bezier.) { positions = new List<Vector3> { aPoint, bPoint }; }
for (int i = 0; i < data.sides.Count; i++) { if (bezier == Bezier.) { positions = Compute(aPoint, aBezier, bPoint); }
Compute(data.sides[i]); if (bezier == Bezier.) { positions = Compute(aPoint, aBezier, bBezier, bPoint); }
points.AddRange(data.sides[i].positions); //线段
lines = new List<DataPlateLine>();
for (int i = 0; i < positions.Count - 1; i++) {
DataPlateLine line = new DataPlateLine();
line.a = positions.LoopIndex(i + 0);
line.b = positions.LoopIndex(i + 1);
line.origin = length;
lines.Add(line);
length += line.Distance;
}
} }
//去除重复边缘点 /// <summary> 二阶贝塞尔线段 </summary>
points = points.Distinct().ToList(); private List<Vector3> Compute(Vector3 a, Vector3 b, Vector3 c) {
data.edgePoints = points; List<Vector3> points = new List<Vector3>();
} //方向,距离
public void Compute(DataSide data) { float distance = Vector2.Distance(c, a);
DataBezier dataBezier = new DataBezier(); //求余,得商数
dataBezier.bezier = data.bezier; int quotient = Quotient(distance, smooth);
dataBezier.smooth = data.plate.smooth; //贝塞尔曲线点
dataBezier.aPoint = data.aPoint.position; for (int i = 0; i < quotient; i++) {
dataBezier.bPoint = data.bPoint.position; float t = i * (distance / quotient) / distance;
dataBezier.aBezier = data.aBezier; Vector2 position = ComputeBezier(a, b, c, t);
dataBezier.bBezier = data.bBezier; points.Add(position);
}
Compute(dataBezier); points.Add(c);
return points;
data.length = dataBezier.length;
data.positions = dataBezier.positions.ToArray();
data.lines = dataBezier.lines.ToArray();
}
/// <summary> 计算曲线细分点 </summary>
private void Compute(DataBezier data) {
//细分点
if (data.bezier == Bezier.) {
data.positions = Compute(data.aPoint, data.bPoint);
} }
if (data.bezier == Bezier.) { /// <summary> 三阶贝塞尔线段 </summary>
data.positions = Compute(data.aPoint, data.aBezier, data.bPoint, data.smooth); private List<Vector3> Compute(Vector3 a, Vector3 b, Vector3 c, Vector3 d) {
List<Vector3> points = new List<Vector3>();
//方向,距离
Vector2 direction = (d - a).normalized;
float distance = Vector2.Distance(d, a);
//求余,得商数
int quotient = Quotient(distance, smooth);
//贝塞尔曲线点
for (int i = 0; i < quotient; i++) {
float t = i * (distance / quotient) / distance;
Vector2 position = ComputeBezier(a, b, c, d, t);
points.Add(position);
}
points.Add(d);
return points;
} }
if (data.bezier == Bezier.) {
data.positions = Compute(data.aPoint, data.aBezier, data.bBezier, data.bPoint, data.smooth);
}
//线段
data.lines = new List<DataLine>();
float origin = 0;
for (int i = 0; i < data.positions.Count - 1; i++) {
DataLine line = new DataLine();
line.a = data.positions.LoopIndex(i + 0);
line.b = data.positions.LoopIndex(i + 1);
line.origin = origin;
data.lines.Add(line);
data.length += line.Distance;
origin += line.Distance;
}
}
/// <summary> 二阶贝塞尔线段 </summary>
private List<Vector3> Compute(Vector3 aPoint, Vector3 bPoint) {
return new List<Vector3> { aPoint, bPoint };
}
/// <summary> 二阶贝塞尔线段 </summary>
private List<Vector3> Compute(Vector3 a, Vector3 b, Vector3 c, float smooth) {
List<Vector3> points = new List<Vector3>();
//方向,距离
Vector2 direction = (c - a).normalized;
float distance = Vector2.Distance(c, a);
//求余,得商数
int quotient = Quotient(distance, smooth);
//贝塞尔曲线点
for (int i = 0; i < quotient; i++) {
float t = i * (distance / quotient) / distance;
Vector2 position = ComputeBezier(a, b, c, t);
points.Add(position);
}
points.Add(c);
return points;
}
/// <summary> 三阶贝塞尔线段 </summary>
private List<Vector3> Compute(Vector3 a, Vector3 b, Vector3 c, Vector3 d, float smooth) {
List<Vector3> points = new List<Vector3>();
//方向,距离
Vector2 direction = (d - a).normalized;
float distance = Vector2.Distance(d, a);
//求余,得商数
int quotient = Quotient(distance, smooth);
//贝塞尔曲线点
for (int i = 0; i < quotient; i++) {
float t = i * (distance / quotient) / distance;
Vector2 position = ComputeBezier(a, b, c, d, t);
points.Add(position);
}
points.Add(d);
return points;
} }
/// <summary> 商数 </summary> /// <summary> 商数 </summary>
@@ -1,28 +1,35 @@
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using UnityEngine; using UnityEngine;
/// <summary> /// <summary>
/// 散点边界算法 /// 散点边界算法
/// </summary> /// </summary>
public class UnitAlgorithmBorder : UnitAlgorithm<DataPlate> { public class UnitAlgorithmBorder : UnitAlgorithm<DataPlateBaking> {
/// <summary> 散点边界算法 </summary> /// <summary> 散点边界算法 </summary>
public UnitAlgorithmBorder() { } public UnitAlgorithmBorder() { }
public void Compute(DataPlate plate) { public void Compute(DataPlateBaking plateBaking) {
List<Vector3> edgePoints = new List<Vector3>(plate.edgePoints); //List<DataPlateSide> plateSides = plateBaking.plate.plateSides;
plate.border = Border(edgePoints);
//List<Vector3> points = new List<Vector3>();
//for (int i = 0; i < plateSides.Count; i++) {
// points.AddRange(plateSides[i].dataBaking.positions);
//}
//plateBaking.border = Border(points.Distinct().ToArray());
} }
public static DataBorder Border(List<Vector3> points) { public static DataBorder Border(Vector3[] points) {
float minX = 0; float minY = 0; float minX = 0; float minY = 0;
float maxX = 0; float maxY = 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 < minX) { minX = points[i].x; }
if (points[i].x > maxX) { maxX = 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 < minY) { minY = points[i].y; }
if (points[i].y > maxY) { maxY = points[i].y; } if (points[i].y > maxY) { maxY = points[i].y; }
} }
return new DataBorder(minX, maxX, minY, maxY); return new DataBorder(minX, maxX, minY, maxY, points);
} }
} }
@@ -6,7 +6,7 @@ using UnityEngine;
/// <summary> /// <summary>
/// 多边形耳切法 /// 多边形耳切法
/// </summary> /// </summary>
public class UnitAlgorithmEarCutting : UnitAlgorithm<DataPlate> { public class UnitAlgorithmEarCutting : UnitAlgorithm<DataPlateDesign> {
/// <summary> 多边形耳切法 </summary> /// <summary> 多边形耳切法 </summary>
public UnitAlgorithmEarCutting() { } public UnitAlgorithmEarCutting() { }
@@ -17,27 +17,27 @@ public class UnitAlgorithmEarCutting : UnitAlgorithm<DataPlate> {
public Vector3 cPoint;//+1 public Vector3 cPoint;//+1
} }
public void Compute(DataPlate data) { public void Compute(DataPlateDesign plateDesign) {
List<Vector3> points = new List<Vector3>(data.edgePoints); List<Vector3> points = new List<Vector3>(plateDesign.points);
//判断散列点排序方向 //判断散列点排序方向
Vector3[] allArray = points.ToArray(); Vector3[] allPoints = plateDesign.points;
bool isClockWise = IsClockWise(allArray); bool isClockWise = IsClockWise(allPoints);
//耳切法生成三角形 //耳切法生成三角形
List<DataTriangle> triangles = new List<DataTriangle>(); List<DataTriangle> triangles = new List<DataTriangle>();
ComputeAuriculare(triangles, points, allArray, isClockWise); ComputeAuriculare(triangles, points, allPoints, isClockWise);
data.triangles = triangles; plateDesign.triangles = triangles;
} }
#region #region
/// <summary> 循环计算有效的耳点 </summary> /// <summary> 循环计算有效的耳点 </summary>
public static void ComputeAuriculare(List<DataTriangle> triangles, List<Vector3> edgePoints, Vector3[] allArray, bool isClockWise) { public static void ComputeAuriculare(List<DataTriangle> triangles, List<Vector3> edgePoints, Vector3[] allPoints, bool isClockWise) {
List<DataTriangle> temp = ComputeAuriculare(edgePoints, allArray, isClockWise); List<DataTriangle> temp = ComputeAuriculare(edgePoints, allPoints, isClockWise);
if (temp.Count == 0) { return; } if (temp.Count == 0) { return; }
triangles.AddRange(temp); triangles.AddRange(temp);
ComputeAuriculare(triangles, edgePoints, allArray, isClockWise); ComputeAuriculare(triangles, edgePoints, allPoints, isClockWise);
} }
/// <summary> 计算一个有效的耳点 </summary> /// <summary> 计算一个有效的耳点 </summary>
public static List<DataTriangle> ComputeAuriculare(List<Vector3> edgePoints, Vector3[] allArray, bool isClockWise) { public static List<DataTriangle> ComputeAuriculare(List<Vector3> edgePoints, Vector3[] allPoints, bool isClockWise) {
Vector3[] array = edgePoints.ToArray(); Vector3[] array = edgePoints.ToArray();
List<DataTriangle> polygons = new List<DataTriangle>(); List<DataTriangle> polygons = new List<DataTriangle>();
for (int i = 0; i < array.Length; i++) { for (int i = 0; i < array.Length; i++) {
@@ -45,7 +45,7 @@ public class UnitAlgorithmEarCutting : UnitAlgorithm<DataPlate> {
// 等于180,大于180,不可能为耳点 // 等于180,大于180,不可能为耳点
if (!GetAngleType(auriculare, isClockWise)) { continue; } if (!GetAngleType(auriculare, isClockWise)) { continue; }
// 包含其他点,不可能为耳点 // 包含其他点,不可能为耳点
if (IsInsideTriangle(auriculare, allArray)) { continue; } if (IsInsideTriangle(auriculare, allPoints)) { continue; }
// 包含其他耳点,不可能成为耳点 // 包含其他耳点,不可能成为耳点
if (!IsInsideAuriculare(auriculare, edgePoints)) { continue; } if (!IsInsideAuriculare(auriculare, edgePoints)) { continue; }
edgePoints.Remove(auriculare.aPoint); edgePoints.Remove(auriculare.aPoint);
@@ -35,7 +35,7 @@ public class UnitAlgorithmEdgePoint : UnitAlgorithm<DataPolygon> {
#region #region
/// <summary> 二阶贝塞尔线段 </summary> /// <summary> 二阶贝塞尔线段 </summary>
public List<Vector3> CreateLine(DataPoint aPoint, DataPoint bPoint, Vector3 b, float smooth) { public List<Vector3> CreateLine(DataPlatePoint aPoint, DataPlatePoint bPoint, Vector3 b, float smooth) {
List<Vector3> points = new List<Vector3>(); List<Vector3> points = new List<Vector3>();
//方向,距离 //方向,距离
Vector2 direction = (bPoint.position - aPoint.position).normalized; Vector2 direction = (bPoint.position - aPoint.position).normalized;
@@ -53,7 +53,7 @@ public class UnitAlgorithmEdgePoint : UnitAlgorithm<DataPolygon> {
return points; return points;
} }
/// <summary> 三阶贝塞尔线段 </summary> /// <summary> 三阶贝塞尔线段 </summary>
public List<Vector3> CreateLine(DataPoint aPoint, DataPoint bPoint, float smooth) { public List<Vector3> CreateLine(DataPlatePoint aPoint, DataPlatePoint bPoint, float smooth) {
List<Vector3> points = new List<Vector3>(); List<Vector3> points = new List<Vector3>();
//方向,距离 //方向,距离
Vector2 direction = (bPoint.position - aPoint.position).normalized; Vector2 direction = (bPoint.position - aPoint.position).normalized;
@@ -0,0 +1,239 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;
using UnityEngine;
/// <summary>
/// 贝塞尔算法 边缘细分 Jobs
/// </summary>
public class UnitAlgorithmJobsSideSubdivision : UnitAlgorithm<DataPlateDesign>, UnitAlgorithm<DataPlateBaking> {
/// <summary> 贝塞尔算法 边缘细分 Jobs </summary>
public UnitAlgorithmJobsSideSubdivision() { }
public void Compute(DataPlateDesign plateDesign) {
int count = plateDesign.plate.plateSides.Count;
List<DataPlateSide> plateSides = plateDesign.plate.plateSides;
NativeArray<JobSubdivision> jobSubdivisions = new NativeArray<JobSubdivision>(count, Allocator.TempJob);
NativeArray<JobHandle> jobHandles = new NativeArray<JobHandle>(count, Allocator.TempJob);
//创建作业任务
for (int i = 0; i < count; i++) {
jobSubdivisions[i] = ToJob(plateSides[i]);
jobHandles[i] = jobSubdivisions[i].Schedule();
}
//执行作业
JobHandle.CompleteAll(jobHandles);
//作业结果转换
List<Vector3> points = new List<Vector3>();
for (int i = 0; i < count; i++) {
DataPlateSideDesign design = plateSides[i].dataDesign;
JobToDesign(design, jobSubdivisions[i]);
points.AddRange(design.positions);
}
plateDesign.points = points.Distinct().ToArray();
//释放作业
jobSubdivisions.Dispose();
jobHandles.Dispose();
}
public void Compute(DataPlateBaking plateBaking) {
//int count = plateBaking.plate.plateSides.Count;
//List<DataPlateSide> plateSides = plateBaking.plate.plateSides;
//NativeArray<JobSubdivision> jobSubdivisions = new NativeArray<JobSubdivision>(count, Allocator.Temp);
//NativeArray<JobHandle> jobHandles = new NativeArray<JobHandle>(count, Allocator.Temp);
////创建作业任务
//for (int i = 0; i < count; i++) {
// jobSubdivisions[i] = ToJob(plateSides[i]);
// jobHandles[i] = jobSubdivisions[i].Schedule();
//}
////执行作业
//JobHandle.CompleteAll(jobHandles);
////作业结果转换
////List<Vector3> points = new List<Vector3>();
//for (int i = 0; i < count; i++) {
// DataPlateSideBaking sideBaking = plateSides[i].dataBaking;
// JobToBaking(sideBaking, jobSubdivisions[i]);
// //points.AddRange(sideBaking.positions);
//}
////plateBaking.points = points.Distinct().ToArray();
}
/// <summary> 转换作业系统数据 </summary>
public JobSubdivision ToJob(DataPlateSide side) {
JobSubdivision jobSubdivision = new JobSubdivision();
jobSubdivision.bezier = side.bezier;
jobSubdivision.aPoint = side.aPoint.position;
jobSubdivision.bPoint = side.bPoint.position;
jobSubdivision.aBezier = side.aBezier;
jobSubdivision.bBezier = side.bBezier;
//距离
float distance = Vector2.Distance(jobSubdivision.aPoint, jobSubdivision.bPoint);
jobSubdivision.distance = distance;
//求余,得商数
jobSubdivision.quotient = side.bezier == Bezier. ? 2 : 10;
jobSubdivision.length = new NativeArray<float>(1, Allocator.TempJob);
jobSubdivision.positions = new NativeArray<Vector3>(jobSubdivision.quotient, Allocator.TempJob);
jobSubdivision.lines = new NativeArray<JobDataLine>(jobSubdivision.quotient - 1, Allocator.TempJob);
return jobSubdivision;
}
/// <summary> 作业系统数据转换设计数据 </summary>
public void JobToDesign(DataPlateSideDesign design, JobSubdivision job) {
design.length = job.length[0];
design.positions = job.positions.ToArray();
DataPlateLine[] lines = new DataPlateLine[job.lines.Length];
for (int i = 0; i < job.lines.Length; i++) {
lines[i] = ToData(job.lines[i]);
}
design.lines = lines;
job.length.Dispose();
job.positions.Dispose();
job.lines.Dispose();
}
/// <summary> 作业系统数据转换烘焙数据 </summary>
public void JobToBaking(DataPlateSideBaking baking, JobSubdivision job) {
baking.length = job.length[0];
baking.positions = job.positions.ToArray();
DataPlateLine[] lines = new DataPlateLine[job.lines.Length];
for (int i = 0; i < job.lines.Length; i++) {
lines[i] = ToData(job.lines[i]);
}
baking.lines = lines;
job.length.Dispose();
job.positions.Dispose();
job.lines.Dispose();
}
/// <summary> 转换托管数据 </summary>
public DataPlateLine ToData(JobDataLine jobDataLine) {
DataPlateLine line = new DataPlateLine();
line.a = jobDataLine.a;
line.b = jobDataLine.b;
line.origin = jobDataLine.origin;
return line;
}
/// <summary> 作业系统数据 </summary>
public struct JobDataLine {
/// <summary> 线段起点a </summary>
public Vector3 a;
/// <summary> 线段终点b </summary>
public Vector3 b;
/// <summary> 原始距离 </summary>
public float origin;
}
[BurstCompile]
public struct JobSubdivision : IJob {
#region
/// <summary> 贝塞尔类型 </summary>
public Bezier bezier;
/// <summary> a点 </summary>
public Vector3 aPoint;
/// <summary> b点 </summary>
public Vector3 bPoint;
/// <summary> a点贝塞尔点 </summary>
public Vector3 aBezier;
/// <summary> b点贝塞尔点 </summary>
public Vector3 bBezier;
/// <summary> a-b距离 </summary>
public float distance;
/// <summary> 细分数 </summary>
public int quotient;
#endregion
#region
/// <summary> 总长度 </summary>
public NativeArray<float> length;
/// <summary> 点 </summary>
public NativeArray<Vector3> positions;
/// <summary> 线 </summary>
public NativeArray<JobDataLine> lines;
#endregion
public void Execute() {
//细分点
if (bezier == Bezier.) { ComputeBezierA(); }
if (bezier == Bezier.) { ComputeBezierB(); }
if (bezier == Bezier.) { ComputeBezierC(); }
//线段
for (int i = 0; i < quotient - 1; i++) {
JobDataLine line = new JobDataLine();
line.a = positions[i];
line.b = positions[i + 1];
line.origin = length[0];
lines[i] = line;
length[0] += Vector3.Distance(line.a, line.b);
}
}
public void ComputeBezierA() {
positions[0] = aPoint;
positions[1] = bPoint;
}
public void ComputeBezierB() {
for (int i = 0; i < quotient; i++) {
float t = i * (distance / quotient) / distance;
Vector2 position = ComputeBezier(aPoint, aBezier, bPoint, t);
positions[i] = position;
}
}
public void ComputeBezierC() {
for (int i = 0; i < quotient; i++) {
float t = i * (distance / quotient) / distance;
Vector2 position = ComputeBezier(aPoint, aBezier, bBezier, bPoint, t);
positions[i] = position;
}
}
}
/// <summary> 商数 </summary>
public static int Quotient(float distance, float smooth) {
int a = (int)(distance * 1000);
int b = (int)(smooth * 1000);
return Math.DivRem(a, b, out int remainder);
}
/// <summary>
/// 一阶贝塞尔算法
/// </summary>
/// <param name="a">起点</param>
/// <param name="b">终点</param>
/// <param name="t">进度</param>
/// <returns></returns>
public static Vector3 ComputeBezier(Vector3 a, Vector3 b, float t) {
return a + (b - a) * t;
}
/// <summary>
/// 二阶贝塞尔算法
/// </summary>
/// <param name="a">起点</param>
/// <param name="b">贝塞尔点</param>
/// <param name="c">终点</param>
/// <param name="t">进度</param>
/// <returns>当前进度的曲线点</returns>
public static Vector3 ComputeBezier(Vector3 a, Vector3 b, Vector3 c, float t) {
Vector3 aa = a + (b - a) * t;
Vector3 bb = b + (c - b) * t;
return aa + (bb - aa) * t;
}
/// <summary>
/// 三阶贝塞尔算法
/// </summary>
/// <param name="a">起点</param>
/// <param name="b">起点的贝塞尔点</param>
/// <param name="c">终点的贝塞尔点</param>
/// <param name="d">终点</param>
/// <param name="t">进度</param>
/// <returns>当前进度的曲线点</returns>
public static Vector3 ComputeBezier(Vector3 a, Vector3 b, Vector3 c, Vector3 d, float t) {
Vector3 aa = a + (b - a) * t;
Vector3 bb = b + (c - b) * t;
Vector3 cc = c + (d - c) * t;
Vector3 aaa = aa + (bb - aa) * t;
Vector3 bbb = bb + (cc - bb) * t;
return aaa + (bbb - aaa) * t;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 39a35ef3408d163469eb7c66d1df96ac
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -10,12 +10,12 @@ using UnityEngine;
/// <summary> /// <summary>
/// 三角形合并网格 /// 三角形合并网格
/// </summary> /// </summary>
public class UnitAlgorithmMergeTriangle : UnitAlgorithm<DataPlate> { public class UnitAlgorithmMergeTriangle : UnitAlgorithm<DataPlateDesign>, UnitAlgorithm<DataPlateBaking> {
/// <summary> 三角形合并网格 </summary> /// <summary> 三角形合并网格 </summary>
public UnitAlgorithmMergeTriangle() { } public UnitAlgorithmMergeTriangle() { }
public void Compute(DataPlate data) { public void Compute(DataPlateDesign plateDesign) {
List<DataTriangle> polygons = data.triangles; List<DataTriangle> polygons = plateDesign.triangles;
//三角形合并 //三角形合并
List<Vector3> vertices = vertices = MergeVertices(polygons); List<Vector3> vertices = vertices = MergeVertices(polygons);
List<int> triangles = JobFindTriangleIndex(polygons, vertices); List<int> triangles = JobFindTriangleIndex(polygons, vertices);
@@ -23,12 +23,28 @@ public class UnitAlgorithmMergeTriangle : UnitAlgorithm<DataPlate> {
List<Vector2> uv = new List<Vector2>(); List<Vector2> uv = new List<Vector2>();
for (int i = 0; i < vertices.Count; i++) { uv.Add(vertices[i]); } for (int i = 0; i < vertices.Count; i++) { uv.Add(vertices[i]); }
//附加数据 //附加数据
data.designMesh = new Mesh(); plateDesign.mesh = new Mesh();
data.designMesh.vertices = vertices.ToArray(); plateDesign.mesh.vertices = vertices.ToArray();
data.designMesh.uv = uv.ToArray(); plateDesign.mesh.uv = uv.ToArray();
data.designMesh.triangles = triangles.ToArray(); plateDesign.mesh.triangles = triangles.ToArray();
data.designMesh.RecalculateBounds(); plateDesign.mesh.RecalculateBounds();
data.designMesh.RecalculateNormals(); plateDesign.mesh.RecalculateNormals();
}
public void Compute(DataPlateBaking plateBaking) {
//List<DataTriangle> polygons = plateBaking.triangles;
////三角形合并
//List<Vector3> vertices = vertices = MergeVertices(polygons);
//List<int> triangles = JobFindTriangleIndex(polygons, vertices);
////展开uv (顶点去掉z坐标就是未缩放的平面UV)
//List<Vector2> uv = new List<Vector2>();
//for (int i = 0; i < vertices.Count; i++) { uv.Add(vertices[i]); }
////附加数据
//plateBaking.mesh = new Mesh();
//plateBaking.mesh.vertices = vertices.ToArray();
//plateBaking.mesh.uv = uv.ToArray();
//plateBaking.mesh.triangles = triangles.ToArray();
//plateBaking.mesh.RecalculateBounds();
//plateBaking.mesh.RecalculateNormals();
} }
/// <summary> 合并顶点 </summary> /// <summary> 合并顶点 </summary>
private List<Vector3> MergeVertices(List<DataTriangle> polygons) { private List<Vector3> MergeVertices(List<DataTriangle> polygons) {
@@ -54,7 +70,7 @@ public class UnitAlgorithmMergeTriangle : UnitAlgorithm<DataPlate> {
triangleIndex.triangles = trianglesArray; triangleIndex.triangles = trianglesArray;
JobHandle dependency = new JobHandle(); JobHandle dependency = new JobHandle();
JobHandle handle = triangleIndex.ScheduleParallel(polygons.Count, 2048, dependency); JobHandle handle = triangleIndex.ScheduleParallel(polygons.Count, 32, dependency);
handle.Complete(); handle.Complete();
List<int> triangles = new List<int>(); List<int> triangles = new List<int>();
@@ -5,55 +5,58 @@ using UnityEngine;
/// <summary> /// <summary>
/// 菱形绘制三角形算法 /// 菱形绘制三角形算法
/// </summary> /// </summary>
public class UnitAlgorithmRhombus : UnitAlgorithm<DataPlate> { public class UnitAlgorithmRhombus : UnitAlgorithm<DataPlateBaking> {
public void Compute(DataPlate data) { public void Compute(DataPlateBaking plateBaking) {
List<DataTriangle> triangles = new List<DataTriangle>(); List<DataTriangle> triangles = new List<DataTriangle>();
data.vertexGrid.Loop((x, y) => { List<DataPlateVertex> vertexs = new List<DataPlateVertex>();
DataVertex vertex = data.vertexGrid.Get(x, y); //plateBaking.grid.Loop((x, y) => {
if (!vertex.isValid) { return; } // DataPlateVertex vertex = plateBaking.grid.Get(x, y);
// if (!vertex.isValid) { return; }
TryGet(data.vertexGrid, x, y + 1, ref vertex.above); // TryGet(plateBaking.grid, x, y + 1, ref vertex.above);
TryGet(data.vertexGrid, x, y - 1, ref vertex.below); // TryGet(plateBaking.grid, x, y - 1, ref vertex.below);
TryGet(data.vertexGrid, x - 1, y, ref vertex.left); // TryGet(plateBaking.grid, x - 1, y, ref vertex.left);
TryGet(data.vertexGrid, x + 1, y, ref vertex.right); // TryGet(plateBaking.grid, x + 1, y, ref vertex.right);
TryGet(data.vertexGrid, x - 1, y + 1, ref vertex.leftAbove); // TryGet(plateBaking.grid, x - 1, y + 1, ref vertex.leftAbove);
TryGet(data.vertexGrid, x - 1, y - 1, ref vertex.leftBelow); // TryGet(plateBaking.grid, x - 1, y - 1, ref vertex.leftBelow);
TryGet(data.vertexGrid, x + 1, y + 1, ref vertex.rightAbove); // TryGet(plateBaking.grid, x + 1, y + 1, ref vertex.rightAbove);
TryGet(data.vertexGrid, x + 1, y - 1, ref vertex.rightBelow); // TryGet(plateBaking.grid, x + 1, y - 1, ref vertex.rightBelow);
//默认绘制左上角 // //默认绘制左上角
if (vertex.above != null && vertex.left != null) { // if (vertex.above != null && vertex.left != null) {
triangles.Add(CreateDataTriangle(vertex, vertex.left, vertex.above)); // triangles.Add(CreateDataTriangle(vertex, vertex.left, vertex.above));
} // }
//默认绘制右下角 // //默认绘制右下角
if (vertex.below != null && vertex.right != null) { // if (vertex.below != null && vertex.right != null) {
triangles.Add(CreateDataTriangle(vertex, vertex.right, vertex.below)); // triangles.Add(CreateDataTriangle(vertex, vertex.right, vertex.below));
} // }
//如果右上角点不存在,则尝试绘制右上角 // //如果右上角点不存在,则尝试绘制右上角
if (vertex.rightAbove == null && vertex.above != null && vertex.right != null) { // if (vertex.rightAbove == null && vertex.above != null && vertex.right != null) {
triangles.Add(CreateDataTriangle(vertex, vertex.above, vertex.right)); // triangles.Add(CreateDataTriangle(vertex, vertex.above, vertex.right));
} // }
//如果左下角点不存在,则尝试绘制左下角 // //如果左下角点不存在,则尝试绘制左下角
if (vertex.leftBelow == null && vertex.below != null && vertex.left != null) { // if (vertex.leftBelow == null && vertex.below != null && vertex.left != null) {
triangles.Add(CreateDataTriangle(vertex, vertex.below, vertex.left)); // triangles.Add(CreateDataTriangle(vertex, vertex.below, vertex.left));
} // }
}); // vertexs.Add(vertex);
data.triangles = triangles; //});
//plateBaking.triangles = triangles;
//plateBaking.vertexs = vertexs.ToArray();
} }
/// <summary> 校验性获取网格上的点 </summary> /// <summary> 校验性获取网格上的点 </summary>
private void TryGet(GridTool<DataVertex> grid, int x, int y, ref DataVertex vertex) { private void TryGet(GridTool<DataPlateVertex> grid, int x, int y, ref DataPlateVertex vertex) {
vertex = null; 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; } if (data.isValid) { vertex = data; }
} }
/// <summary> 创建三角形 </summary> /// <summary> 创建三角形 </summary>
private DataTriangle CreateDataTriangle(DataVertex a, DataVertex b, DataVertex c) { private DataTriangle CreateDataTriangle(DataPlateVertex a, DataPlateVertex b, DataPlateVertex c) {
DataTriangle triangle = new DataTriangle(); DataTriangle triangle = new DataTriangle();
triangle.b = a.design; triangle.b = a.position;
triangle.c = b.design; triangle.c = b.position;
triangle.a = c.design; triangle.a = c.position;
return triangle; return triangle;
} }
} }
@@ -0,0 +1,64 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 烘焙的缝合线
/// </summary>
public class UnitAlgorithmSutureBaking : UnitAlgorithm<DataSutureSide> {
/// <summary> 烘焙的缝合线 </summary>
public UnitAlgorithmSutureBaking() { }
public void Compute(DataSutureSide sutureSide) {
AllVertexs(sutureSide);
//缝合范围内的顶点
SetVertex(sutureSide);
//顶点转换位置
SetPositions(sutureSide);
}
/// <summary> 顶点距离数据 </summary>
private List<DataSutureSideVertex> GetVertex(DataPlateVertex[] vertexsArray, bool isReversal) {
float length = 0;
List<DataSutureSideVertex> vertexs = new List<DataSutureSideVertex>();
List<DataPlateVertex> sideVertexs = new List<DataPlateVertex>(vertexsArray);
if (isReversal) { sideVertexs.Reverse(); }
for (int i = 0; i < sideVertexs.Count - 1; i++) {
DataSutureSideVertex vertex = new DataSutureSideVertex(length, sideVertexs[i], sideVertexs[i + 1]);
vertexs.Add(vertex); length += vertex.Distance;
}
return vertexs;
}
/// <summary> 全部顶点 </summary>
private void AllVertexs(DataSutureSide sutureSide) {
DataPlateVertex[] vertexsArray = sutureSide.plateSide.dataBaking.vertexs;
List<DataSutureSideVertex> allVertexs = GetVertex(vertexsArray, false);
sutureSide.dataBaking.allVertexs = allVertexs.ToArray();
}
/// <summary> 缝合范围内的顶点 </summary>
private void SetVertex(DataSutureSide sutureSide) {
//全部顶点
List<DataSutureSideVertex> allVertexs = GetVertex(sutureSide.plateSide.dataBaking.vertexs, sutureSide.isReversal);
//缝合范围内的顶点
float maxLength = sutureSide.suture.length;
List<DataSutureSideVertex> vertexs = new List<DataSutureSideVertex>();
for (int i = 0; i < allVertexs.Count; i++) {
if (allVertexs[i].origin <= maxLength) { vertexs.Add(allVertexs[i]); }
}
sutureSide.dataBaking.vertexs = vertexs.ToArray();
}
/// <summary> 顶点转换位置 </summary>
private void SetPositions(DataSutureSide sutureSide) {
Vector3 platePosition = sutureSide.plateSide.plate.dataBaking.position;
Vector3 plateEulerAngles = sutureSide.plateSide.plate.dataBaking.eulerAngles;
List<Vector3> positions = new List<Vector3>();
DataSutureSideVertex[] vertexs = sutureSide.dataBaking.vertexs;
for (int i = 0; i < vertexs.Length; i++) {
Quaternion quaternion = Quaternion.Euler(plateEulerAngles);
Vector3 baking = quaternion * vertexs[i].a.position;
Vector3 position = baking + platePosition;
positions.Add(position);
}
sutureSide.dataBaking.positions = positions.ToArray();
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9735cc247f76e0b42b50f8b7956d3c8a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,52 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 设计的缝合线
/// </summary>
public class UnitAlgorithmSutureDesign : UnitAlgorithm<DataSutureSide> {
/// <summary> 设计的缝合线 </summary>
public UnitAlgorithmSutureDesign() { }
public class Line {
public float origin;
public Vector3 a;
public Vector3 b;
public Line(float origin, Vector3 a, Vector3 b) {
this.origin = origin;
this.a = a;
this.b = b;
}
public float Distance => Vector3.Distance(a, b);
}
public void Compute(DataSutureSide sutureSide) {
float maxLength = sutureSide.suture.length;
Vector3 platePosition = sutureSide.plateSide.plate.dataDesign.position;
List<Vector3> sidePositions = new List<Vector3>(sutureSide.plateSide.dataDesign.positions);
float length = 0;
List<Line> lines = new List<Line>();
if (sutureSide.isReversal) { sidePositions.Reverse(); }
for (int i = 0; i < sidePositions.Count - 1; i++) {
Line line = new Line(length, sidePositions[i], sidePositions[i + 1]);
lines.Add(line);
length += line.Distance;
}
List<Vector3> positions = new List<Vector3>();
for (int i = 0; i < lines.Count; i++) {
Line line = lines[i];
if (line.origin < maxLength) { positions.Add(line.a + platePosition); }
float nextDistance = line.origin + line.Distance;
if (nextDistance < maxLength) { continue; }
if (nextDistance == maxLength) { positions.Add(line.b + platePosition); break; }
float distance = maxLength - line.origin;
Vector3 direction = (line.b - line.a).normalized;
Vector3 position = line.a + direction * distance;
positions.Add(position + platePosition);
break;
}
sutureSide.dataDesign.positions = positions.ToArray();
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b98adb17aebd36b4ab5dfe90020fb902
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -6,97 +6,95 @@ using UnityEngine;
/// <summary> /// <summary>
/// 顶点算法 /// 顶点算法
/// </summary> /// </summary>
public class UnitAlgorithmVertex : UnitAlgorithm<DataPlate> { public class UnitAlgorithmVertex : UnitAlgorithm<DataPlateBaking> {
public class SideVertex : IComparable<SideVertex> { public class SideVertex : IComparable<SideVertex> {
public float distance; public float distance;
public DataVertex vertex; public Vector3 position;
public int CompareTo(SideVertex other) { 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) { public void Compute(DataPlateBaking plateBaking) {
float smooth = data.smooth; DataBorder border = plateBaking.border;
DataBorder border = data.border; Vector3[] points = border.points;
List<Vector3> edgePoints = new List<Vector3>(data.edgePoints);
int wide = Mathf.FloorToInt(border.Wide / smooth) + 1;
int high = Mathf.FloorToInt(border.High / smooth) + 1;
//计算内部顶点 //计算内部顶点
data.vertexGrid = new GridTool<DataVertex>(wide, high, (x, y) => { //plateBaking.grid = new GridTool<DataPlateVertex>(border.GridWide, border.GridHigh, (x, y) => {
Vector3 position = border.MinPoint + new Vector3(x * smooth, y * smooth); // Vector3 position = new Vector3(x, y) * border.smooth + border.MinPoint;
DataVertex vertex = new DataVertex(); // DataPlateVertex vertex = new DataPlateVertex();
vertex.isValid = FindPlateInside(edgePoints, position); // vertex.isValid = FindPlateInside(points, position);
vertex.design = position; // vertex.position = position;
return vertex; // return vertex;
}); //});
//边缘所有的线段 //边缘所有的线段
for (int i = 0; i < data.sides.Count; i++) { //List<DataPlateSide> plateSides = plateBaking.plate.plateSides;
Compute(data.sides[i], wide, high, border, smooth, data.vertexGrid); //for (int i = 0; i < plateSides.Count; i++) {
} // SubdivideSideVertex(plateBaking, plateSides[i]);
//}
} }
/// <summary> 向网格和边缘写入顶点数据 </summary> private void SubdivideSideVertex(DataPlateBaking plateBaking, DataPlateSide plateSides) {
private void Compute(DataSide side, int wide, int high, DataBorder border, float smooth, GridTool<DataVertex> grid) { DataBorder border = plateBaking.border;
DataLine[] lines = side.lines; DataPlateLine[] lines = plateSides.dataBaking.lines;
List<SideVertex> sideVertices = new List<SideVertex>();
//计算水平线段顶点 //计算水平线段顶点
for (int x = 0; x < wide; x++) { List<SideVertex> sideVertexs = new List<SideVertex>();
Vector3 a = new Vector3(border.minX + x * smooth, border.minY - 1); for (int x = 0; x < border.GridWide; x++) {
Vector3 b = new Vector3(border.minX + x * smooth, border.maxY + 1); 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++) { for (int i = 0; i < lines.Length; i++) {
DataVertex vertex = Compute(a, b, lines[i], smooth, border, grid); if (!TryGetIntersectPoint(a, b, lines[i].a, lines[i].b, out Vector3 IntersectPoint)) { continue; }
if (vertex == null) { continue; } float distance = Vector3.Distance(lines[i].a, IntersectPoint) + lines[i].origin;
float distance = Vector3.Distance(lines[i].a, vertex.design) + lines[i].origin;
SideVertex sideVertex = new SideVertex(); SideVertex sideVertex = new SideVertex();
sideVertex.distance = distance; sideVertex.distance = distance;
sideVertex.vertex = vertex; sideVertex.position = IntersectPoint;
sideVertices.Add(sideVertex); sideVertexs.Add(sideVertex);
} }
} }
//计算垂直线段顶点 //计算垂直线段顶点
for (int y = 0; y < high; y++) { for (int y = 0; y < border.GridHigh; y++) {
Vector3 a = new Vector3(border.minX - 1, border.minY + y * smooth); Vector3 a = new Vector3(border.minX - 1, border.minY + y * border.smooth);
Vector3 b = new Vector3(border.maxX + 1, border.minY + y * smooth); Vector3 b = new Vector3(border.maxX + 1, border.minY + y * border.smooth);
for (int i = 0; i < lines.Length; i++) { for (int i = 0; i < lines.Length; i++) {
DataVertex vertex = Compute(a, b, lines[i], smooth, border, grid); if (!TryGetIntersectPoint(a, b, lines[i].a, lines[i].b, out Vector3 IntersectPoint)) { continue; }
if (vertex == null) { continue; } float distance = Vector3.Distance(lines[i].a, IntersectPoint) + lines[i].origin;
float distance = Vector3.Distance(lines[i].a, vertex.design) + lines[i].origin;
SideVertex sideVertex = new SideVertex(); SideVertex sideVertex = new SideVertex();
sideVertex.distance = distance; sideVertex.distance = distance;
sideVertex.vertex = vertex; sideVertex.position = IntersectPoint;
sideVertices.Add(sideVertex); sideVertexs.Add(sideVertex);
} }
} }
sideVertices.Sort(); //排序
List<DataVertex> vertices = new List<DataVertex>(); sideVertexs.Sort();
for (int i = 0; i < sideVertices.Count; i++) { //写入网格,写入顶点
vertices.Add(sideVertices[i].vertex); Vector3 offset = border.MinPoint - new Vector3(border.smooth, border.smooth, 0) * 0.3f;
List<DataPlateVertex> vertexs = new List<DataPlateVertex>();
for (int i = 0; i < sideVertexs.Count; i++) {
Vector3 position = sideVertexs[i].position;
Vector3 gridPosition = position - offset;
int vertexX = Mathf.FloorToInt(gridPosition.x / border.smooth);
int vertexY = Mathf.FloorToInt(gridPosition.y / border.smooth);
//填充数据
//DataPlateVertex vertex = plateBaking.grid.Get(vertexX, vertexY);
//vertex.isValid = true;
//vertex.position = position;
////写入顶点
//vertexs.Add(vertex);
} }
side.vertices = vertices.ToArray(); plateSides.dataBaking.vertexs = vertexs.ToArray();
}
/// <summary> 向网格写入边缘顶点数据 </summary>
private DataVertex Compute(Vector3 a, Vector3 b, DataLine line, float smooth, DataBorder border, GridTool<DataVertex> grid) {
//计算交点
if (!TryGetIntersectPoint(a, b, line.a, line.b, out Vector3 IntersectPoint)) { return null; }
//计算顶点xy
Vector3 offset = new Vector3(smooth, smooth, 0) * 0.3f;
Vector3 position = IntersectPoint - border.MinPoint + offset;
int vertexX = Mathf.FloorToInt(position.x / smooth);
int vertexY = Mathf.FloorToInt(position.y / smooth);
//填充数据
DataVertex vertex = grid.Get(vertexX, vertexY);
vertex.isValid = true;
vertex.design = IntersectPoint;
return vertex;
} }
/// <summary> 转角法查询位置是否在板片内 </summary> /// <summary> 转角法查询位置是否在板片内 </summary>
public static bool FindPlateInside(List<Vector3> points, Vector3 position) { public static bool FindPlateInside(Vector3[] points, Vector3 position) {
double angles = 0; 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 a = points.LoopIndex(i + 0) - position;
Vector3 b = points.LoopIndex(i + 1) - position; Vector3 b = points.LoopIndex(i + 1) - position;
float angle = Vector2.SignedAngle(a, b); float angle = Vector2.SignedAngle(a, b);
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3105cf897e8dcb6408a9d5b207fa348e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,74 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 查询边交点
/// </summary>
public class FindSideIntersectPoint : UnitFind<SideIntersectPoint> {
public readonly float FindRange = 0.01f;
/// <summary> 板片资产 </summary>
public ModuleAssets<DataPlate> AssetsPlate => ModuleCore.I.AssetsPlate;
/// <summary> 查询边交点 </summary>
public FindSideIntersectPoint() { }
public bool Find(Vector3 position, out SideIntersectPoint sip) {
sip = new SideIntersectPoint();
List<DataPlate> 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;
}
/// <summary> 查询匹配的边 </summary>
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;
}
/// <summary> 查询匹配的边 </summary>
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;
}
/// <summary>
/// 向量投影法
/// 计算点c到线段ab最近的点
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <param name="c"></param>
/// <returns>如果不在线段上返回 float.MaxValue</returns>
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);
}
}
/// <summary>
/// 边交点
/// </summary>
public class SideIntersectPoint {
/// <summary> 匹配的边 </summary>
public DataPlateSide side;
/// <summary> 交点 </summary>
public Vector3 intersectPoint;
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 368e1bf20f25d424f8ed16d00323b8b8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+8
View File
@@ -0,0 +1,8 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public interface UnitFind<Data> {
/// <summary> 查询 </summary>
public bool Find(Vector3 position, out Data data);
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 77073523d35e8fb4bb758404278690c5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -17,15 +17,15 @@ public class BakingMobilePlate : UnitMouseInput {
if (!ViewCamera.ScreenToWorldObject(data.ScreenPosition, out platePrefab)) { return; } if (!ViewCamera.ScreenToWorldObject(data.ScreenPosition, out platePrefab)) { return; }
mousePosition = data.ScreenPosition; mousePosition = data.ScreenPosition;
originalPosition = platePrefab.transform.localPosition; originalPosition = platePrefab.transform.localPosition;
platePrefab.Value.bakingPosition = originalPosition; platePrefab.Value.dataBaking.position = originalPosition;
ModuleCore.BakingMobilePlate(platePrefab.Value); ModuleCore.BakingMobilePlate(platePrefab.Value);
} }
public override void MouseDrag(DataMouseInput data) { public override void MouseDrag(DataMouseInput data) {
if (platePrefab == null) { return; } if (platePrefab == null) { return; }
if (ViewCamera.ScreenToWorldObjectParent(data.ScreenPosition, out arrange, Arrange)) { if (ViewCamera.ScreenToWorldObjectParent(data.ScreenPosition, out arrange, Arrange)) {
platePrefab.Value.arrange = arrange; platePrefab.Value.arrange = arrange;
platePrefab.Value.bakingPosition = arrange.transform.localPosition; platePrefab.Value.dataBaking.position = arrange.transform.localPosition;
platePrefab.Value.bakingEulerAngles = arrange.transform.localEulerAngles; platePrefab.Value.dataBaking.eulerAngles = arrange.transform.localEulerAngles;
} }
else { Mobile(data.WorldPosition); } else { Mobile(data.WorldPosition); }
platePrefab.Value.UpdateVisual(false); platePrefab.Value.UpdateVisual(false);
@@ -41,6 +41,6 @@ public class BakingMobilePlate : UnitMouseInput {
Vector3 offset = current - original; Vector3 offset = current - original;
Vector3 up = ViewCamera.Up * offset.y; Vector3 up = ViewCamera.Up * offset.y;
Vector3 right = ViewCamera.Right * offset.x; Vector3 right = ViewCamera.Right * offset.x;
platePrefab.Value.bakingPosition = originalPosition - up - right; platePrefab.Value.dataBaking.position = originalPosition - up - right;
} }
} }
@@ -6,10 +6,10 @@ public class DesignBezier : UnitMouseInput {
/// <summary> 设计视图相机模块 </summary> /// <summary> 设计视图相机模块 </summary>
public ModuleViewCamera ViewCamera => ModuleCore.ViewCameraDesign; public ModuleViewCamera ViewCamera => ModuleCore.ViewCameraDesign;
/// <summary> 查询点算法模块 </summary> /// <summary> 查询点算法模块 </summary>
public ModuleFind<DataSide> FindSide => ModuleCore.FindSide; public ModuleFind<DataPlateSide> FindSide => ModuleCore.FindSide;
public override void MouseDown(DataMouseInput data) { 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.TwoRankBezier(); side.plate.UpdateVisual(); return; }
if (side.bezier == Bezier.) { side.ThreeRankBezier(); side.plate.UpdateVisual(); return; } if (side.bezier == Bezier.) { side.ThreeRankBezier(); side.plate.UpdateVisual(); return; }
if (side.bezier == Bezier.) { side.OneRankBezier(); side.plate.UpdateVisual(); return; } if (side.bezier == Bezier.) { side.OneRankBezier(); side.plate.UpdateVisual(); return; }
@@ -3,28 +3,33 @@ using System.Collections.Generic;
using UnityEngine; using UnityEngine;
public class DesignInsert : UnitMouseInput { public class DesignInsert : UnitMouseInput {
/// <summary> 板片资产 </summary> /// <summary> 查询边交点 </summary>
public ModuleAssets<DataPlate> AssetsPlate => ModuleCore.AssetsPlate; public UnitFind<SideIntersectPoint> find = new FindSideIntersectPoint();
/// <summary> 查询边算法模块 </summary>
public ModuleFind<DataSide> FindSide => ModuleCore.FindSide;
/// <summary> 计算位置到边上最近的点 </summary>
public ModuleAlgorithm<DataIntersect> AlgorithmSidePoint => ModuleCore.AlgorithmSidePoint;
/// <summary> 插入点数据转换板片上的点 </summary>
public ModuleBuilder<DataInsertPoint, DataPoint> InsertPointToPoint => ModuleCore.InsertPointToPoint;
public override void MouseDown(DataMouseInput data) { 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); private void Insert(DataPlateSide side, DataPlate plate, DataPlatePoint aPoint, DataPlatePoint bPoint, Vector3 position) {
AlgorithmSidePoint.Compute(intersect); //创建新的点
if (!intersect.isIntersect) { return; } DataPlatePoint newPoint = new DataPlatePoint(plate);
newPoint.position = position - plate.dataDesign.position;
DataInsertPoint insertPoint = new DataInsertPoint(); //改变关联的边B点,重置贝塞尔曲线
insertPoint.position = intersect.intersectPoint - side.plate.designPosition; side.bPoint = newPoint;
insertPoint.plate = side.plate; side.OneRankBezier();
insertPoint.aPoint = side.aPoint; //创建新的边
insertPoint.bPoint = side.bPoint; DataPlateSide newSide = new DataPlateSide(plate);
insertPoint.side = side; newSide.aPoint = newPoint;
InsertPointToPoint.To(insertPoint); 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();
} }
} }
@@ -11,7 +11,7 @@ public class DesignMobile : UnitMouseInput {
private DataBezier bezier; private DataBezier bezier;
private Vector3 mousePosition; private Vector3 mousePosition;
private Vector3 originalPosition; private Vector3 originalPosition;
private ModulePrefab<DataPoint> prefabPoint; private ModulePrefab<DataPlatePoint> prefabPoint;
private ModulePrefab<DataPlate> prefabPlate; private ModulePrefab<DataPlate> prefabPlate;
public override void MouseDown(DataMouseInput data) { public override void MouseDown(DataMouseInput data) {
@@ -61,10 +61,10 @@ public class DesignMobile : UnitMouseInput {
//板片 //板片
private void RecordPlate(Vector3 screenPosition) { private void RecordPlate(Vector3 screenPosition) {
mousePosition = screenPosition; mousePosition = screenPosition;
originalPosition = prefabPlate.Value.designPosition; originalPosition = prefabPlate.Value.dataDesign.position;
} }
private void MobilePlate(Vector3 offset) { private void MobilePlate(Vector3 offset) {
prefabPlate.Value.designPosition = originalPosition + offset; prefabPlate.Value.dataDesign.position = originalPosition + offset;
prefabPlate.Value.UpdateVisual(false); prefabPlate.Value.UpdateVisual(false);
} }
//相机 //相机
@@ -3,29 +3,30 @@ using System.Collections.Generic;
using UnityEngine; using UnityEngine;
public class DesignSuture : UnitMouseInput { public class DesignSuture : UnitMouseInput {
/// <summary> 设计视图相机模块 </summary> /// <summary> 查询边交点 </summary>
public ModuleViewCamera ViewCamera => ModuleCore.ViewCameraDesign; public UnitFind<SideIntersectPoint> find = new FindSideIntersectPoint();
/// <summary> 查询点算法模块 </summary>
public ModuleFind<DataSide> FindSide => ModuleCore.FindSide;
/// <summary> 计算位置到边上最近的点 </summary>
public ModuleAlgorithm<DataIntersect> AlgorithmSidePoint => ModuleCore.AlgorithmSidePoint;
/// <summary> 连接可视化内容生成模块 </summary> /// <summary> 连接可视化内容生成模块 </summary>
public ModuleVisual<DataConnector> VisualConnector => ModuleCore.VisualConnector; public ModuleVisual<DataConnector> VisualConnector => ModuleCore.VisualConnector;
private DataSide aSide; private DataPlateSide aSide;
private DataSide bSide; private DataPlateSide bSide;
private DataConnector connector; private DataConnector connector;
public override void MouseDown(DataMouseInput data) { 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 = new DataConnector();
connector.aPoint = intersectPoint; connector.aPoint = data.WorldPosition;
connector.bPoint = intersectPoint; if (!find.Find(data.WorldPosition, out SideIntersectPoint sip)) { return; }
connector.aPoint = sip.intersectPoint;
aSide = sip.side;
} }
public override void MouseDrag(DataMouseInput data) { public override void MouseDrag(DataMouseInput data) {
if (aSide == null) { return; } if (connector == null) { return; }
connector.bPoint = GetPosition(data); 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); VisualConnector.UpdateVisual(connector);
} }
public override void MouseRelease(DataMouseInput data) { public override void MouseRelease(DataMouseInput data) {
@@ -41,16 +42,16 @@ public class DesignSuture : UnitMouseInput {
aSide.plate.UpdateVisual(); aSide.plate.UpdateVisual();
} }
private Vector3 GetPosition(DataMouseInput data) { //private Vector3 GetPosition(DataMouseInput data) {
if (!FindSide.Find(data.WorldPosition, out bSide)) { return data.WorldPosition; } // if (!FindSide.Find(data.WorldPosition, out bSide)) { return data.WorldPosition; }
if (aSide == bSide) { return data.WorldPosition; } // if (aSide == bSide) { return data.WorldPosition; }
if (Intersect(bSide, data.WorldPosition, out Vector3 intersectPoint)) { return intersectPoint; } // if (Intersect(bSide, data.WorldPosition, out Vector3 intersectPoint)) { return intersectPoint; }
else { return data.WorldPosition; } // else { return data.WorldPosition; }
} //}
private bool Intersect(DataSide side, Vector3 position, out Vector3 intersectPoint) { //private bool Intersect(DataSide side, Vector3 position, out Vector3 intersectPoint) {
DataIntersect intersect = new DataIntersect(side, position); //DataIntersect intersect = new DataIntersect(side, position);
AlgorithmSidePoint.Compute(intersect); //AlgorithmSidePoint.Compute(intersect);
intersectPoint = intersect.intersectPoint; //intersectPoint = intersect.intersectPoint;
return intersect.isIntersect; //return intersect.isIntersect;
} //}
} }
@@ -6,14 +6,14 @@ public class DesignSutureReversal : UnitMouseInput {
/// <summary> 设计视图相机模块 </summary> /// <summary> 设计视图相机模块 </summary>
public ModuleViewCamera ViewCamera => ModuleCore.ViewCameraDesign; public ModuleViewCamera ViewCamera => ModuleCore.ViewCameraDesign;
/// <summary> 查询点算法模块 </summary> /// <summary> 查询点算法模块 </summary>
public ModuleFind<DataSide> FindSide => ModuleCore.FindSide; public ModuleFind<DataPlateSide> FindSide => ModuleCore.FindSide;
public override void MouseDown(DataMouseInput data) { 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.suture.a.side == side) { if (side.suture.a.plateSide == side) {
side.suture.a.isReversal = !side.suture.a.isReversal; 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.suture.b.isReversal = !side.suture.b.isReversal;
} }
side.plate.UpdateVisual(); side.plate.UpdateVisual();
+1
View File
@@ -3,6 +3,7 @@
"com.muhua.tools": "https://github.com/MuHua-123/MuHua-Tools.git?path=Packages/Tools", "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.muhua.uicontrol": "https://github.com/MuHua-123/MuHua-UIControl.git?path=Packages/UIControl",
"com.unity.collab-proxy": "2.5.2", "com.unity.collab-proxy": "2.5.2",
"com.unity.collections": "1.2.4",
"com.unity.feature.development": "1.0.1", "com.unity.feature.development": "1.0.1",
"com.unity.render-pipelines.universal": "14.0.11", "com.unity.render-pipelines.universal": "14.0.11",
"com.unity.textmeshpro": "3.0.6", "com.unity.textmeshpro": "3.0.6",
+10
View File
@@ -30,6 +30,16 @@
"dependencies": {}, "dependencies": {},
"url": "https://packages.unity.cn" "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": { "com.unity.editorcoroutines": {
"version": "1.0.0", "version": "1.0.0",
"depth": 1, "depth": 1,
+17
View File
@@ -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