初始化项目
This commit is contained in:
@@ -1,12 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 单个算法函数
|
||||
/// </summary>
|
||||
/// <typeparam name="Data"></typeparam>
|
||||
public interface UnitAlgorithm<Data> {
|
||||
/// <summary> 执行算法 </summary>
|
||||
public void Compute(Data data);
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 60c99317b7676b6408025f3f6fed9f1a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,151 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e8b300a54238da848b5628cef749aeb2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,151 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 贝塞尔算法
|
||||
/// </summary>
|
||||
public class UnitAlgorithmBezier : UnitAlgorithm<DataPlate> {
|
||||
/// <summary> 贝塞尔算法 </summary>
|
||||
public UnitAlgorithmBezier() { }
|
||||
|
||||
public void Compute(DataPlate data) {
|
||||
List<Vector3> points = new List<Vector3>();
|
||||
for (int i = 0; i < data.plateSides.Count; i++) {
|
||||
Compute(data.plateSides[i]);
|
||||
//points.AddRange(data.plateSides[i].positions);
|
||||
}
|
||||
//去除重复边缘点
|
||||
points = points.Distinct().ToList();
|
||||
//data.edgePoints = points;
|
||||
}
|
||||
public void Compute(DataPlateSide data) {
|
||||
DataBezier dataBezier = new DataBezier();
|
||||
dataBezier.bezier = data.bezier;
|
||||
//dataBezier.smooth = data.plate.smooth;
|
||||
dataBezier.aPoint = data.aPoint.position;
|
||||
dataBezier.bPoint = data.bPoint.position;
|
||||
dataBezier.aBezier = data.aBezier;
|
||||
dataBezier.bBezier = data.bBezier;
|
||||
|
||||
dataBezier.Compute();
|
||||
|
||||
//data.length = dataBezier.length;
|
||||
//data.positions = dataBezier.positions.ToArray();
|
||||
//data.lines = dataBezier.lines.ToArray();
|
||||
}
|
||||
|
||||
public class DataBezier {
|
||||
//输入
|
||||
public float smooth;
|
||||
public Bezier bezier;
|
||||
public Vector3 aPoint;
|
||||
public Vector3 bPoint;
|
||||
public Vector3 aBezier;
|
||||
public Vector3 bBezier;
|
||||
//输出
|
||||
public float length;
|
||||
public List<Vector3> positions = new List<Vector3>();
|
||||
public List<DataPlateLine> lines = new List<DataPlateLine>();
|
||||
/// <summary> 计算曲线细分点 </summary>
|
||||
public void Compute() {
|
||||
//细分点
|
||||
if (bezier == Bezier.一阶) { positions = new List<Vector3> { aPoint, bPoint }; }
|
||||
if (bezier == Bezier.二阶) { positions = Compute(aPoint, aBezier, bPoint); }
|
||||
if (bezier == Bezier.三阶) { positions = Compute(aPoint, aBezier, bBezier, bPoint); }
|
||||
//线段
|
||||
lines = new List<DataPlateLine>();
|
||||
for (int i = 0; i < positions.Count - 1; i++) {
|
||||
DataPlateLine line = new DataPlateLine();
|
||||
line.a = positions.LoopIndex(i + 0);
|
||||
line.b = positions.LoopIndex(i + 1);
|
||||
line.origin = length;
|
||||
lines.Add(line);
|
||||
length += line.Distance;
|
||||
}
|
||||
}
|
||||
/// <summary> 二阶贝塞尔线段 </summary>
|
||||
private List<Vector3> Compute(Vector3 a, Vector3 b, Vector3 c) {
|
||||
List<Vector3> points = new List<Vector3>();
|
||||
//方向,距离
|
||||
float distance = Vector2.Distance(c, a);
|
||||
//求余,得商数
|
||||
int quotient = Quotient(distance, smooth);
|
||||
//贝塞尔曲线点
|
||||
for (int i = 0; i < quotient; i++) {
|
||||
float t = i * (distance / quotient) / distance;
|
||||
Vector2 position = ComputeBezier(a, b, c, t);
|
||||
points.Add(position);
|
||||
}
|
||||
points.Add(c);
|
||||
return points;
|
||||
}
|
||||
/// <summary> 三阶贝塞尔线段 </summary>
|
||||
private List<Vector3> Compute(Vector3 a, Vector3 b, Vector3 c, Vector3 d) {
|
||||
List<Vector3> points = new List<Vector3>();
|
||||
//方向,距离
|
||||
Vector2 direction = (d - a).normalized;
|
||||
float distance = Vector2.Distance(d, a);
|
||||
//求余,得商数
|
||||
int quotient = Quotient(distance, smooth);
|
||||
//贝塞尔曲线点
|
||||
for (int i = 0; i < quotient; i++) {
|
||||
float t = i * (distance / quotient) / distance;
|
||||
Vector2 position = ComputeBezier(a, b, c, d, t);
|
||||
points.Add(position);
|
||||
}
|
||||
points.Add(d);
|
||||
return points;
|
||||
}
|
||||
}
|
||||
|
||||
/// <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;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c59160eac8bcdec48a6b5584c7c91192
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,35 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 散点边界算法
|
||||
/// </summary>
|
||||
public class UnitAlgorithmBorder : UnitAlgorithm<DataPlateBaking> {
|
||||
/// <summary> 散点边界算法 </summary>
|
||||
public UnitAlgorithmBorder() { }
|
||||
|
||||
public void Compute(DataPlateBaking plateBaking) {
|
||||
//List<DataPlateSide> plateSides = plateBaking.plate.plateSides;
|
||||
|
||||
//List<Vector3> points = new List<Vector3>();
|
||||
//for (int i = 0; i < plateSides.Count; i++) {
|
||||
// points.AddRange(plateSides[i].dataBaking.positions);
|
||||
//}
|
||||
|
||||
//plateBaking.border = Border(points.Distinct().ToArray());
|
||||
}
|
||||
|
||||
public static DataBorder Border(Vector3[] points) {
|
||||
float minX = 0; float minY = 0;
|
||||
float maxX = 0; float maxY = 0;
|
||||
for (int i = 0; i < points.Length; i++) {
|
||||
if (points[i].x < minX) { minX = points[i].x; }
|
||||
if (points[i].x > maxX) { maxX = points[i].x; }
|
||||
if (points[i].y < minY) { minY = points[i].y; }
|
||||
if (points[i].y > maxY) { maxY = points[i].y; }
|
||||
}
|
||||
return new DataBorder(minX, maxX, minY, maxY, points);
|
||||
}
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 多边形耳切法
|
||||
/// </summary>
|
||||
public class UnitAlgorithmEarCutting : UnitAlgorithm<DataPlateDesign> {
|
||||
/// <summary> 多边形耳切法 </summary>
|
||||
public UnitAlgorithmEarCutting() { }
|
||||
|
||||
public class Auriculare {
|
||||
public int index;
|
||||
public Vector3 aPoint;//+0
|
||||
public Vector3 bPoint;//-1
|
||||
public Vector3 cPoint;//+1
|
||||
}
|
||||
|
||||
public void Compute(DataPlateDesign plateDesign) {
|
||||
List<Vector3> points = new List<Vector3>(plateDesign.points);
|
||||
//判断散列点排序方向
|
||||
Vector3[] allPoints = plateDesign.points;
|
||||
bool isClockWise = IsClockWise(allPoints);
|
||||
//耳切法生成三角形
|
||||
List<DataTriangle> triangles = new List<DataTriangle>();
|
||||
ComputeAuriculare(triangles, points, allPoints, isClockWise);
|
||||
plateDesign.triangles = triangles;
|
||||
}
|
||||
|
||||
#region 函数
|
||||
/// <summary> 循环计算有效的耳点 </summary>
|
||||
public static void ComputeAuriculare(List<DataTriangle> triangles, List<Vector3> edgePoints, Vector3[] allPoints, bool isClockWise) {
|
||||
List<DataTriangle> temp = ComputeAuriculare(edgePoints, allPoints, isClockWise);
|
||||
if (temp.Count == 0) { return; }
|
||||
triangles.AddRange(temp);
|
||||
ComputeAuriculare(triangles, edgePoints, allPoints, isClockWise);
|
||||
}
|
||||
/// <summary> 计算一个有效的耳点 </summary>
|
||||
public static List<DataTriangle> ComputeAuriculare(List<Vector3> edgePoints, Vector3[] allPoints, bool isClockWise) {
|
||||
Vector3[] array = edgePoints.ToArray();
|
||||
List<DataTriangle> polygons = new List<DataTriangle>();
|
||||
for (int i = 0; i < array.Length; i++) {
|
||||
Auriculare auriculare = CreateAuriculare(i, array);
|
||||
// 等于180,大于180,不可能为耳点
|
||||
if (!GetAngleType(auriculare, isClockWise)) { continue; }
|
||||
// 包含其他点,不可能为耳点
|
||||
if (IsInsideTriangle(auriculare, allPoints)) { continue; }
|
||||
// 包含其他耳点,不可能成为耳点
|
||||
if (!IsInsideAuriculare(auriculare, edgePoints)) { continue; }
|
||||
edgePoints.Remove(auriculare.aPoint);
|
||||
polygons.Add(CreateAuriculareToTriangle(auriculare));
|
||||
}
|
||||
return polygons;
|
||||
}
|
||||
/// <summary> 创建耳点 </summary>
|
||||
public static Auriculare CreateAuriculare(int index, Vector3[] array) {
|
||||
Auriculare auriculare = new Auriculare();
|
||||
auriculare.index = index;
|
||||
auriculare.bPoint = array.LoopIndex(index - 1);
|
||||
auriculare.aPoint = array.LoopIndex(index);
|
||||
auriculare.cPoint = array.LoopIndex(index + 1);
|
||||
return auriculare;
|
||||
}
|
||||
/// <summary> 计算三角形内是否包含其他点 </summary>
|
||||
public static bool IsInsideTriangle(Auriculare auriculare, Vector3[] array) {
|
||||
for (int i = 0; i < array.Length; i++) {
|
||||
if (array[i] == auriculare.aPoint) { continue; }
|
||||
if (array[i] == auriculare.bPoint) { continue; }
|
||||
if (array[i] == auriculare.cPoint) { continue; }
|
||||
if (IsInsideTriangle(auriculare, array[i])) { return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// <summary> 计算三角形内是否包含其他点 </summary>
|
||||
public static bool IsInsideAuriculare(Auriculare auriculare, List<Vector3> edgePoints) {
|
||||
if (!edgePoints.Contains(auriculare.aPoint)) { return false; }
|
||||
if (!edgePoints.Contains(auriculare.bPoint)) { return false; }
|
||||
if (!edgePoints.Contains(auriculare.cPoint)) { return false; }
|
||||
return true;
|
||||
}
|
||||
/// <summary> 从节点创建三角形 </summary>
|
||||
public static DataTriangle CreateAuriculareToTriangle(Auriculare auriculare) {
|
||||
DataTriangle triangle = new DataTriangle();
|
||||
triangle.a = auriculare.aPoint;
|
||||
triangle.b = auriculare.bPoint;
|
||||
triangle.c = auriculare.cPoint;
|
||||
return triangle;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 算法
|
||||
/// <summary> 当前的点方向是否为顺时针 </summary>
|
||||
public static bool IsClockWise(Vector3[] array) {
|
||||
// 通过计算叉乘来确定方向
|
||||
float sum = 0f;
|
||||
double count = array.Length;
|
||||
Vector3 va, vb;
|
||||
for (int i = 0; i < array.Length; i++) {
|
||||
va = array[i];
|
||||
vb = (i == count - 1) ? array[0] : array[i + 1];
|
||||
sum += va.x * vb.y - va.y * vb.x;
|
||||
}
|
||||
return sum < 0;
|
||||
}
|
||||
/// <summary> 判断角的类型 </summary>
|
||||
public static bool GetAngleType(Auriculare auriculare, bool isClockWise) {
|
||||
// 角度是否小于180
|
||||
// oa & ob 之间的夹角,(右手法则)
|
||||
// 逆时针顺序是相反的
|
||||
Vector2 a = auriculare.aPoint;
|
||||
Vector2 b = auriculare.bPoint;
|
||||
Vector2 c = auriculare.cPoint;
|
||||
float f = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
|
||||
bool flag = isClockWise ? f > 0 : f < 0;
|
||||
if (f == 0) { return false;/*平角*/ }
|
||||
else if (flag) { return true;/*劣角*/ }
|
||||
else { return false;/*优角*/ }
|
||||
}
|
||||
/// <summary> p点是否在点a,b,c组成的三角形内,或边上 </summary>
|
||||
public static bool IsInsideTriangle(Auriculare auriculare, Vector2 p) {
|
||||
// p点是否在abc三角形内
|
||||
Vector2 a = auriculare.aPoint;
|
||||
Vector2 b = auriculare.bPoint;
|
||||
Vector2 c = auriculare.cPoint;
|
||||
float c1 = (b.x - a.x) * (p.y - b.y) - (b.y - a.y) * (p.x - b.x);
|
||||
float c2 = (c.x - b.x) * (p.y - c.y) - (c.y - b.y) * (p.x - c.x);
|
||||
float c3 = (a.x - c.x) * (p.y - a.y) - (a.y - c.y) * (p.x - a.x);
|
||||
return (c1 > 0f && c2 >= 0f && c3 >= 0f) || (c1 < 0f && c2 <= 0f && c3 <= 0f);
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4372bf8b5aa864f47bc02eec462942d7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,127 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 贝塞尔曲线计算边缘点
|
||||
/// </summary>
|
||||
public class UnitAlgorithmEdgePoint : UnitAlgorithm<DataPolygon> {
|
||||
|
||||
/// <summary> 三阶贝塞尔曲线计算边缘点 </summary>
|
||||
public UnitAlgorithmEdgePoint() { }
|
||||
|
||||
public void Compute(DataPolygon data) {
|
||||
//List<DataPoint> points = new List<DataPoint>(data.points);
|
||||
//List<Vector3> edgePoints = new List<Vector3>();
|
||||
//for (int i = 0; i < points.Count; i++) {
|
||||
// DataPoint aPoint = points.LoopIndex(i);
|
||||
// DataPoint bPoint = points.LoopIndex(i + 1);
|
||||
// if (!aPoint.isCurveAfter && !bPoint.isCurveFront) {
|
||||
// edgePoints.Add(aPoint.position);
|
||||
// }
|
||||
// if (!aPoint.isCurveAfter && bPoint.isCurveFront) {
|
||||
// edgePoints.AddRange(CreateLine(aPoint, bPoint, bPoint.frontBezier, data.edgeSmooth));
|
||||
// }
|
||||
// if (aPoint.isCurveAfter && !bPoint.isCurveFront) {
|
||||
// edgePoints.AddRange(CreateLine(aPoint, bPoint, aPoint.afterBezier, data.edgeSmooth));
|
||||
// }
|
||||
// if (aPoint.isCurveAfter && bPoint.isCurveFront) {
|
||||
// edgePoints.AddRange(CreateLine(aPoint, bPoint, data.edgeSmooth));
|
||||
// }
|
||||
//}
|
||||
//data.edgePoints = edgePoints;
|
||||
}
|
||||
|
||||
#region 函数
|
||||
/// <summary> 二阶贝塞尔线段 </summary>
|
||||
public List<Vector3> CreateLine(DataPlatePoint aPoint, DataPlatePoint bPoint, Vector3 b, float smooth) {
|
||||
List<Vector3> points = new List<Vector3>();
|
||||
//方向,距离
|
||||
Vector2 direction = (bPoint.position - aPoint.position).normalized;
|
||||
float distance = Vector2.Distance(bPoint.position, aPoint.position);
|
||||
//求余,得商数
|
||||
int quotient = Quotient(distance, smooth);
|
||||
//贝塞尔曲线点
|
||||
Vector3 a = aPoint.position;
|
||||
Vector3 c = bPoint.position;
|
||||
for (int i = 0; i < quotient; i++) {
|
||||
float t = i * (distance / quotient) / distance;
|
||||
Vector2 position = ComputeBezier(a, b, c, t);
|
||||
points.Add(position);
|
||||
}
|
||||
return points;
|
||||
}
|
||||
/// <summary> 三阶贝塞尔线段 </summary>
|
||||
public List<Vector3> CreateLine(DataPlatePoint aPoint, DataPlatePoint bPoint, float smooth) {
|
||||
List<Vector3> points = new List<Vector3>();
|
||||
//方向,距离
|
||||
Vector2 direction = (bPoint.position - aPoint.position).normalized;
|
||||
float distance = Vector2.Distance(bPoint.position, aPoint.position);
|
||||
//求余,得商数
|
||||
int quotient = Quotient(distance, smooth);
|
||||
//贝塞尔曲线点
|
||||
//Vector3 a = aPoint.position;
|
||||
//Vector3 b = aPoint.afterBezier;
|
||||
//Vector3 c = bPoint.frontBezier;
|
||||
//Vector3 d = bPoint.position;
|
||||
//for (int i = 0; i < quotient; i++) {
|
||||
// float t = i * (distance / quotient) / distance;
|
||||
// Vector2 position = ComputeBezier(a, b, c, d, t);
|
||||
// points.Add(position);
|
||||
//}
|
||||
return points;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 算法
|
||||
/// <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;
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c1c3f376c874a464db8a962d4a2f4730
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,239 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 39a35ef3408d163469eb7c66d1df96ac
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,123 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Unity.Burst;
|
||||
using Unity.Collections;
|
||||
using Unity.Jobs;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 三角形合并网格
|
||||
/// </summary>
|
||||
public class UnitAlgorithmMergeTriangle : UnitAlgorithm<DataPlateDesign>, UnitAlgorithm<DataPlateBaking> {
|
||||
/// <summary> 三角形合并网格 </summary>
|
||||
public UnitAlgorithmMergeTriangle() { }
|
||||
|
||||
public void Compute(DataPlateDesign plateDesign) {
|
||||
List<DataTriangle> polygons = plateDesign.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]); }
|
||||
//附加数据
|
||||
plateDesign.mesh = new Mesh();
|
||||
plateDesign.mesh.vertices = vertices.ToArray();
|
||||
plateDesign.mesh.uv = uv.ToArray();
|
||||
plateDesign.mesh.triangles = triangles.ToArray();
|
||||
plateDesign.mesh.RecalculateBounds();
|
||||
plateDesign.mesh.RecalculateNormals();
|
||||
}
|
||||
public void Compute(DataPlateBaking plateBaking) {
|
||||
//List<DataTriangle> polygons = plateBaking.triangles;
|
||||
////三角形合并
|
||||
//List<Vector3> vertices = vertices = MergeVertices(polygons);
|
||||
//List<int> triangles = JobFindTriangleIndex(polygons, vertices);
|
||||
////展开uv (顶点去掉z坐标就是未缩放的平面UV)
|
||||
//List<Vector2> uv = new List<Vector2>();
|
||||
//for (int i = 0; i < vertices.Count; i++) { uv.Add(vertices[i]); }
|
||||
////附加数据
|
||||
//plateBaking.mesh = new Mesh();
|
||||
//plateBaking.mesh.vertices = vertices.ToArray();
|
||||
//plateBaking.mesh.uv = uv.ToArray();
|
||||
//plateBaking.mesh.triangles = triangles.ToArray();
|
||||
//plateBaking.mesh.RecalculateBounds();
|
||||
//plateBaking.mesh.RecalculateNormals();
|
||||
}
|
||||
/// <summary> 合并顶点 </summary>
|
||||
private List<Vector3> MergeVertices(List<DataTriangle> polygons) {
|
||||
List<Vector3> vertices = new List<Vector3>();
|
||||
for (int i = 0; i < polygons.Count; i++) {
|
||||
vertices.Add(polygons[i].a);
|
||||
vertices.Add(polygons[i].b);
|
||||
vertices.Add(polygons[i].c);
|
||||
}
|
||||
return vertices.Distinct().ToList();
|
||||
}
|
||||
|
||||
#region Jobs
|
||||
/// <summary> 三角形顶点索引查找作业 </summary>
|
||||
private List<int> JobFindTriangleIndex(List<DataTriangle> polygons, List<Vector3> vertices) {
|
||||
NativeArray<DataTriangle> dataArray = new NativeArray<DataTriangle>(polygons.ToArray(), Allocator.TempJob);
|
||||
NativeArray<Vector3> verticeArray = new NativeArray<Vector3>(vertices.ToArray(), Allocator.TempJob);
|
||||
NativeArray<Triangle> trianglesArray = new NativeArray<Triangle>(polygons.Count, Allocator.TempJob);
|
||||
|
||||
TriangleIndex triangleIndex = new TriangleIndex();
|
||||
triangleIndex.dataArray = dataArray;
|
||||
triangleIndex.vertices = verticeArray;
|
||||
triangleIndex.triangles = trianglesArray;
|
||||
|
||||
JobHandle dependency = new JobHandle();
|
||||
JobHandle handle = triangleIndex.ScheduleParallel(polygons.Count, 32, dependency);
|
||||
handle.Complete();
|
||||
|
||||
List<int> triangles = new List<int>();
|
||||
for (int i = 0; i < trianglesArray.Length; i++) {
|
||||
triangles.Add(trianglesArray[i].a);
|
||||
triangles.Add(trianglesArray[i].b);
|
||||
triangles.Add(trianglesArray[i].c);
|
||||
}
|
||||
|
||||
dataArray.Dispose();
|
||||
verticeArray.Dispose();
|
||||
trianglesArray.Dispose();
|
||||
return triangles;
|
||||
}
|
||||
/// <summary> 三角形顶点索引查找作业 </summary>
|
||||
[BurstCompile]
|
||||
public struct TriangleIndex : IJobFor {
|
||||
[ReadOnly] public NativeArray<DataTriangle> dataArray;
|
||||
[ReadOnly] public NativeArray<Vector3> vertices;
|
||||
public NativeArray<Triangle> triangles;
|
||||
|
||||
public void Execute(int index) {
|
||||
DataTriangle dataTriangle = dataArray[index];
|
||||
Triangle triangle = new Triangle();
|
||||
bool a = false, b = false, c = false;
|
||||
for (int i = 0; i < vertices.Length; i++) {
|
||||
Vector3 vector = vertices[i];
|
||||
if (dataTriangle.a == vector) { triangle.a = i; a = true; }
|
||||
if (dataTriangle.b == vector) { triangle.b = i; b = true; }
|
||||
if (dataTriangle.c == vector) { triangle.c = i; c = true; }
|
||||
if (a && b && c) { break; }
|
||||
}
|
||||
triangles[index] = triangle;
|
||||
}
|
||||
}
|
||||
/// <summary> 三角形顶点索引 </summary>
|
||||
public struct Triangle { public int a, b, c; }
|
||||
#endregion
|
||||
|
||||
/// <summary> 是否启用计时器 </summary>
|
||||
private readonly bool isEnableTimer = true;
|
||||
/// <summary> 计时器 </summary>
|
||||
private void Chronoscope(string content, Action action) {
|
||||
if (!isEnableTimer) { action?.Invoke(); return; }
|
||||
float time = Time.realtimeSinceStartup;
|
||||
action?.Invoke();
|
||||
float consumed = Time.realtimeSinceStartup - time;
|
||||
Debug.Log($"{content}{consumed * 1000}");
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e4f1e7f586419604093e6609268f27b8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,95 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 合并三角形
|
||||
/// </summary>
|
||||
public class UnitAlgorithmMergeTriangles : UnitAlgorithm<DataPolygon> {
|
||||
public void Compute(DataPolygon data) {
|
||||
//List<DataTriangle> triangles = new List<DataTriangle>(data.triangles);
|
||||
//index = 0;
|
||||
//Merge(triangles);
|
||||
//data.triangles = triangles;
|
||||
//ModuleCore.I.VisualPolygon.UpdateVisual(data);
|
||||
}
|
||||
private int index;
|
||||
private int maxIndex;
|
||||
/// <summary> 取一个三角形出来 匹配剩下的三角形 符合条件则合并 </summary>
|
||||
private void Merge(List<DataTriangle> triangles) {
|
||||
if (index > triangles.Count) { return; }
|
||||
|
||||
DataTriangle aT = triangles[0];
|
||||
triangles.Remove(aT);
|
||||
|
||||
maxIndex = triangles.Count;
|
||||
for (int i = 0; i < triangles.Count; i++) {
|
||||
DataTriangle bT = triangles[i];
|
||||
//ab同边
|
||||
if (MergeConditions(bT.a, bT.b, bT, ref aT)) { triangles.Remove(bT); continue; }
|
||||
//bc同边
|
||||
if (MergeConditions(bT.b, bT.c, bT, ref aT)) { triangles.Remove(bT); continue; }
|
||||
//ca同边
|
||||
if (MergeConditions(bT.c, bT.a, bT, ref aT)) { triangles.Remove(bT); continue; }
|
||||
}
|
||||
index = maxIndex == triangles.Count ? index + 1 : 0;
|
||||
Debug.Log($"{index} , {maxIndex} , {triangles.Count}");
|
||||
|
||||
triangles.Add(aT);
|
||||
Merge(triangles);
|
||||
}
|
||||
/// <summary> 匹配三角形 符合条件则合并 无法合并则返回 true </summary>
|
||||
private bool Merge(List<DataTriangle> triangles, DataTriangle aT) {
|
||||
for (int i = 0; i < triangles.Count; i++) {
|
||||
DataTriangle bT = triangles[i];
|
||||
//ab同边
|
||||
if (MergeConditions(bT.a, bT.b, bT, ref aT)) { triangles.Remove(bT); }
|
||||
//bc同边
|
||||
if (MergeConditions(bT.b, bT.c, bT, ref aT)) { triangles.Remove(bT); }
|
||||
//ca同边
|
||||
if (MergeConditions(bT.c, bT.a, bT, ref aT)) { triangles.Remove(bT); }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/// <summary> 计算三角形内是否包含其他点 </summary>
|
||||
private bool IsInsideTriangle(DataTriangle triangle, Vector3 point) {
|
||||
if (triangle.a == point) { return true; }
|
||||
if (triangle.b == point) { return true; }
|
||||
if (triangle.c == point) { return true; }
|
||||
return false;
|
||||
}
|
||||
//检测合并条件是否满足
|
||||
private bool MergeConditions(Vector3 a, Vector3 b, DataTriangle bT, ref DataTriangle aT) {
|
||||
if (!IsInsideTriangle(aT, a, b, out Vector3 o)) { return false; }
|
||||
if (!IsInsideTriangle(bT, a, b, out Vector3 c)) { return false; }
|
||||
if (IsInsideTriangle(aT, c)) { return true; }
|
||||
Vector3 oa = (o - a).normalized;
|
||||
Vector3 ob = (o - b).normalized;
|
||||
Vector3 oc = (o - c).normalized;
|
||||
if (oc == oa) { aT.a = o; aT.b = b; aT.c = c; return true; }
|
||||
if (oc == ob) { aT.a = o; aT.b = a; aT.c = c; return true; }
|
||||
return false;
|
||||
}
|
||||
/// <summary> 计算三角形内是否包含其他点 </summary>
|
||||
private bool IsInsideTriangle(DataTriangle triangle, Vector3 a, Vector3 b, out Vector3 o) {
|
||||
if (triangle.a == a && triangle.b == b) { o = triangle.c; return true; }
|
||||
if (triangle.a == b && triangle.b == a) { o = triangle.c; return true; }
|
||||
if (triangle.a == a && triangle.c == b) { o = triangle.b; return true; }
|
||||
if (triangle.a == b && triangle.c == a) { o = triangle.b; return true; }
|
||||
if (triangle.b == a && triangle.c == b) { o = triangle.a; return true; }
|
||||
if (triangle.b == b && triangle.c == a) { o = triangle.a; return true; }
|
||||
o = a; return false;
|
||||
}
|
||||
|
||||
/// <summary> p点是否在点a,b,c组成的三角形内,或边上 </summary>
|
||||
public static bool IsInsideTriangle(DataTriangle auriculare, Vector2 p) {
|
||||
// p点是否在abc三角形内
|
||||
Vector2 a = auriculare.a;
|
||||
Vector2 b = auriculare.b;
|
||||
Vector2 c = auriculare.c;
|
||||
float c1 = (b.x - a.x) * (p.y - b.y) - (b.y - a.y) * (p.x - b.x);
|
||||
float c2 = (c.x - b.x) * (p.y - c.y) - (c.y - b.y) * (p.x - c.x);
|
||||
float c3 = (a.x - c.x) * (p.y - a.y) - (a.y - c.y) * (p.x - a.x);
|
||||
return (c1 > 0f && c2 >= 0f && c3 >= 0f) || (c1 < 0f && c2 <= 0f && c3 <= 0f);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 45d3c753563f5be468680173acf8b1e8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,149 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class UnitAlgorithmMeshVertex : UnitAlgorithm<DataPolygon> {
|
||||
public class Line {
|
||||
public Vector3 aPoint;
|
||||
public Vector3 bPoint;
|
||||
}
|
||||
|
||||
public class VertexUnit {
|
||||
public Vector3 position;
|
||||
}
|
||||
|
||||
public VertexUnit[,] unitArray;
|
||||
|
||||
public void Compute(DataPolygon data) {
|
||||
//List<Vector3> edgePoints = new List<Vector3>(data.edgePoints);
|
||||
////计算边界
|
||||
//float minX = 0; float minY = 0;
|
||||
//float maxX = 0; float maxY = 0;
|
||||
//for (int i = 0; i < edgePoints.Count; i++) {
|
||||
// if (edgePoints[i].x < minX) { minX = edgePoints[i].x; }
|
||||
// if (edgePoints[i].x > maxX) { maxX = edgePoints[i].x; }
|
||||
// if (edgePoints[i].y < minY) { minY = edgePoints[i].y; }
|
||||
// if (edgePoints[i].y > maxY) { maxY = edgePoints[i].y; }
|
||||
//}
|
||||
//float wide = maxX - minX;
|
||||
//float high = maxY - minY;
|
||||
////求余,得商数
|
||||
//int wideQuotient = Quotient(wide, 0.01f) + 1;
|
||||
//int highQuotient = Quotient(high, 0.01f) + 1;
|
||||
////平均间隔
|
||||
//float wideAverage = wide / wideQuotient;
|
||||
//float highAverage = high / highQuotient;
|
||||
////计算内部网格点
|
||||
//List<Vector3> vertices = new List<Vector3>();
|
||||
//Vector3 origin = new Vector3(minX, minY);
|
||||
//for (int i = 0; i < highQuotient; i++) {
|
||||
// for (int j = 0; j < wideQuotient; j++) {
|
||||
// Vector3 position = origin + new Vector3(j * wideAverage, i * highAverage);
|
||||
// if (FindPlateInside(edgePoints, position)) { vertices.Add(position); }
|
||||
// }
|
||||
//}
|
||||
////创建边缘线段,区分方向
|
||||
//List<Line> horizontal = new List<Line>();
|
||||
//List<Line> vertical = new List<Line>();
|
||||
//for (int i = 0; i < edgePoints.Count; i++) {
|
||||
// Line line = new Line();
|
||||
// line.aPoint = edgePoints.LoopIndex(i + 0);
|
||||
// line.bPoint = edgePoints.LoopIndex(i + 1);
|
||||
// Vector3 direction = (line.bPoint - line.aPoint).normalized;
|
||||
// if (Mathf.Abs(direction.x) >= 0.9) { horizontal.Add(line); }
|
||||
// else { vertical.Add(line); }
|
||||
//}
|
||||
////计算水平线段顶点
|
||||
//for (int i = 0; i < wideQuotient; i++) {
|
||||
// Vector3 a = new Vector3(minX + i * wideAverage, minY - 1);
|
||||
// Vector3 b = new Vector3(minX + i * wideAverage, maxY + 1);
|
||||
// //Debug.Log($"线段:{a} , {b}");
|
||||
// for (int j = 0; j < horizontal.Count; j++) {
|
||||
// Line line = horizontal[j];
|
||||
// //Debug.Log($"线段:{a} , {b} , {line.aPoint} , {line.bPoint}");
|
||||
// if (!TryGetIntersectPoint(a, b, line.aPoint, line.bPoint, out Vector3 intersectPos)) { continue; }
|
||||
// //Debug.Log($"交点:{intersectPos}");
|
||||
// vertices.Add(intersectPos);
|
||||
// }
|
||||
//}
|
||||
////计算垂直线段顶点
|
||||
//for (int i = 0; i < highQuotient; i++) {
|
||||
// Vector3 a = new Vector3(minX - 1, minY + i * highAverage);
|
||||
// Vector3 b = new Vector3(maxX + 1, minY + i * highAverage);
|
||||
// //Debug.Log($"线段:{a} , {b}");
|
||||
// for (int j = 0; j < vertical.Count; j++) {
|
||||
// Line line = vertical[j];
|
||||
// //Debug.Log($"线段:{a} , {b} , {line.aPoint} , {line.bPoint}");
|
||||
// if (!TryGetIntersectPoint(a, b, line.aPoint, line.bPoint, out Vector3 intersectPos)) { continue; }
|
||||
// //Debug.Log($"交点:{intersectPos}");
|
||||
// vertices.Add(intersectPos);
|
||||
// }
|
||||
//}
|
||||
//Debug.Log(vertices.Count);
|
||||
//data.vertices = vertices;
|
||||
}
|
||||
|
||||
|
||||
/// <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>
|
||||
public static bool FindPlateInside(List<Vector3> points, Vector3 position) {
|
||||
double angles = 0;
|
||||
for (int i = 0; i < points.Count; 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9b4b2ff6807f9704cb50f12b41e2a0a5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,62 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 菱形绘制三角形算法
|
||||
/// </summary>
|
||||
public class UnitAlgorithmRhombus : UnitAlgorithm<DataPlateBaking> {
|
||||
|
||||
public void Compute(DataPlateBaking plateBaking) {
|
||||
List<DataTriangle> triangles = new List<DataTriangle>();
|
||||
List<DataPlateVertex> vertexs = new List<DataPlateVertex>();
|
||||
//plateBaking.grid.Loop((x, y) => {
|
||||
// DataPlateVertex vertex = plateBaking.grid.Get(x, y);
|
||||
// if (!vertex.isValid) { return; }
|
||||
|
||||
// TryGet(plateBaking.grid, x, y + 1, ref vertex.above);
|
||||
// TryGet(plateBaking.grid, x, y - 1, ref vertex.below);
|
||||
// TryGet(plateBaking.grid, x - 1, y, ref vertex.left);
|
||||
// TryGet(plateBaking.grid, x + 1, y, ref vertex.right);
|
||||
|
||||
// TryGet(plateBaking.grid, x - 1, y + 1, ref vertex.leftAbove);
|
||||
// TryGet(plateBaking.grid, x - 1, y - 1, ref vertex.leftBelow);
|
||||
// TryGet(plateBaking.grid, x + 1, y + 1, ref vertex.rightAbove);
|
||||
// TryGet(plateBaking.grid, x + 1, y - 1, ref vertex.rightBelow);
|
||||
// //默认绘制左上角
|
||||
// if (vertex.above != null && vertex.left != null) {
|
||||
// triangles.Add(CreateDataTriangle(vertex, vertex.left, vertex.above));
|
||||
// }
|
||||
// //默认绘制右下角
|
||||
// if (vertex.below != null && vertex.right != null) {
|
||||
// triangles.Add(CreateDataTriangle(vertex, vertex.right, vertex.below));
|
||||
// }
|
||||
// //如果右上角点不存在,则尝试绘制右上角
|
||||
// if (vertex.rightAbove == null && vertex.above != null && vertex.right != null) {
|
||||
// triangles.Add(CreateDataTriangle(vertex, vertex.above, vertex.right));
|
||||
// }
|
||||
// //如果左下角点不存在,则尝试绘制左下角
|
||||
// if (vertex.leftBelow == null && vertex.below != null && vertex.left != null) {
|
||||
// triangles.Add(CreateDataTriangle(vertex, vertex.below, vertex.left));
|
||||
// }
|
||||
// vertexs.Add(vertex);
|
||||
//});
|
||||
//plateBaking.triangles = triangles;
|
||||
//plateBaking.vertexs = vertexs.ToArray();
|
||||
}
|
||||
|
||||
/// <summary> 校验性获取网格上的点 </summary>
|
||||
private void TryGet(GridTool<DataPlateVertex> grid, int x, int y, ref DataPlateVertex vertex) {
|
||||
vertex = null;
|
||||
if (!grid.TryGet(x, y, out DataPlateVertex data)) { return; }
|
||||
if (data.isValid) { vertex = data; }
|
||||
}
|
||||
/// <summary> 创建三角形 </summary>
|
||||
private DataTriangle CreateDataTriangle(DataPlateVertex a, DataPlateVertex b, DataPlateVertex c) {
|
||||
DataTriangle triangle = new DataTriangle();
|
||||
triangle.b = a.position;
|
||||
triangle.c = b.position;
|
||||
triangle.a = c.position;
|
||||
return triangle;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e45b841993dc7c04584b87f7794cf2fb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,35 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class UnitAlgorithmSubdivision : UnitAlgorithm<DataPolygon> {
|
||||
public void Compute(DataPolygon data) {
|
||||
//List<DataTriangle> triangles = new List<DataTriangle>(data.triangles);
|
||||
//List<DataTriangle> subdivision = new List<DataTriangle>();
|
||||
//for (int i = 0; i < triangles.Count; i++) {
|
||||
// subdivision.AddRange(Compute(triangles[i]));
|
||||
//}
|
||||
//subdivision.AddRange(Subdivision(triangles[121], data.edgeSmooth));
|
||||
|
||||
//data.triangles = subdivision;
|
||||
}
|
||||
private List<DataTriangle> Compute(DataTriangle triangle) {
|
||||
float ab = Vector3.Distance(triangle.a, triangle.b);
|
||||
float bc = Vector3.Distance(triangle.b, triangle.c);
|
||||
float ca = Vector3.Distance(triangle.c, triangle.a);
|
||||
if (ab > bc && ab > ca && ab > 0.02f) { return Compute(triangle.c, triangle.a, triangle.b); }
|
||||
if (bc > ab && bc > ca && bc > 0.02f) { return Compute(triangle.a, triangle.b, triangle.c); }
|
||||
if (ca > bc && ca > ab && ca > 0.02f) { return Compute(triangle.b, triangle.c, triangle.a); }
|
||||
|
||||
return new List<DataTriangle> { triangle };
|
||||
}
|
||||
private List<DataTriangle> Compute(Vector3 a, Vector3 b, Vector3 c) {
|
||||
Vector3 direction = b - c;
|
||||
Vector3 d = c + direction * 0.5f;
|
||||
|
||||
DataTriangle aT = new DataTriangle { a = a, b = d, c = c };
|
||||
DataTriangle bT = new DataTriangle { a = a, b = b, c = d };
|
||||
return new List<DataTriangle> { aT, bT, };
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bb4aa74668cf2134eb322b3a40d74c29
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,64 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9735cc247f76e0b42b50f8b7956d3c8a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,52 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b98adb17aebd36b4ab5dfe90020fb902
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,148 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 顶点算法
|
||||
/// </summary>
|
||||
public class UnitAlgorithmVertex : UnitAlgorithm<DataPlateBaking> {
|
||||
|
||||
public class SideVertex : IComparable<SideVertex> {
|
||||
public float distance;
|
||||
public Vector3 position;
|
||||
|
||||
public int CompareTo(SideVertex other) {
|
||||
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(DataPlateBaking plateBaking) {
|
||||
DataBorder border = plateBaking.border;
|
||||
Vector3[] points = border.points;
|
||||
|
||||
//计算内部顶点
|
||||
//plateBaking.grid = new GridTool<DataPlateVertex>(border.GridWide, border.GridHigh, (x, y) => {
|
||||
// Vector3 position = new Vector3(x, y) * border.smooth + border.MinPoint;
|
||||
// DataPlateVertex vertex = new DataPlateVertex();
|
||||
// vertex.isValid = FindPlateInside(points, position);
|
||||
// vertex.position = position;
|
||||
// return vertex;
|
||||
//});
|
||||
|
||||
//边缘所有的线段
|
||||
//List<DataPlateSide> plateSides = plateBaking.plate.plateSides;
|
||||
//for (int i = 0; i < plateSides.Count; i++) {
|
||||
// SubdivideSideVertex(plateBaking, plateSides[i]);
|
||||
//}
|
||||
}
|
||||
|
||||
private void SubdivideSideVertex(DataPlateBaking plateBaking, DataPlateSide plateSides) {
|
||||
DataBorder border = plateBaking.border;
|
||||
DataPlateLine[] lines = plateSides.dataBaking.lines;
|
||||
//计算水平线段顶点
|
||||
List<SideVertex> sideVertexs = new List<SideVertex>();
|
||||
for (int x = 0; x < border.GridWide; x++) {
|
||||
Vector3 a = new Vector3(border.minX + x * border.smooth, border.minY - 1);
|
||||
Vector3 b = new Vector3(border.minX + x * border.smooth, border.maxY + 1);
|
||||
for (int i = 0; i < lines.Length; i++) {
|
||||
if (!TryGetIntersectPoint(a, b, lines[i].a, lines[i].b, out Vector3 IntersectPoint)) { continue; }
|
||||
float distance = Vector3.Distance(lines[i].a, IntersectPoint) + lines[i].origin;
|
||||
SideVertex sideVertex = new SideVertex();
|
||||
sideVertex.distance = distance;
|
||||
sideVertex.position = IntersectPoint;
|
||||
sideVertexs.Add(sideVertex);
|
||||
}
|
||||
}
|
||||
//计算垂直线段顶点
|
||||
for (int y = 0; y < border.GridHigh; y++) {
|
||||
Vector3 a = new Vector3(border.minX - 1, border.minY + y * border.smooth);
|
||||
Vector3 b = new Vector3(border.maxX + 1, border.minY + y * border.smooth);
|
||||
for (int i = 0; i < lines.Length; i++) {
|
||||
if (!TryGetIntersectPoint(a, b, lines[i].a, lines[i].b, out Vector3 IntersectPoint)) { continue; }
|
||||
float distance = Vector3.Distance(lines[i].a, IntersectPoint) + lines[i].origin;
|
||||
SideVertex sideVertex = new SideVertex();
|
||||
sideVertex.distance = distance;
|
||||
sideVertex.position = IntersectPoint;
|
||||
sideVertexs.Add(sideVertex);
|
||||
}
|
||||
}
|
||||
//排序
|
||||
sideVertexs.Sort();
|
||||
//写入网格,写入顶点
|
||||
Vector3 offset = border.MinPoint - new Vector3(border.smooth, border.smooth, 0) * 0.3f;
|
||||
List<DataPlateVertex> vertexs = new List<DataPlateVertex>();
|
||||
for (int i = 0; i < sideVertexs.Count; i++) {
|
||||
Vector3 position = sideVertexs[i].position;
|
||||
Vector3 gridPosition = position - offset;
|
||||
int vertexX = Mathf.FloorToInt(gridPosition.x / border.smooth);
|
||||
int vertexY = Mathf.FloorToInt(gridPosition.y / border.smooth);
|
||||
//填充数据
|
||||
//DataPlateVertex vertex = plateBaking.grid.Get(vertexX, vertexY);
|
||||
//vertex.isValid = true;
|
||||
//vertex.position = position;
|
||||
////写入顶点
|
||||
//vertexs.Add(vertex);
|
||||
}
|
||||
plateSides.dataBaking.vertexs = vertexs.ToArray();
|
||||
}
|
||||
|
||||
/// <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;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4a24da15970a3654386664f8d6503d04
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3105cf897e8dcb6408a9d5b207fa348e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,74 +0,0 @@
|
||||
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;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 368e1bf20f25d424f8ed16d00323b8b8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public interface UnitFind<Data> {
|
||||
/// <summary> 查询 </summary>
|
||||
public bool Find(Vector3 position, out Data data);
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 77073523d35e8fb4bb758404278690c5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4ef3354979b38474ab3efdbe7d603f9c
|
||||
guid: e6ffff57450000c409c511daef71ed5a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class BakingMobile : UnitMouseInput {
|
||||
/// <summary> 设计视图相机模块 </summary>
|
||||
public ModuleViewCamera ViewCamera => ModuleCore.ViewCameraBaking;
|
||||
|
||||
private Vector3 mousePosition;
|
||||
private Vector3 originalPosition;
|
||||
|
||||
public override void MouseDown(DataMouseInput data) {
|
||||
mousePosition = data.ScreenPosition;
|
||||
originalPosition = ViewCamera.Position;
|
||||
}
|
||||
public override void MouseDrag(DataMouseInput data) {
|
||||
Vector3 original = ViewCamera.ScreenToWorldPosition(mousePosition);
|
||||
Vector3 current = data.WorldPosition;
|
||||
Vector3 offset = current - original;
|
||||
Vector3 up = ViewCamera.Up * offset.y;
|
||||
Vector3 right = ViewCamera.Right * offset.x;
|
||||
ViewCamera.Position = originalPosition + up + right;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2e91048b6b41fcd488c55503ebfc3723
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,46 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class BakingMobilePlate : UnitMouseInput {
|
||||
/// <summary> 安排点图层遮罩 </summary>
|
||||
private readonly LayerMask Arrange = LayerMaskTool.Arrange;
|
||||
/// <summary> 烘焙视图相机模块 </summary>
|
||||
public ModuleViewCamera ViewCamera => ModuleCore.ViewCameraBaking;
|
||||
|
||||
private Vector3 mousePosition;
|
||||
private Vector3 originalPosition;
|
||||
private FixedArrange arrange;
|
||||
private ModulePrefab<DataPlate> platePrefab;
|
||||
|
||||
public override void MouseDown(DataMouseInput data) {
|
||||
if (!ViewCamera.ScreenToWorldObject(data.ScreenPosition, out platePrefab)) { return; }
|
||||
mousePosition = data.ScreenPosition;
|
||||
originalPosition = platePrefab.transform.localPosition;
|
||||
platePrefab.Value.dataBaking.position = originalPosition;
|
||||
ModuleCore.BakingMobilePlate(platePrefab.Value);
|
||||
}
|
||||
public override void MouseDrag(DataMouseInput data) {
|
||||
if (platePrefab == null) { return; }
|
||||
if (ViewCamera.ScreenToWorldObjectParent(data.ScreenPosition, out arrange, Arrange)) {
|
||||
platePrefab.Value.arrange = arrange;
|
||||
platePrefab.Value.dataBaking.position = arrange.transform.localPosition;
|
||||
platePrefab.Value.dataBaking.eulerAngles = arrange.transform.localEulerAngles;
|
||||
}
|
||||
else { Mobile(data.WorldPosition); }
|
||||
platePrefab.Value.UpdateVisual(false);
|
||||
}
|
||||
public override void MouseRelease(DataMouseInput data) {
|
||||
ModuleCore.BakingMobilePlate(null);
|
||||
}
|
||||
|
||||
private void Mobile(Vector3 worldPosition) {
|
||||
platePrefab.Value.arrange = null;
|
||||
Vector3 original = ViewCamera.ScreenToWorldPosition(mousePosition);
|
||||
Vector3 current = worldPosition;
|
||||
Vector3 offset = current - original;
|
||||
Vector3 up = ViewCamera.Up * offset.y;
|
||||
Vector3 right = ViewCamera.Right * offset.x;
|
||||
platePrefab.Value.dataBaking.position = originalPosition - up - right;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 00b6b3cc18640204a8ad48985d53db48
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,21 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class BakingRotate : UnitMouseInput {
|
||||
/// <summary> 设计视图相机模块 </summary>
|
||||
public ModuleViewCamera ViewCamera => ModuleCore.ViewCameraBaking;
|
||||
|
||||
private Vector3 mousePosition;
|
||||
private Vector3 originalEulerAngles;
|
||||
|
||||
public override void MouseDown(DataMouseInput data) {
|
||||
mousePosition = data.ViewPosition;
|
||||
originalEulerAngles = ViewCamera.EulerAngles;
|
||||
}
|
||||
public override void MouseDrag(DataMouseInput data) {
|
||||
float offsetX = data.ViewPosition.x - mousePosition.x;
|
||||
float offsetY = data.ViewPosition.y - mousePosition.y;
|
||||
ViewCamera.EulerAngles = originalEulerAngles + new Vector3(-offsetY, offsetX , 0) * 360;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 49bda1134b4639f4cb22ffd3bb0499ce
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,7 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class BakingSelect : UnitMouseInput {
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c1b9618a80c54534ca23a5e71c9d9de0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,17 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class DesignBezier : UnitMouseInput {
|
||||
/// <summary> 设计视图相机模块 </summary>
|
||||
public ModuleViewCamera ViewCamera => ModuleCore.ViewCameraDesign;
|
||||
/// <summary> 查询点算法模块 </summary>
|
||||
public ModuleFind<DataPlateSide> FindSide => ModuleCore.FindSide;
|
||||
|
||||
public override void MouseDown(DataMouseInput data) {
|
||||
if (!FindSide.Find(data.WorldPosition, out DataPlateSide side)) { return; }
|
||||
if (side.bezier == Bezier.一阶) { side.TwoRankBezier(); side.plate.UpdateVisual(); return; }
|
||||
if (side.bezier == Bezier.二阶) { side.ThreeRankBezier(); side.plate.UpdateVisual(); return; }
|
||||
if (side.bezier == Bezier.三阶) { side.OneRankBezier(); side.plate.UpdateVisual(); return; }
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c4c272ae3cc78a54c819d6b6194a75a8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,35 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class DesignInsert : UnitMouseInput {
|
||||
/// <summary> 查询边交点 </summary>
|
||||
public UnitFind<SideIntersectPoint> find = new FindSideIntersectPoint();
|
||||
|
||||
public override void MouseDown(DataMouseInput data) {
|
||||
if (!find.Find(data.WorldPosition, out SideIntersectPoint sip)) { return; }
|
||||
Insert(sip.side, sip.side.plate, sip.side.aPoint, sip.side.bPoint, sip.intersectPoint);
|
||||
}
|
||||
|
||||
private void Insert(DataPlateSide side, DataPlate plate, DataPlatePoint aPoint, DataPlatePoint bPoint, Vector3 position) {
|
||||
//创建新的点
|
||||
DataPlatePoint newPoint = new DataPlatePoint(plate);
|
||||
newPoint.position = position - plate.dataDesign.position;
|
||||
//改变关联的边B点,重置贝塞尔曲线
|
||||
side.bPoint = newPoint;
|
||||
side.OneRankBezier();
|
||||
//创建新的边
|
||||
DataPlateSide newSide = new DataPlateSide(plate);
|
||||
newSide.aPoint = newPoint;
|
||||
newSide.bPoint = bPoint;
|
||||
newSide.OneRankBezier();
|
||||
//插入边
|
||||
int sideIndex = plate.plateSides.IndexOf(side);
|
||||
plate.plateSides.Insert(sideIndex + 1, newSide);
|
||||
//插入点
|
||||
int pointIndex = plate.platePoints.IndexOf(aPoint);
|
||||
plate.platePoints.Insert(pointIndex + 1, newPoint);
|
||||
//更新数据
|
||||
plate.UpdateVisual();
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6572c7ebab448a94d880fca85c728132
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,78 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class DesignMobile : UnitMouseInput {
|
||||
/// <summary> 设计视图相机模块 </summary>
|
||||
public ModuleViewCamera ViewCamera => ModuleCore.ViewCameraDesign;
|
||||
/// <summary> 查询贝塞尔点算法模块 </summary>
|
||||
public ModuleFind<DataBezier> FindBezier => ModuleCore.FindBezier;
|
||||
|
||||
private DataBezier bezier;
|
||||
private Vector3 mousePosition;
|
||||
private Vector3 originalPosition;
|
||||
private ModulePrefab<DataPlatePoint> prefabPoint;
|
||||
private ModulePrefab<DataPlate> prefabPlate;
|
||||
|
||||
public override void MouseDown(DataMouseInput data) {
|
||||
//判断是否选中贝塞尔点
|
||||
if (FindBezier.Find(data.WorldPosition, out bezier)) {
|
||||
RecordBezier(data.ScreenPosition); return;
|
||||
}
|
||||
//判断是否选中点
|
||||
if (ViewCamera.ScreenToWorldObjectParent(data.ScreenPosition, out prefabPoint)) {
|
||||
RecordPoint(data.ScreenPosition); return;
|
||||
}
|
||||
//判断是否选中板片
|
||||
if (ViewCamera.ScreenToWorldObjectParent(data.ScreenPosition,out prefabPlate)) {
|
||||
RecordPlate(data.ScreenPosition); return;
|
||||
}
|
||||
RecordCamera(data.ScreenPosition);
|
||||
}
|
||||
public override void MouseDrag(DataMouseInput data) {
|
||||
Vector3 original = ViewCamera.ScreenToWorldPosition(mousePosition);
|
||||
Vector3 current = data.WorldPosition;
|
||||
Vector3 offset = current - original;
|
||||
|
||||
if (bezier != null) { MobileBezier(offset); return; }
|
||||
if (prefabPoint != null) { MobilePoint(offset); return; }
|
||||
if (prefabPlate != null) { MobilePlate(offset); return; }
|
||||
MobileCamera(offset);
|
||||
}
|
||||
|
||||
//贝塞尔
|
||||
private void RecordBezier(Vector3 screenPosition) {
|
||||
mousePosition = screenPosition;
|
||||
originalPosition = bezier.position;
|
||||
}
|
||||
private void MobileBezier(Vector3 offset) {
|
||||
Vector3 position = originalPosition + offset;
|
||||
bezier.SetBezierPosition(position);
|
||||
}
|
||||
//点
|
||||
private void RecordPoint(Vector3 screenPosition) {
|
||||
mousePosition = screenPosition;
|
||||
originalPosition = prefabPoint.Value.position;
|
||||
}
|
||||
private void MobilePoint(Vector3 offset) {
|
||||
prefabPoint.Value.position = originalPosition + offset;
|
||||
prefabPoint.Value.plate.UpdateVisual();
|
||||
}
|
||||
//板片
|
||||
private void RecordPlate(Vector3 screenPosition) {
|
||||
mousePosition = screenPosition;
|
||||
originalPosition = prefabPlate.Value.dataDesign.position;
|
||||
}
|
||||
private void MobilePlate(Vector3 offset) {
|
||||
prefabPlate.Value.dataDesign.position = originalPosition + offset;
|
||||
prefabPlate.Value.UpdateVisual(false);
|
||||
}
|
||||
//相机
|
||||
private void RecordCamera(Vector3 screenPosition) {
|
||||
mousePosition = screenPosition;
|
||||
originalPosition = ViewCamera.Position;
|
||||
}
|
||||
private void MobileCamera(Vector3 offset) {
|
||||
ViewCamera.Position = originalPosition - offset;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1d9fbc3106b97d147ac9164dc314865a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,57 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class DesignSuture : UnitMouseInput {
|
||||
/// <summary> 查询边交点 </summary>
|
||||
public UnitFind<SideIntersectPoint> find = new FindSideIntersectPoint();
|
||||
/// <summary> 连接可视化内容生成模块 </summary>
|
||||
public ModuleVisual<DataConnector> VisualConnector => ModuleCore.VisualConnector;
|
||||
|
||||
private DataPlateSide aSide;
|
||||
private DataPlateSide bSide;
|
||||
private DataConnector connector;
|
||||
|
||||
public override void MouseDown(DataMouseInput data) {
|
||||
connector = new DataConnector();
|
||||
connector.aPoint = data.WorldPosition;
|
||||
if (!find.Find(data.WorldPosition, out SideIntersectPoint sip)) { return; }
|
||||
connector.aPoint = sip.intersectPoint;
|
||||
aSide = sip.side;
|
||||
}
|
||||
public override void MouseDrag(DataMouseInput data) {
|
||||
if (connector == null) { return; }
|
||||
connector.bPoint = data.WorldPosition;
|
||||
if (find.Find(data.WorldPosition, out SideIntersectPoint sip)) {
|
||||
connector.bPoint = sip.intersectPoint;
|
||||
bSide = sip.side;
|
||||
}
|
||||
else { connector.bPoint = data.WorldPosition; }
|
||||
VisualConnector.UpdateVisual(connector);
|
||||
}
|
||||
public override void MouseRelease(DataMouseInput data) {
|
||||
if (connector == null) { return; }
|
||||
VisualConnector.ReleaseVisual(connector);
|
||||
connector = null;
|
||||
|
||||
if (aSide == null || bSide == null || aSide == bSide) { return; }
|
||||
if (aSide.suture != null || bSide.suture != null) { return; }
|
||||
DataSuture suture = new DataSuture(aSide, bSide);
|
||||
aSide.suture = suture;
|
||||
bSide.suture = suture;
|
||||
aSide.plate.UpdateVisual();
|
||||
}
|
||||
|
||||
//private Vector3 GetPosition(DataMouseInput data) {
|
||||
// if (!FindSide.Find(data.WorldPosition, out bSide)) { return data.WorldPosition; }
|
||||
// if (aSide == bSide) { return data.WorldPosition; }
|
||||
// if (Intersect(bSide, data.WorldPosition, out Vector3 intersectPoint)) { return intersectPoint; }
|
||||
// else { return data.WorldPosition; }
|
||||
//}
|
||||
//private bool Intersect(DataSide side, Vector3 position, out Vector3 intersectPoint) {
|
||||
//DataIntersect intersect = new DataIntersect(side, position);
|
||||
//AlgorithmSidePoint.Compute(intersect);
|
||||
//intersectPoint = intersect.intersectPoint;
|
||||
//return intersect.isIntersect;
|
||||
//}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f4da355235e26524388688f6bd6d5f43
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,21 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class DesignSutureReversal : UnitMouseInput {
|
||||
/// <summary> 设计视图相机模块 </summary>
|
||||
public ModuleViewCamera ViewCamera => ModuleCore.ViewCameraDesign;
|
||||
/// <summary> 查询点算法模块 </summary>
|
||||
public ModuleFind<DataPlateSide> FindSide => ModuleCore.FindSide;
|
||||
|
||||
public override void MouseDown(DataMouseInput data) {
|
||||
if (!FindSide.Find(data.WorldPosition, out DataPlateSide side)) { return; }
|
||||
if (side.suture.a.plateSide == side) {
|
||||
side.suture.a.isReversal = !side.suture.a.isReversal;
|
||||
}
|
||||
if (side.suture.b.plateSide == side) {
|
||||
side.suture.b.isReversal = !side.suture.b.isReversal;
|
||||
}
|
||||
side.plate.UpdateVisual();
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4360e81518739f24c842afc64b8e81b3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -2,9 +2,6 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 鼠标输入单元
|
||||
/// </summary>
|
||||
public abstract class UnitMouseInput {
|
||||
/// <summary> 核心模块 </summary>
|
||||
protected virtual ModuleCore ModuleCore => ModuleCore.I;
|
||||
@@ -17,4 +14,6 @@ public abstract class UnitMouseInput {
|
||||
public virtual void MouseMove(DataMouseInput data) { }
|
||||
/// <summary> 释放鼠标 </summary>
|
||||
public virtual void MouseRelease(DataMouseInput data) { }
|
||||
/// <summary> 鼠标滚轮 </summary>
|
||||
public virtual void MouseScroll(DataMouseInput data) { }
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e54a1981f15dce04b95e1b917c13cccd
|
||||
guid: d6cbde8dad4ff3f44bd5cc80c96fc3b9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 003c25d4c480b204eb86572109652c5d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,68 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
public class UIControlBaking : UnitUIControl {
|
||||
|
||||
#region UI元素
|
||||
public override VisualElement Element => ModuleUIPage.Q<VisualElement>("PlateBaking");
|
||||
public VisualElement Rendering => Element.Q<VisualElement>("Rendering");
|
||||
public Button Button1 => Element.Q<Button>("Button1");
|
||||
public Button Button2 => Element.Q<Button>("Button2");
|
||||
public Button Button3 => Element.Q<Button>("Button3");
|
||||
public Button Button4 => Element.Q<Button>("Button4");
|
||||
public Button Button5 => Element.Q<Button>("Button5");
|
||||
#endregion
|
||||
|
||||
#region 引用模块
|
||||
/// <summary> 视图相机模块 </summary>
|
||||
public ModuleViewCamera ViewCamera => ModuleCore.ViewCameraBaking;
|
||||
/// <summary> UI输入模块 </summary>
|
||||
public ModuleUIInput<UnitMouseInput> UIInput => ModuleCore.UIInputBaking;
|
||||
#endregion
|
||||
|
||||
public override void Awake() {
|
||||
Element.generateVisualContent += Element_GenerateVisualContent;
|
||||
Button1.clicked += () => { UIInput.ChangeInput(new BakingMobile()); };
|
||||
Button2.clicked += () => { UIInput.ChangeInput(new BakingMobilePlate()); };
|
||||
//Button3.clicked += () => { UIInput.ChangeInput(new DesignBezier()); };
|
||||
//Button4.clicked += () => { UIInputDesign.ChangeInput(new IDesignSelect()); };
|
||||
//Button5.clicked += () => { UIInputDesign.ChangeInput(new IDesignSelect()); };
|
||||
}
|
||||
private void Start() {
|
||||
UIInput.Binding(Rendering);
|
||||
UIInput.OnChangeInput += UIInputDesign_OnChangeInput;
|
||||
UIInput.ChangeInput(new BakingMobile());
|
||||
}
|
||||
|
||||
#region 更新视图
|
||||
private void Element_GenerateVisualContent(MeshGenerationContext context) {
|
||||
StartCoroutine(UpdateRenderTexture());
|
||||
}
|
||||
private IEnumerator UpdateRenderTexture() {
|
||||
yield return null;
|
||||
int width = (int)Element.resolvedStyle.width;
|
||||
int height = (int)Element.resolvedStyle.height;
|
||||
ViewCamera.UpdateRenderTexture(width, height);
|
||||
Background background = Background.FromRenderTexture(ViewCamera.RenderTexture);
|
||||
StyleBackground style = new StyleBackground(background);
|
||||
Rendering.style.backgroundImage = style;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 输入功能
|
||||
private void UIInputDesign_OnChangeInput(UnitMouseInput obj) {
|
||||
Type type = obj.GetType();
|
||||
ButtonStyleChange(type, typeof(BakingMobile), Button1);
|
||||
ButtonStyleChange(type, typeof(BakingMobilePlate), Button2);
|
||||
//ButtonStyleChange(type, typeof(DesignBezier), Button3);
|
||||
}
|
||||
private void ButtonStyleChange(Type obj, Type compare, Button button) {
|
||||
if (obj == compare) { button.AddToClassList("pb-button-s"); }
|
||||
else { button.RemoveFromClassList("pb-button-s"); }
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 64a73ef8100a7184c8668f3a50cb50d4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,73 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
public class UIControlDesign : UnitUIControl {
|
||||
|
||||
#region UI元素
|
||||
public override VisualElement Element => ModuleUIPage.Q<VisualElement>("PlateDesign");
|
||||
public VisualElement Rendering => Element.Q<VisualElement>("Rendering");
|
||||
public Button Button1 => Element.Q<Button>("Button1");
|
||||
public Button Button2 => Element.Q<Button>("Button2");
|
||||
public Button Button3 => Element.Q<Button>("Button3");
|
||||
public Button Button4 => Element.Q<Button>("Button4");
|
||||
public Button Button5 => Element.Q<Button>("Button5");
|
||||
public Button Button6 => Element.Q<Button>("Button6");
|
||||
public Button Button7 => Element.Q<Button>("Button7");
|
||||
#endregion
|
||||
|
||||
#region 引用模块
|
||||
/// <summary> 设计视图相机模块 </summary>
|
||||
public ModuleViewCamera ViewCamera => ModuleCore.ViewCameraDesign;
|
||||
/// <summary> 设计UI输入模块 </summary>
|
||||
public ModuleUIInput<UnitMouseInput> UIInputDesign => ModuleCore.UIInputDesign;
|
||||
#endregion
|
||||
|
||||
public override void Awake() {
|
||||
Element.generateVisualContent += Element_GenerateVisualContent;
|
||||
Button1.clicked += () => { UIInputDesign.ChangeInput(new DesignMobile()); };
|
||||
Button2.clicked += () => { UIInputDesign.ChangeInput(new DesignInsert()); };
|
||||
Button3.clicked += () => { UIInputDesign.ChangeInput(new DesignBezier()); };
|
||||
Button4.clicked += () => { UIInputDesign.ChangeInput(new DesignSuture()); };
|
||||
Button5.clicked += () => { UIInputDesign.ChangeInput(new DesignSutureReversal()); };
|
||||
}
|
||||
private void Start() {
|
||||
UIInputDesign.Binding(Rendering);
|
||||
UIInputDesign.OnChangeInput += UIInputDesign_OnChangeInput;
|
||||
UIInputDesign.ChangeInput(new DesignMobile());
|
||||
}
|
||||
private void OnDestroy() {
|
||||
if (UIInputDesign == null) { return; }
|
||||
UIInputDesign.OnChangeInput -= UIInputDesign_OnChangeInput;
|
||||
}
|
||||
|
||||
#region 更新视图
|
||||
private void Element_GenerateVisualContent(MeshGenerationContext context) {
|
||||
StartCoroutine(UpdateRenderTexture());
|
||||
}
|
||||
private IEnumerator UpdateRenderTexture() {
|
||||
yield return null;
|
||||
int width = (int)Element.resolvedStyle.width;
|
||||
int height = (int)Element.resolvedStyle.height;
|
||||
ViewCamera.UpdateRenderTexture(width, height);
|
||||
Background background = Background.FromRenderTexture(ViewCamera.RenderTexture);
|
||||
StyleBackground style = new StyleBackground(background);
|
||||
Rendering.style.backgroundImage = style;
|
||||
}
|
||||
#endregion
|
||||
|
||||
private void UIInputDesign_OnChangeInput(UnitMouseInput obj) {
|
||||
Type type = obj.GetType();
|
||||
ButtonStyleChange(type, typeof(DesignMobile), Button1);
|
||||
ButtonStyleChange(type, typeof(DesignInsert), Button2);
|
||||
ButtonStyleChange(type, typeof(DesignBezier), Button3);
|
||||
ButtonStyleChange(type, typeof(DesignSuture), Button4);
|
||||
ButtonStyleChange(type, typeof(DesignSutureReversal), Button5);
|
||||
}
|
||||
private void ButtonStyleChange(Type obj, Type compare, Button button) {
|
||||
if (obj == compare) { button.AddToClassList("pd-button-s"); }
|
||||
else { button.RemoveFromClassList("pd-button-s"); }
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 141e3035b49c87441bdd757f6d978c1e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,63 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using MuHua;
|
||||
|
||||
public class UIControlInspect : UnitUIControl {
|
||||
|
||||
#region UI元素
|
||||
public override VisualElement Element => ModuleUIPage.Q<VisualElement>("Inspect");
|
||||
public VisualElement PlateSettings => Element.Q<VisualElement>("PlateSettings");
|
||||
public VisualElement PointSettings => Element.Q<VisualElement>("PointSettings");
|
||||
#endregion
|
||||
|
||||
#region 引用模块
|
||||
/// <summary> 广播查询数据模块 </summary>
|
||||
//public ModuleSending<DataFind> SendingFind => ModuleCore.SendingFind;
|
||||
#endregion
|
||||
|
||||
//private DataPlate Plate => SendingFind.Current.plate;
|
||||
//private DataPoint Point => SendingFind.Current.point;
|
||||
|
||||
private UIPlateSettings uiPlateSettings;
|
||||
private UIPointSettings uiPointSettings;
|
||||
public override void Awake() {
|
||||
uiPlateSettings = new UIPlateSettings(PlateSettings);
|
||||
|
||||
uiPointSettings = new UIPointSettings(PointSettings);
|
||||
//uiPointSettings.Toggle1.OnChange += (value) => { Point.isCurveFront = value; Plate.UpdateVisual(); };
|
||||
//uiPointSettings.Toggle2.OnChange += (value) => { Point.isCurveAfter = value; Plate.UpdateVisual(); };
|
||||
}
|
||||
|
||||
private void Start() {
|
||||
//SendingFind.OnChange += SendingFind_OnChange;
|
||||
}
|
||||
|
||||
//private void SendingFind_OnChange(DataFind obj) {
|
||||
// PointSettings.style.display = DisplayStyle.None;
|
||||
// PlateSettings.style.display = DisplayStyle.None;
|
||||
// if (obj.IsValidPoint) { UpdateUIPointSettings(); return; }
|
||||
// if (obj.IsValidPlate) { UpdateUIPlateSettings(); return; }
|
||||
//}
|
||||
private void UpdateUIPlateSettings() {
|
||||
PlateSettings.style.display = DisplayStyle.Flex;
|
||||
}
|
||||
private void UpdateUIPointSettings() {
|
||||
PointSettings.style.display = DisplayStyle.Flex;
|
||||
//uiPointSettings.Toggle1.SetValue(Point.isCurveFront);
|
||||
//uiPointSettings.Toggle2.SetValue(Point.isCurveAfter);
|
||||
}
|
||||
|
||||
public class UIPlateSettings {
|
||||
public readonly VisualElement element;
|
||||
public UIPlateSettings(VisualElement element) => this.element = element;
|
||||
}
|
||||
public class UIPointSettings {
|
||||
public readonly VisualElement element;
|
||||
public VisualElement Bezier => element.Q<VisualElement>("Bezier");
|
||||
public MUToggle Toggle1 => element.Q<MUToggle>("Toggle1");
|
||||
public MUToggle Toggle2 => element.Q<MUToggle>("Toggle2");
|
||||
public UIPointSettings(VisualElement element) => this.element = element;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e19ef8edf7b1d7844838898350516ef8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 78a3f28d3b5c8334f8dcfa20b5e73d29
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e32e80c5be1d97347ba09f54d8962952
|
||||
guid: bd3360ba80b4e6f45b980c09ca91b77f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
+5
-2
@@ -3,11 +3,14 @@ using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
public abstract class UnitUIControl : MonoBehaviour {
|
||||
/// <summary>
|
||||
/// UI面板单元
|
||||
/// </summary>
|
||||
public abstract class UnitUIPanel : MonoBehaviour {
|
||||
/// <summary> 绑定的页面 </summary>
|
||||
public ModuleUIPage ModuleUIPage;
|
||||
/// <summary> 必须初始化 </summary>
|
||||
public abstract void Awake();
|
||||
protected abstract void Awake();
|
||||
/// <summary> 核心模块 </summary>
|
||||
protected virtual ModuleCore ModuleCore => ModuleCore.I;
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 794f9553060acb04e88211793e35c810
|
||||
guid: ff06370808b1ecd46b161a402c6c171e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
Reference in New Issue
Block a user