111
This commit is contained in:
@@ -4,14 +4,11 @@ using System.Linq;
|
||||
|
||||
public class ShadowColliderGenerator : MonoBehaviour
|
||||
{
|
||||
[Header("References")]
|
||||
public Camera shadowCamera;
|
||||
public RenderTexture shadowRT;
|
||||
public PolygonCollider2D polygonCollider;
|
||||
|
||||
[Header("Settings")]
|
||||
[Range(0f, 1f)]
|
||||
public float shadowThreshold = 0.3f;
|
||||
public float shadowThreshold = 0.1f;
|
||||
public int gridSize = 2; // 网格大小,越小越精确
|
||||
public float simplifyTolerance = 1f;
|
||||
|
||||
@@ -19,9 +16,6 @@ public class ShadowColliderGenerator : MonoBehaviour
|
||||
|
||||
void Start()
|
||||
{
|
||||
if (polygonCollider == null)
|
||||
polygonCollider = GetComponent<PolygonCollider2D>();
|
||||
|
||||
processedTexture = new Texture2D(shadowRT.width, shadowRT.height, TextureFormat.R8, false);
|
||||
GenerateCollider();
|
||||
}
|
||||
@@ -36,253 +30,411 @@ public class ShadowColliderGenerator : MonoBehaviour
|
||||
|
||||
[ContextMenu("Generate Collider")]
|
||||
public void GenerateCollider()
|
||||
{
|
||||
|
||||
ReadRenderTexture();
|
||||
|
||||
}
|
||||
void ReadRenderTexture()
|
||||
{
|
||||
if (shadowCamera == null || shadowRT == null) return;
|
||||
|
||||
// 渲染阴影
|
||||
shadowCamera.Render();
|
||||
|
||||
// 读取纹理
|
||||
RenderTexture.active = shadowRT;
|
||||
processedTexture.ReadPixels(new Rect(0, 0, shadowRT.width, shadowRT.height), 0, 0);
|
||||
processedTexture.Apply();
|
||||
RenderTexture.active = null;
|
||||
|
||||
// 生成轮廓
|
||||
List<Vector2> contour = GenerateContourFromTexture();
|
||||
|
||||
if (contour.Count > 2)
|
||||
Color[] pixels = processedTexture.GetPixels();
|
||||
float[,] grid = new float[shadowRT.width, shadowRT.height];
|
||||
for (int y = 0; y < shadowRT.height; y++)
|
||||
{
|
||||
List<Vector2> worldPoints = ConvertToWorldCoordinates(contour);
|
||||
polygonCollider.SetPath(0, worldPoints);
|
||||
Debug.Log($"Collider generated with {worldPoints.Count} points");
|
||||
}
|
||||
else
|
||||
{
|
||||
polygonCollider.pathCount = 0;
|
||||
Debug.Log("No contour generated");
|
||||
}
|
||||
}
|
||||
|
||||
List<Vector2> GenerateContourFromTexture()
|
||||
{
|
||||
int width = processedTexture.width;
|
||||
int height = processedTexture.height;
|
||||
|
||||
// 创建二值化网格
|
||||
bool[,] grid = CreateBinaryGrid(width, height);
|
||||
|
||||
// 找到所有边界点
|
||||
List<Vector2> boundaryPoints = FindBoundaryPoints(grid);
|
||||
|
||||
// 连接边界点形成轮廓
|
||||
List<Vector2> contour = ConnectBoundaryPoints(boundaryPoints);
|
||||
|
||||
return contour;
|
||||
}
|
||||
|
||||
bool[,] CreateBinaryGrid(int width, int height)
|
||||
{
|
||||
bool[,] grid = new bool[width / gridSize, height / gridSize];
|
||||
|
||||
for (int x = 0; x < grid.GetLength(0); x++)
|
||||
{
|
||||
for (int y = 0; y < grid.GetLength(1); y++)
|
||||
for (int x = 0; x < shadowRT.width; x++)
|
||||
{
|
||||
int texX = x * gridSize;
|
||||
int texY = y * gridSize;
|
||||
Color pixel = processedTexture.GetPixel(texX, texY);
|
||||
grid[x, y] = pixel.grayscale < shadowThreshold;
|
||||
// 只取R通道(因为是灰度图,RGB值相同)
|
||||
grid[x, y] = pixels[y * shadowRT.width + x].r;
|
||||
}
|
||||
}
|
||||
|
||||
return grid;
|
||||
Debug.Log($"{grid[0, shadowRT.height - 1]:F3}, {grid[shadowRT.width - 1, 0]:F3}");
|
||||
AnalyzeWithMarchingSquares(grid, shadowThreshold);
|
||||
}
|
||||
|
||||
List<Vector2> FindBoundaryPoints(bool[,] grid)
|
||||
void AnalyzeWithMarchingSquares(float[,] grid, float checkValue)
|
||||
{
|
||||
List<Vector2> boundaryPoints = new List<Vector2>();
|
||||
//List<Vector2> allEdgePoints = CollectAllEdgePoints(grid, checkValue);
|
||||
//List<Vector2> contour = ImprovedContourConnection(allEdgePoints);
|
||||
//UpdatePolygonCollider(allEdgePoints, grid.GetLength(0), grid.GetLength(1));
|
||||
|
||||
//Debug.Log("Marching Squares处理完成");
|
||||
|
||||
// 使用正确的轮廓跟踪
|
||||
int width = grid.GetLength(0);
|
||||
int height = grid.GetLength(1);
|
||||
|
||||
for (int x = 0; x < width; x++)
|
||||
// 使用正确的轮廓跟踪
|
||||
List<List<Vector2>> contours = GenerateContours(grid, checkValue, width, height);
|
||||
|
||||
// 过滤掉点太少的轮廓
|
||||
List<List<Vector2>> validContours = contours;
|
||||
//List<List<Vector2>> validContours = contours.Where(c => c.Count > 10).ToList();
|
||||
|
||||
Debug.Log($"生成 {contours.Count} 个轮廓,有效轮廓 {validContours.Count} 个");
|
||||
|
||||
// 显示每个轮廓的信息
|
||||
for (int i = 0; i < Mathf.Min(5, validContours.Count); i++) // 只显示前5个
|
||||
{
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
if (grid[x, y])
|
||||
{
|
||||
// 检查是否是边界(有非阴影像素邻居)
|
||||
bool isBoundary = false;
|
||||
|
||||
// 检查4邻域
|
||||
if (x == 0 || !grid[x - 1, y]) isBoundary = true;
|
||||
else if (x == width - 1 || !grid[x + 1, y]) isBoundary = true;
|
||||
else if (y == 0 || !grid[x, y - 1]) isBoundary = true;
|
||||
else if (y == height - 1 || !grid[x, y + 1]) isBoundary = true;
|
||||
|
||||
if (isBoundary)
|
||||
{
|
||||
boundaryPoints.Add(new Vector2(x * gridSize, y * gridSize));
|
||||
}
|
||||
}
|
||||
}
|
||||
Debug.Log($"轮廓 {i}: {validContours[i].Count} 个点");
|
||||
}
|
||||
|
||||
Debug.Log($"Found {boundaryPoints.Count} boundary points");
|
||||
return boundaryPoints;
|
||||
// 使用所有有效轮廓创建碰撞体
|
||||
UpdatePolygonCollider(validContours, width, height);
|
||||
|
||||
Debug.Log("Marching Squares处理完成");
|
||||
}
|
||||
|
||||
List<Vector2> ConnectBoundaryPoints(List<Vector2> points)
|
||||
{
|
||||
if (points.Count < 3) return points;
|
||||
|
||||
List<Vector2> contour = new List<Vector2>();
|
||||
List<Vector2> remaining = new List<Vector2>(points);
|
||||
|
||||
// 找到最左边的点作为起点
|
||||
Vector2 start = remaining.OrderBy(p => p.x).First();
|
||||
contour.Add(start);
|
||||
remaining.Remove(start);
|
||||
|
||||
Vector2 current = start;
|
||||
Vector2 previousDirection = Vector2.right;
|
||||
|
||||
int maxIterations = points.Count * 2;
|
||||
int iterations = 0;
|
||||
|
||||
while (remaining.Count > 0 && iterations < maxIterations)
|
||||
{
|
||||
iterations++;
|
||||
|
||||
// 找到与当前方向最一致的下一个点
|
||||
float bestScore = float.MinValue;
|
||||
Vector2 bestPoint = Vector2.zero;
|
||||
int bestIndex = -1;
|
||||
|
||||
for (int i = 0; i < remaining.Count; i++)
|
||||
{
|
||||
Vector2 toPoint = (remaining[i] - current).normalized;
|
||||
float distance = Vector2.Distance(current, remaining[i]);
|
||||
|
||||
// 评分:方向一致性 + 距离权重
|
||||
float directionScore = Vector2.Dot(previousDirection, toPoint);
|
||||
float distanceScore = 1f / (distance + 0.1f);
|
||||
float totalScore = directionScore + distanceScore * 0.1f;
|
||||
|
||||
if (totalScore > bestScore && distance < 50f) // 距离限制
|
||||
{
|
||||
bestScore = totalScore;
|
||||
bestPoint = remaining[i];
|
||||
bestIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestIndex >= 0)
|
||||
{
|
||||
previousDirection = (bestPoint - current).normalized;
|
||||
contour.Add(bestPoint);
|
||||
remaining.RemoveAt(bestIndex);
|
||||
current = bestPoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 确保轮廓闭合
|
||||
if (contour.Count > 2 && Vector2.Distance(contour[0], contour[contour.Count - 1]) > 30f)
|
||||
{
|
||||
contour.Add(contour[0]);
|
||||
}
|
||||
|
||||
// 简化轮廓
|
||||
contour = SimplifyContour(contour);
|
||||
|
||||
Debug.Log($"Connected {contour.Count} points into contour");
|
||||
return contour;
|
||||
}
|
||||
|
||||
List<Vector2> SimplifyContour(List<Vector2> contour)
|
||||
{
|
||||
if (contour.Count <= 3) return contour;
|
||||
|
||||
List<Vector2> simplified = new List<Vector2>();
|
||||
simplified.Add(contour[0]);
|
||||
|
||||
for (int i = 1; i < contour.Count - 1; i++)
|
||||
{
|
||||
// 如果角度变化太大,保留这个点
|
||||
if (i > 1)
|
||||
{
|
||||
Vector2 prevDir = (contour[i] - contour[i - 1]).normalized;
|
||||
Vector2 nextDir = (contour[i + 1] - contour[i]).normalized;
|
||||
float angle = Vector2.Angle(prevDir, nextDir);
|
||||
|
||||
if (angle > 30f) // 角度阈值
|
||||
{
|
||||
simplified.Add(contour[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simplified.Add(contour[contour.Count - 1]);
|
||||
|
||||
return simplified;
|
||||
}
|
||||
|
||||
List<Vector2> ConvertToWorldCoordinates(List<Vector2> texturePoints)
|
||||
List<Vector2> ConvertToWorldCoordinates(List<Vector2> texturePoints, int textureWidth, int textureHeight)
|
||||
{
|
||||
List<Vector2> worldPoints = new List<Vector2>();
|
||||
|
||||
foreach (Vector2 texCoord in texturePoints)
|
||||
{
|
||||
Vector3 viewportPos = new Vector3(
|
||||
texCoord.x / processedTexture.width,
|
||||
texCoord.y / processedTexture.height,
|
||||
shadowCamera.nearClipPlane
|
||||
// 将纹理坐标归一化到 [0,1] 范围
|
||||
Vector2 normalizedCoord = new Vector2(
|
||||
texCoord.x / textureWidth,
|
||||
texCoord.y / textureHeight
|
||||
);
|
||||
|
||||
Vector3 worldPos = shadowCamera.ViewportToWorldPoint(viewportPos);
|
||||
worldPoints.Add(new Vector2(worldPos.x, worldPos.y));
|
||||
// 将归一化坐标转换到世界坐标
|
||||
// 假设墙的本地坐标范围是 [0,0] 到 [1,1]
|
||||
Vector2 worldPoint = normalizedCoord;
|
||||
|
||||
worldPoints.Add(worldPoint);
|
||||
}
|
||||
|
||||
return worldPoints;
|
||||
}
|
||||
|
||||
// 调试:显示边界点
|
||||
void OnDrawGizmosSelected()
|
||||
/// <summary>
|
||||
/// 创建或更新PolygonCollider2D(支持多个轮廓)
|
||||
/// </summary>
|
||||
void UpdatePolygonCollider(List<List<Vector2>> contours, int textureWidth, int textureHeight)
|
||||
{
|
||||
if (processedTexture == null) return;
|
||||
|
||||
Gizmos.color = Color.red;
|
||||
|
||||
// 显示边界点
|
||||
bool[,] grid = CreateBinaryGrid(processedTexture.width, processedTexture.height);
|
||||
List<Vector2> boundaryPoints = FindBoundaryPoints(grid);
|
||||
|
||||
foreach (Vector2 point in boundaryPoints)
|
||||
// 获取或添加PolygonCollider2D组件
|
||||
PolygonCollider2D polygonCollider = GetComponent<PolygonCollider2D>();
|
||||
if (polygonCollider == null)
|
||||
{
|
||||
Vector3 viewportPos = new Vector3(
|
||||
point.x / processedTexture.width,
|
||||
point.y / processedTexture.height,
|
||||
shadowCamera.nearClipPlane
|
||||
);
|
||||
Vector3 worldPos = shadowCamera.ViewportToWorldPoint(viewportPos);
|
||||
Gizmos.DrawSphere(worldPos, 0.02f);
|
||||
polygonCollider = gameObject.AddComponent<PolygonCollider2D>();
|
||||
Debug.Log("添加PolygonCollider2D组件");
|
||||
}
|
||||
|
||||
// 显示碰撞器轮廓
|
||||
if (polygonCollider != null && polygonCollider.pathCount > 0)
|
||||
if (contours.Count > 0)
|
||||
{
|
||||
Gizmos.color = Color.green;
|
||||
Vector2[] path = polygonCollider.GetPath(0);
|
||||
for (int i = 0; i < path.Length; i++)
|
||||
// 设置轮廓数量
|
||||
polygonCollider.pathCount = contours.Count;
|
||||
|
||||
int totalPoints = 0;
|
||||
|
||||
for (int i = 0; i < contours.Count; i++)
|
||||
{
|
||||
Vector3 start = path[i];
|
||||
Vector3 end = path[(i + 1) % path.Length];
|
||||
Gizmos.DrawLine(start, end);
|
||||
if (contours[i].Count > 2)
|
||||
{
|
||||
// 转换坐标
|
||||
List<Vector2> worldPoints = ConvertToWorldCoordinates(contours[i], textureWidth, textureHeight);
|
||||
|
||||
// 设置当前轮廓路径
|
||||
polygonCollider.SetPath(i, worldPoints);
|
||||
|
||||
totalPoints += worldPoints.Count;
|
||||
|
||||
Debug.Log($"轮廓 {i}: {worldPoints.Count} 个点");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 点太少,设置空路径
|
||||
polygonCollider.SetPath(i, new Vector2[0]);
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log($"碰撞体创建成功: {contours.Count} 个轮廓,共 {totalPoints} 个顶点");
|
||||
|
||||
// 显示碰撞体边界信息
|
||||
Bounds bounds = polygonCollider.bounds;
|
||||
Debug.Log($"碰撞体边界: 中心({bounds.center.x:F2}, {bounds.center.y:F2}), 大小({bounds.size.x:F2}, {bounds.size.y:F2})");
|
||||
}
|
||||
else
|
||||
{
|
||||
polygonCollider.pathCount = 0;
|
||||
Debug.Log("没有有效轮廓,清除碰撞体");
|
||||
}
|
||||
}
|
||||
List<Vector2> ImprovedContourConnection(List<Vector2> points)
|
||||
{
|
||||
if (points.Count < 3)
|
||||
{
|
||||
Debug.Log("点太少,无法形成轮廓");
|
||||
return new List<Vector2>();
|
||||
}
|
||||
|
||||
// 方法1:直接返回原始点(按细胞顺序)
|
||||
Debug.Log($"直接返回 {points.Count} 个点(未排序)");
|
||||
return points;
|
||||
|
||||
// 或者方法2:简单的按Y然后X排序
|
||||
// List<Vector2> sorted = points.OrderBy(p => p.y).ThenBy(p => p.x).ToList();
|
||||
// return sorted;
|
||||
}
|
||||
|
||||
List<Vector2> CollectAllEdgePoints(float[,] grid, float checkValue)
|
||||
{
|
||||
List<Vector2> allEdgePoints = new List<Vector2>();
|
||||
for (int y = 0; y < grid.GetLength(1) - 1; y++)
|
||||
{
|
||||
for (int x = 0; x < grid.GetLength(0) - 1; x++)
|
||||
{
|
||||
int cellstate = CalculateCellState(x, y, grid, checkValue);
|
||||
if (cellstate != 0 && cellstate != 15)
|
||||
{
|
||||
List<Vector2> edgePoints = FindEdgePointsInCell(x, y, cellstate, grid, checkValue);
|
||||
allEdgePoints.AddRange(edgePoints);
|
||||
}
|
||||
}
|
||||
}
|
||||
Debug.Log($"收集到 {allEdgePoints.Count} 个等值点");
|
||||
|
||||
// 显示前10个点作为示例
|
||||
for (int i = 0; i < Mathf.Min(10, allEdgePoints.Count); i++)
|
||||
{
|
||||
Debug.Log($"点 {i}: ({allEdgePoints[i].x:F2}, {allEdgePoints[i].y:F2})");
|
||||
}
|
||||
return allEdgePoints;
|
||||
}
|
||||
List<Vector2> FindEdgePointsInCell(int x, int y, int cellState, float[,] grid, float checkValue)
|
||||
{
|
||||
List<Vector2> edges = new List<Vector2>();
|
||||
bool p0 = (cellState & 1) != 0;
|
||||
bool p1 = (cellState & 2) != 0;
|
||||
bool p2 = (cellState & 4) != 0;
|
||||
bool p3 = (cellState & 8) != 0;
|
||||
if (p0 != p1)
|
||||
{
|
||||
Vector2 point = CalculateEdgePoint(x, y,CellEdge.Bottom, grid, checkValue);
|
||||
edges.Add(point);
|
||||
}
|
||||
if (p1 != p2)
|
||||
{
|
||||
Vector2 point = CalculateEdgePoint(x, y, CellEdge.Right, grid, checkValue);
|
||||
edges.Add(point);
|
||||
}
|
||||
if (p2 != p3)
|
||||
{
|
||||
Vector2 point = CalculateEdgePoint(x, y, CellEdge.Top, grid, checkValue);
|
||||
edges.Add(point);
|
||||
}
|
||||
if (p3 != p0)
|
||||
{
|
||||
Vector2 point = CalculateEdgePoint(x, y, CellEdge.Left, grid, checkValue);
|
||||
edges.Add(point);
|
||||
}
|
||||
return edges;
|
||||
}
|
||||
Vector2 CalculateEdgePoint(int x, int y, CellEdge cellEdge, float[,] grid, float checkValue)
|
||||
{
|
||||
Vector2 p1 = Vector2.zero, p2 = Vector2.zero;
|
||||
float v1 = 0, v2 = 0;
|
||||
switch (cellEdge)
|
||||
{
|
||||
case CellEdge.Bottom:
|
||||
p1 = new Vector2(x, y);
|
||||
p2 = new Vector2(x+1, y);
|
||||
v1 = grid[x, y];
|
||||
v2 = grid[x+1, y];
|
||||
break;
|
||||
case CellEdge.Right:
|
||||
p1 = new Vector2(x+1, y);
|
||||
p2 = new Vector2(x + 1, y+1);
|
||||
v1 = grid[x + 1, y];
|
||||
v2 = grid[x + 1, y + 1];
|
||||
break;
|
||||
case CellEdge.Top:
|
||||
p1 = new Vector2(x + 1, y + 1);
|
||||
p2 = new Vector2(x , y + 1);
|
||||
v1 = grid[x + 1, y + 1];
|
||||
v2 = grid[x, y + 1];
|
||||
break;
|
||||
case CellEdge.Left:
|
||||
p1 = new Vector2(x, y + 1);
|
||||
p2 = new Vector2(x , y);
|
||||
v1 = grid[x, y + 1];
|
||||
v2 = grid[x , y];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
float t = (checkValue-v1)/(v2 - v1);
|
||||
return Vector2.Lerp(p1, p2, t);
|
||||
}
|
||||
int CalculateCellState(int x,int y, float[,] grid,float checkValue )
|
||||
{
|
||||
int state = 0;
|
||||
if (grid[x, y] <= checkValue) state |= 1;
|
||||
if (grid[x+1, y] <= checkValue) state |= 2;
|
||||
if (grid[x+1, y+1] <= checkValue) state |= 4;
|
||||
if (grid[x, y + 1] <= checkValue) state |= 8;
|
||||
return state;
|
||||
}
|
||||
/// <summary>
|
||||
/// 正确的Marching Squares轮廓生成(带方向跟踪)
|
||||
/// </summary>
|
||||
List<List<Vector2>> GenerateContours(float[,] grid, float isoLevel, int width, int height)
|
||||
{
|
||||
List<List<Vector2>> contours = new List<List<Vector2>>();
|
||||
bool[,] visited = new bool[width - 1, height - 1];
|
||||
|
||||
for (int y = 0; y < height - 1; y++)
|
||||
{
|
||||
for (int x = 0; x < width - 1; x++)
|
||||
{
|
||||
if (visited[x, y]) continue;
|
||||
|
||||
int cellState = CalculateCellState(x, y, grid, isoLevel);
|
||||
|
||||
// 只处理有边界穿过的细胞
|
||||
if (cellState > 0 && cellState < 15)
|
||||
{
|
||||
List<Vector2> contour = TraceContour(x, y, grid, isoLevel, width, height, visited);
|
||||
if (contour != null && contour.Count > 2)
|
||||
{
|
||||
contours.Add(contour);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return contours;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 跟踪一个轮廓(按行进方向)
|
||||
/// </summary>
|
||||
List<Vector2> TraceContour(int startX, int startY, float[,] grid, float isoLevel, int width, int height, bool[,] visited)
|
||||
{
|
||||
List<Vector2> contour = new List<Vector2>();
|
||||
int x = startX;
|
||||
int y = startY;
|
||||
int entryEdge = 0; // 进入边,从下边开始
|
||||
|
||||
do
|
||||
{
|
||||
if (x < 0 || x >= width - 1 || y < 0 || y >= height - 1) break;
|
||||
|
||||
visited[x, y] = true;
|
||||
int cellState = CalculateCellState(x, y, grid, isoLevel);
|
||||
|
||||
// 根据细胞状态和进入边决定出口边
|
||||
int exitEdge = GetExitEdge(cellState, entryEdge);
|
||||
|
||||
if (exitEdge == -1) break;
|
||||
|
||||
// 计算当前边的等值点
|
||||
Vector2 point = CalculateEdgePoint(x, y, (CellEdge)exitEdge, grid, isoLevel);
|
||||
contour.Add(point);
|
||||
|
||||
// 移动到下一个细胞
|
||||
switch (exitEdge)
|
||||
{
|
||||
case 0: // 从下边出,向下移动
|
||||
y--;
|
||||
entryEdge = 2; // 进入上边
|
||||
break;
|
||||
case 1: // 从右边出,向右移动
|
||||
x++;
|
||||
entryEdge = 3; // 进入左边
|
||||
break;
|
||||
case 2: // 从上边出,向上移动
|
||||
y++;
|
||||
entryEdge = 0; // 进入下边
|
||||
break;
|
||||
case 3: // 从左边出,向左移动
|
||||
x--;
|
||||
entryEdge = 1; // 进入右边
|
||||
break;
|
||||
}
|
||||
|
||||
} while (!(x == startX && y == startY) && contour.Count < 1000);
|
||||
|
||||
return contour;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据细胞状态和进入边获取出口边
|
||||
/// </summary>
|
||||
int GetExitEdge(int cellState, int entryEdge)
|
||||
{
|
||||
// 简化的查找表 [细胞状态, 进入边] -> 出口边
|
||||
// 这是一个简化版本,实际需要完整的16x4查找表
|
||||
switch (cellState)
|
||||
{
|
||||
case 1: // 0001
|
||||
case 14: // 1110
|
||||
return (entryEdge == 0) ? 3 : 0;
|
||||
case 2: // 0010
|
||||
case 13: // 1101
|
||||
return (entryEdge == 1) ? 0 : 1;
|
||||
case 4: // 0100
|
||||
case 11: // 1011
|
||||
return (entryEdge == 2) ? 1 : 2;
|
||||
case 8: // 1000
|
||||
case 7: // 0111
|
||||
return (entryEdge == 3) ? 2 : 3;
|
||||
case 3: // 0011
|
||||
case 12: // 1100
|
||||
return (entryEdge == 0) ? 1 : 0;
|
||||
case 6: // 0110
|
||||
case 9: // 1001
|
||||
return (entryEdge == 1) ? 2 : 1;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
// 在类末尾添加Gizmos方法(支持多个轮廓)
|
||||
void OnDrawGizmosSelected()
|
||||
{
|
||||
PolygonCollider2D polygonCollider = GetComponent<PolygonCollider2D>();
|
||||
if (polygonCollider != null && polygonCollider.pathCount > 0)
|
||||
{
|
||||
for (int pathIndex = 0; pathIndex < polygonCollider.pathCount; pathIndex++)
|
||||
{
|
||||
Vector2[] path = polygonCollider.GetPath(pathIndex);
|
||||
|
||||
if (path.Length < 3) continue;
|
||||
|
||||
// 每个轮廓用不同颜色
|
||||
Color[] colors = { Color.green, Color.blue, Color.yellow, Color.cyan, Color.magenta };
|
||||
Gizmos.color = colors[pathIndex % colors.Length];
|
||||
|
||||
// 绘制轮廓线
|
||||
for (int i = 0; i < path.Length; i++)
|
||||
{
|
||||
Vector3 start = transform.TransformPoint(path[i]);
|
||||
Vector3 end = transform.TransformPoint(path[(i + 1) % path.Length]);
|
||||
Gizmos.DrawLine(start, end);
|
||||
}
|
||||
|
||||
// 显示顶点
|
||||
Gizmos.color = Color.red;
|
||||
foreach (Vector2 point in path)
|
||||
{
|
||||
Vector3 worldPoint = transform.TransformPoint(point);
|
||||
Gizmos.DrawSphere(worldPoint, 0.005f);
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log($"Gizmos显示 {polygonCollider.pathCount} 个轮廓");
|
||||
}
|
||||
}
|
||||
enum CellEdge
|
||||
{
|
||||
Bottom = 0,
|
||||
Right = 1,
|
||||
Top = 2,
|
||||
Left = 3
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user