NLDClient-yudde/ProjectNLD/Assets/Editor/Scene/PostProcesser/Utils/MeshCombineUtils.cs

211 lines
6.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 网格合并工具类
/// </summary>
public static class MeshCombineUtils
{
/// <summary>
/// 收集渲染器
/// </summary>
public static List<Renderer> CollectRenderers(List<Transform> roots)
{
List<Renderer> allRenderers = new();
foreach (var root in roots)
{
if (!root)
{
continue;
}
var render = root.GetComponentsInChildren<Renderer>();
if (render is not { Length: > 0 })
{
continue;
}
allRenderers.AddRange(render);
}
return allRenderers;
}
/// <summary>
/// 根据相互距离对渲染器进行分组
/// 只要物体与组内任意一个物体距离小于 maxDistance就将其加入该组
/// </summary>
public static Dictionary<string, List<Renderer>> GroupRenderersByProximity(List<Renderer> renderers,
float maxDistance)
{
var groups = new Dictionary<string, List<Renderer>>();
var groupIndex = 0;
// 已分组的渲染器
var processedRenderers = new HashSet<Renderer>();
// 对所有渲染器进行处理
while (processedRenderers.Count < renderers.Count)
{
// 找到第一个未处理的渲染器作为新组的起点
Renderer startRenderer = FindFirstUnprocessedRenderer(renderers, processedRenderers);
if (startRenderer == null)
break;
// 创建新组并添加起点渲染器
var currentGroup = new List<Renderer> { startRenderer };
processedRenderers.Add(startRenderer);
// 扩展当前组
ExpandGroupByProximity(renderers, currentGroup, processedRenderers, maxDistance);
// 添加组到结果
groups.Add($"Group_{groupIndex}", currentGroup);
groupIndex++;
}
Debug.Log($"基于邻近距离分组:将{renderers.Count}个渲染器分成{groups.Count}个组,最大距离为{maxDistance}");
return groups;
}
/// <summary>
/// 查找第一个未处理的渲染器
/// </summary>
private static Renderer FindFirstUnprocessedRenderer(List<Renderer> renderers, HashSet<Renderer> processedRenderers)
{
foreach (var renderer in renderers)
{
if (!processedRenderers.Contains(renderer))
{
return renderer;
}
}
return null;
}
/// <summary>
/// 通过邻近距离扩展组
/// </summary>
private static void ExpandGroupByProximity(List<Renderer> allRenderers, List<Renderer> currentGroup,
HashSet<Renderer> processedRenderers, float maxDistance)
{
bool addedNew = true;
while (addedNew)
{
addedNew = false;
// 查找与当前组中任意一个渲染器距离在阈值内的未处理渲染器
foreach (var renderer in allRenderers)
{
if (processedRenderers.Contains(renderer))
continue;
// 检查是否与组内任何一个渲染器距离小于阈值
if (IsCloseToAnyInGroup(renderer, currentGroup, maxDistance))
{
currentGroup.Add(renderer);
processedRenderers.Add(renderer);
addedNew = true;
}
}
}
}
/// <summary>
/// 检查渲染器是否与组内任一渲染器距离小于阈值
/// </summary>
private static bool IsCloseToAnyInGroup(Renderer renderer, List<Renderer> group, float maxDistance)
{
foreach (var groupRenderer in group)
{
float distance = CalculateDistance(renderer, groupRenderer);
if (distance <= maxDistance)
{
return true;
}
}
return false;
}
/// <summary>
/// 计算两个渲染器之间的距离
/// </summary>
private static float CalculateDistance(Renderer renderer1, Renderer renderer2)
{
return Vector3.Distance(renderer1.transform.position, renderer2.transform.position);
}
/// <summary>
/// 计算渲染组的中心点
/// </summary>
public static Vector3 CalculateGroupCenter(List<Renderer> group)
{
if (group.Count == 0)
return Vector3.zero;
var sum = Vector3.zero;
foreach (var renderer in group)
{
sum += renderer.transform.position;
}
return sum / group.Count;
}
/// <summary>
/// 根据圆形区域对渲染器进行分组(原始算法,保留作参考)
/// </summary>
public static Dictionary<string, List<Renderer>> GroupRenderersByCircularDistance(List<Renderer> renderers,
float maxDistance)
{
var groups = new Dictionary<string, List<Renderer>>();
var groupIndex = 0;
// 已分组的渲染器
var processedRenderers = new HashSet<Renderer>();
// 对所有渲染器进行处理
while (processedRenderers.Count < renderers.Count)
{
// 找到第一个未处理的渲染器作为新组的起点
Renderer startRenderer = FindFirstUnprocessedRenderer(renderers, processedRenderers);
if (startRenderer == null)
break;
// 创建新组
var currentGroup = new List<Renderer>();
currentGroup.Add(startRenderer);
processedRenderers.Add(startRenderer);
bool addedNew = true;
while (addedNew)
{
addedNew = false;
// 计算当前组的中心点
var groupCenter = CalculateGroupCenter(currentGroup);
// 查找距离中心点在阈值内的未处理渲染器
foreach (var renderer in renderers)
{
if (processedRenderers.Contains(renderer))
continue;
var distance = Vector3.Distance(groupCenter, renderer.transform.position);
if (!(distance <= maxDistance)) continue;
currentGroup.Add(renderer);
processedRenderers.Add(renderer);
addedNew = true;
}
}
groups.Add($"Group_{groupIndex}", currentGroup);
groupIndex++;
}
Debug.Log($"基于圆形区域分组:将{renderers.Count}个渲染器分成{groups.Count}个组,半径为{maxDistance}");
return groups;
}
}