using UnityEngine; using UnityEditor; [ExecuteInEditMode] public class VoxelizationTool : MonoBehaviour { public Vector3 gridSize = new Vector3(10, 10, 10); // 体素化区域的尺寸 public float voxelSize = 1.0f; // 每个体素的大小 public Color gridColor = Color.cyan; // 网格颜色 public bool showGrid = true; // 是否显示网格 public bool onlyShowMeshVoxels = true; // 是否仅显示包含 Mesh 的体素 private Bounds gridBounds; // 网格的总体包围盒 private void OnDrawGizmos() { if (!showGrid) return; Gizmos.color = gridColor; // 定义整个体素网格的包围盒 gridBounds = new Bounds(transform.position + gridSize * voxelSize / 2, gridSize * voxelSize); // 获取场景中的所有 MeshFilter MeshFilter[] meshFilters = FindObjectsOfType(); foreach (MeshFilter meshFilter in meshFilters) { Bounds meshBounds = meshFilter.sharedMesh.bounds; meshBounds = TransformBounds(meshBounds, meshFilter.transform); // 遍历体素,检查是否与当前 Mesh 的 Bounds 相交 for (int x = 0; x < gridSize.x; x++) { for (int y = 0; y < gridSize.y; y++) { for (int z = 0; z < gridSize.z; z++) { Vector3 voxelCenter = transform.position + new Vector3(x, y, z) * voxelSize + Vector3.one * voxelSize / 2; // 跳过不在包围盒内的体素 if (!gridBounds.Contains(voxelCenter)) continue; // 检查体素是否与 Mesh 的 Bounds 相交 Bounds voxelBounds = new Bounds(voxelCenter, Vector3.one * voxelSize); if (meshBounds.Intersects(voxelBounds)) { Gizmos.DrawWireCube(voxelCenter, Vector3.one * voxelSize); } } } } } } /// /// 将本地 Bounds 转换为世界空间的 Bounds /// private Bounds TransformBounds(Bounds localBounds, Transform transform) { Vector3 worldCenter = transform.TransformPoint(localBounds.center); Vector3 worldExtents = Vector3.Scale(localBounds.extents, transform.lossyScale); return new Bounds(worldCenter, worldExtents * 2); } }