111
This commit is contained in:
264
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/CamGeometryCapture.cs
vendored
Normal file
264
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/CamGeometryCapture.cs
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MeshCombineStudio
|
||||
{
|
||||
public class CamGeometryCapture : MonoBehaviour
|
||||
{
|
||||
public ComputeShader computeDepthToArray;
|
||||
public Int2 resolution = new Int2(1024, 1024);
|
||||
// public bool capture;
|
||||
// public float radius = 0.5f;
|
||||
|
||||
public Camera cam;
|
||||
public Transform t;
|
||||
|
||||
public RenderTexture rtCapture;
|
||||
|
||||
float[] heights;
|
||||
|
||||
Bounds bounds;
|
||||
|
||||
float maxSize;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
if (t != null) return;
|
||||
|
||||
t = transform;
|
||||
|
||||
cam = GetComponent<Camera>();
|
||||
|
||||
cam.aspect = 1;
|
||||
cam.orthographic = true;
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
DisposeRTCapture();
|
||||
}
|
||||
|
||||
//void Update()
|
||||
//{
|
||||
// if (capture)
|
||||
// {
|
||||
// capture = false;
|
||||
// Capture(mr.bounds, collisionMask.value, direction, resolution);
|
||||
// }
|
||||
//}
|
||||
|
||||
void DisposeRenderTexture(ref RenderTexture rt)
|
||||
{
|
||||
if (rt == null) return;
|
||||
|
||||
rt.Release();
|
||||
|
||||
#if UNITY_EDITOR
|
||||
DestroyImmediate(rt);
|
||||
#else
|
||||
Destroy(rt);
|
||||
#endif
|
||||
|
||||
rt = null;
|
||||
}
|
||||
|
||||
public void DisposeRTCapture()
|
||||
{
|
||||
cam.targetTexture = null;
|
||||
DisposeRenderTexture(ref rtCapture);
|
||||
}
|
||||
|
||||
public void RemoveTrianglesBelowSurface(Transform t, MeshCombineJobManager.MeshCombineJob meshCombineJob, MeshCache.SubMeshCache newMeshCache, ref byte[] vertexIsBelow)
|
||||
{
|
||||
if (vertexIsBelow == null) vertexIsBelow = new byte[65534];
|
||||
|
||||
Vector3 pos = Vector3.zero;
|
||||
int layerMask = meshCombineJob.meshCombiner.surfaceLayerMask;
|
||||
// float rayHeight = meshCombineJob.meshCombiner.maxSurfaceHeight;
|
||||
|
||||
Vector3[] newVertices = newMeshCache.vertices;
|
||||
int[] newTriangles = newMeshCache.triangles;
|
||||
|
||||
List<MeshObject> meshObjects = meshCombineJob.meshObjectsHolder.meshObjects;
|
||||
|
||||
int startIndex = meshCombineJob.startIndex;
|
||||
int endIndex = meshCombineJob.endIndex;
|
||||
|
||||
const byte belowSurface = 1, aboveSurface = 2;
|
||||
|
||||
for (int i = startIndex; i < endIndex; i++)
|
||||
{
|
||||
MeshObject meshObject = meshObjects[i];
|
||||
|
||||
Capture(meshObject.cachedGO.mr.bounds, layerMask, new Vector3(0, -1, 0), new Int2(1024, 1024));
|
||||
|
||||
int startTriangleIndex = meshObject.startNewTriangleIndex;
|
||||
int endTriangleIndex = meshObject.newTriangleCount + startTriangleIndex;
|
||||
|
||||
// Debug.Log("startIndex " + startIndex + " triangle " + startTriangleIndex + " - " + endTriangleIndex);
|
||||
|
||||
for (int j = startTriangleIndex; j < endTriangleIndex; j += 3)
|
||||
{
|
||||
bool isAboveSurface = false;
|
||||
|
||||
for (int k = 0; k < 3; k++)
|
||||
{
|
||||
int vertexIndex = newTriangles[j + k];
|
||||
if (vertexIndex == -1) continue;
|
||||
|
||||
byte isBelow = vertexIsBelow[vertexIndex];
|
||||
|
||||
if (isBelow == 0)
|
||||
{
|
||||
pos = t.TransformPoint(newVertices[vertexIndex]);
|
||||
|
||||
float height = GetHeight(pos);
|
||||
|
||||
isBelow = pos.y < height ? belowSurface : aboveSurface;
|
||||
vertexIsBelow[vertexIndex] = isBelow;
|
||||
|
||||
if (pos.y < height)
|
||||
{
|
||||
vertexIsBelow[vertexIndex] = isBelow = belowSurface;
|
||||
}
|
||||
else
|
||||
{
|
||||
vertexIsBelow[vertexIndex] = isBelow = aboveSurface;
|
||||
}
|
||||
}
|
||||
|
||||
if (isBelow != belowSurface) { isAboveSurface = true; break; }
|
||||
}
|
||||
|
||||
if (!isAboveSurface)
|
||||
{
|
||||
meshCombineJob.trianglesRemoved += 3;
|
||||
newTriangles[j] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Array.Clear(vertexIsBelow, 0, newVertices.Length);
|
||||
}
|
||||
|
||||
public void Capture(Bounds bounds, int collisionMask, Vector3 direction, Int2 resolution)
|
||||
{
|
||||
if (rtCapture == null || rtCapture.width != resolution.x || rtCapture.height != resolution.y)
|
||||
{
|
||||
if (rtCapture != null) DisposeRTCapture();
|
||||
|
||||
rtCapture = new RenderTexture(resolution.x, resolution.y, 16, RenderTextureFormat.Depth, RenderTextureReadWrite.Linear);
|
||||
}
|
||||
|
||||
bounds.size *= 1.1f;
|
||||
|
||||
this.bounds = bounds;
|
||||
|
||||
cam.targetTexture = rtCapture;
|
||||
cam.cullingMask = collisionMask;
|
||||
|
||||
SetCamera(direction);
|
||||
|
||||
cam.Render();
|
||||
|
||||
int heightsLength = resolution.x * resolution.y;
|
||||
|
||||
ComputeBuffer heightBuffer = new ComputeBuffer(heightsLength, 4);
|
||||
|
||||
computeDepthToArray.SetTexture(0, "rtDepth", rtCapture);
|
||||
computeDepthToArray.SetBuffer(0, "heightBuffer", heightBuffer);
|
||||
computeDepthToArray.SetInt("resolution", resolution.x);
|
||||
computeDepthToArray.SetFloat("captureHeight", t.position.y);
|
||||
computeDepthToArray.SetFloat("distance", bounds.size.y + 256);
|
||||
computeDepthToArray.SetInt("direction", direction.y == 1 ? 1 : -1);
|
||||
|
||||
computeDepthToArray.Dispatch(0, Mathf.CeilToInt(resolution.x / 8), Mathf.CeilToInt(resolution.y / 8), 1);
|
||||
|
||||
if (heights == null || heights.Length != heightsLength) heights = new float[heightsLength];
|
||||
|
||||
heightBuffer.GetData(heights);
|
||||
|
||||
// Debug.Log(bounds.size.x + " " + bounds.size.y + " " + bounds.size.z);
|
||||
|
||||
heightBuffer.Dispose();
|
||||
}
|
||||
|
||||
//private void OnDrawGizmos()
|
||||
//{
|
||||
// Gizmos.color = Color.red;
|
||||
|
||||
// Mesh m = mf.sharedMesh;
|
||||
// Vector3[] vertices = m.vertices;
|
||||
// // Vector3 startPos = new Vector3(t.position.x, 0, t.position.z) - new Vector3(maxSize / 2, 0, maxSize / 2);
|
||||
|
||||
// for (int i = 0; i < vertices.Length; i++)
|
||||
// {
|
||||
// Vector3 pos = mf.transform.TransformPoint(vertices[i]);
|
||||
// pos.y = GetHeight(pos);
|
||||
// Gizmos.DrawSphere(pos, radius);
|
||||
// }
|
||||
//}
|
||||
|
||||
public void SetCamera(Vector3 direction)
|
||||
{
|
||||
if (direction == new Vector3(0, 1, 0))
|
||||
{
|
||||
t.position = bounds.center - new Vector3(0, bounds.extents.y + 256, 0);
|
||||
}
|
||||
else if (direction == new Vector3(0, -1, 0))
|
||||
{
|
||||
t.position = bounds.center + new Vector3(0, bounds.extents.y + 256, 0);
|
||||
}
|
||||
|
||||
t.forward = direction;
|
||||
|
||||
maxSize = bounds.size.x;
|
||||
|
||||
if (bounds.size.z > maxSize) maxSize = bounds.size.z;
|
||||
|
||||
cam.orthographicSize = maxSize / 2;
|
||||
|
||||
cam.nearClipPlane = 0;
|
||||
cam.farClipPlane = (bounds.size.y + 256);
|
||||
}
|
||||
|
||||
public float GetHeight(Vector3 pos)
|
||||
{
|
||||
pos -= bounds.min;
|
||||
pos.x += (maxSize - bounds.size.x) / 2;
|
||||
pos.z += (maxSize - bounds.size.z) / 2;
|
||||
|
||||
float xx = maxSize / (resolution.x);
|
||||
float yy = maxSize / (resolution.y);
|
||||
|
||||
float x = (int)(pos.x / xx);
|
||||
float y = (int)(pos.z / yy);
|
||||
|
||||
if (x > resolution.x - 2 || x < 0 || y > resolution.y - 2 || y < 0)
|
||||
{
|
||||
Debug.Log("Out of bounds " + x + " " + y);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int intX = (int)x;
|
||||
int intY = (int)y;
|
||||
float lerpValue = x - intX;
|
||||
|
||||
float height0 = heights[intX + (intY * resolution.y)];
|
||||
float height1 = heights[intX + 1 + (intY * resolution.y)];
|
||||
|
||||
float heightx1 = Mathf.Lerp(height0, height1, lerpValue);
|
||||
|
||||
height0 = heights[intX + ((intY + 1) * resolution.y)];
|
||||
height1 = heights[intX + 1 + ((intY + 1) * resolution.y)];
|
||||
|
||||
float heightx2 = Mathf.Lerp(height0, height1, lerpValue);
|
||||
|
||||
lerpValue = y - intY;
|
||||
|
||||
return Mathf.Lerp(heightx1, heightx2, lerpValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/CamGeometryCapture.cs.meta
vendored
Normal file
11
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/CamGeometryCapture.cs.meta
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5118f6ea05613d14b899e139ed9dcbff
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
274
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/CombinedLODManager.cs
vendored
Normal file
274
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/CombinedLODManager.cs
vendored
Normal file
@@ -0,0 +1,274 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MeshCombineStudio
|
||||
{
|
||||
public class CombinedLODManager : MonoBehaviour
|
||||
{
|
||||
public enum LodMode { Automatic, DebugLod }
|
||||
public enum LodDistanceMode { Automatic, Manual }
|
||||
|
||||
public bool drawGizmos = true;
|
||||
public LOD[] lods;
|
||||
public float[] distances;
|
||||
public LodDistanceMode lodDistanceMode;
|
||||
public LodMode lodMode;
|
||||
public int showLod = 0;
|
||||
public bool lodCulled;
|
||||
public float lodCullDistance = 500;
|
||||
|
||||
public Vector3 octreeCenter = Vector3.zero;
|
||||
public Vector3 octreeSize = new Vector3(256, 256, 256);
|
||||
public int maxLevels = 4;
|
||||
public bool search = true;
|
||||
Cell octree;
|
||||
|
||||
Transform cameraMainT;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
cameraMainT = Camera.main.transform;
|
||||
}
|
||||
|
||||
void InitOctree()
|
||||
{
|
||||
octree = new Cell(octreeCenter, octreeSize, maxLevels);
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (search)
|
||||
{
|
||||
search = false;
|
||||
InitOctree();
|
||||
Search();
|
||||
}
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (octree.cellsUsed != null) Lod(lodMode);
|
||||
}
|
||||
|
||||
public void UpdateLods(MeshCombiner meshCombiner, int lodAmount)
|
||||
{
|
||||
if (lods != null && lods.Length == lodAmount) return;
|
||||
|
||||
lods = new LOD[lodAmount];
|
||||
float[] newDistances = new float[lodAmount];
|
||||
|
||||
for (int i = 0; i < lods.Length; i++)
|
||||
{
|
||||
lods[i] = new LOD();
|
||||
|
||||
if (lodDistanceMode == LodDistanceMode.Automatic) newDistances[i] = meshCombiner.cellSize * i;
|
||||
else if (distances != null && i < distances.Length) newDistances[i] = distances[i];
|
||||
}
|
||||
|
||||
distances = newDistances;
|
||||
}
|
||||
|
||||
public void UpdateDistances(MeshCombiner meshCombiner)
|
||||
{
|
||||
if (lodDistanceMode != LodDistanceMode.Automatic) return;
|
||||
|
||||
for (int i = 0; i < distances.Length; i++) distances[i] = meshCombiner.cellSize * i;
|
||||
}
|
||||
|
||||
public void Search()
|
||||
{
|
||||
for (int i = 0; i < lods.Length; i++)
|
||||
{
|
||||
lods[i].searchParent.gameObject.SetActive(true);
|
||||
MeshRenderer[] mrs = lods[i].searchParent.GetComponentsInChildren<MeshRenderer>();
|
||||
|
||||
for (int j = 0; j < mrs.Length; j++) octree.AddMeshRenderer(mrs[j], mrs[j].transform.position, i, lods.Length);
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetOctree()
|
||||
{
|
||||
if (octree == null) return;
|
||||
octree.cells = null;
|
||||
octree.cellsUsed = null;
|
||||
|
||||
for (int i = 0; i < lods.Length; i++)
|
||||
{
|
||||
if (lods[i].searchParent != null) Destroy(lods[i].searchParent.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
public void Lod(LodMode lodMode)
|
||||
{
|
||||
Vector3 cameraPosition = cameraMainT.position;
|
||||
|
||||
for (int i = 0; i < lods.Length - 1; i++)
|
||||
{
|
||||
lods[i].sphere.center = cameraPosition;
|
||||
lods[i].sphere.radius = distances[i + 1];
|
||||
}
|
||||
|
||||
// if (Benchmark.active) lodBenchmark.Start();
|
||||
if (lodMode == LodMode.Automatic) octree.AutoLodInternal(lods, lodCulled ? lodCullDistance : -1);
|
||||
else octree.LodInternal(lods, showLod);
|
||||
// if (Benchmark.active) lodBenchmark.Stop();
|
||||
}
|
||||
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
if (drawGizmos && octree != null && octree.cells != null) octree.DrawGizmos(lods);
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class LOD
|
||||
{
|
||||
public Transform searchParent;
|
||||
public Sphere3 sphere = new Sphere3();
|
||||
|
||||
public LOD() { }
|
||||
public LOD(Transform searchParent)
|
||||
{
|
||||
this.searchParent = searchParent;
|
||||
}
|
||||
}
|
||||
|
||||
public class Cell : BaseOctree.Cell
|
||||
{
|
||||
public Cell[] cells;
|
||||
AABB3 box;
|
||||
|
||||
public Cell() { }
|
||||
public Cell(Vector3 position, Vector3 size, int maxLevels) : base(position, size, maxLevels) { }
|
||||
|
||||
public void AddMeshRenderer(MeshRenderer mr, Vector3 position, int lodLevel, int lodLevels)
|
||||
{
|
||||
if (InsideBounds(position)) AddMeshRendererInternal(mr, position, lodLevel, lodLevels);
|
||||
}
|
||||
|
||||
void AddMeshRendererInternal(MeshRenderer mr, Vector3 position, int lodLevel, int lodLevels)
|
||||
{
|
||||
if (level == maxLevels)
|
||||
{
|
||||
MaxCell thisCell = (MaxCell)this;
|
||||
if (thisCell.mrList == null) thisCell.mrList = new List<MeshRenderer>[lodLevels];
|
||||
List<MeshRenderer>[] mrList = thisCell.mrList;
|
||||
|
||||
if (mrList[lodLevel] == null) mrList[lodLevel] = new List<MeshRenderer>();
|
||||
mrList[lodLevel].Add(mr);
|
||||
thisCell.currentLod = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool maxCellCreated;
|
||||
int index = AddCell<Cell, MaxCell>(ref cells, position, out maxCellCreated);
|
||||
cells[index].box = new AABB3(cells[index].bounds.min, cells[index].bounds.max);
|
||||
cells[index].AddMeshRendererInternal(mr, position, lodLevel, lodLevels);
|
||||
}
|
||||
}
|
||||
|
||||
public void AutoLodInternal(LOD[] lods, float lodCulledDistance)
|
||||
{
|
||||
if (level == maxLevels)
|
||||
{
|
||||
MaxCell thisCell = (MaxCell)this;
|
||||
if (lodCulledDistance != -1)
|
||||
{
|
||||
float squareDistance = (bounds.center - lods[0].sphere.center).sqrMagnitude;
|
||||
if (squareDistance > lodCulledDistance * lodCulledDistance)
|
||||
{
|
||||
if (thisCell.currentLod != -1)
|
||||
{
|
||||
for (int i = 0; i < lods.Length; i++)
|
||||
{
|
||||
for (int j = 0; j < thisCell.mrList[i].Count; j++) thisCell.mrList[i][j].enabled = false;
|
||||
}
|
||||
thisCell.currentLod = -1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (int lodIndex = 0; lodIndex < lods.Length; lodIndex++)
|
||||
{
|
||||
bool intersect;
|
||||
if (lodIndex < lods.Length - 1) intersect = Mathw.IntersectAABB3Sphere3(box, lods[lodIndex].sphere);
|
||||
else intersect = true;
|
||||
|
||||
if (intersect)
|
||||
{
|
||||
if (thisCell.currentLod != lodIndex)
|
||||
{
|
||||
for (int i = 0; i < lods.Length; i++)
|
||||
{
|
||||
bool active = (i == lodIndex);
|
||||
for (int j = 0; j < thisCell.mrList[i].Count; j++) thisCell.mrList[i][j].enabled = active;
|
||||
}
|
||||
thisCell.currentLod = lodIndex;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else for (int i = 0; i < 8; ++i) if (cellsUsed[i]) cells[i].AutoLodInternal(lods, lodCulledDistance);
|
||||
}
|
||||
|
||||
public void LodInternal(LOD[] lods, int lodLevel)
|
||||
{
|
||||
if (level == maxLevels)
|
||||
{
|
||||
MaxCell thisCell = (MaxCell)this;
|
||||
if (thisCell.currentLod != lodLevel)
|
||||
{
|
||||
for (int i = 0; i < lods.Length; i++)
|
||||
{
|
||||
bool active = (i == lodLevel);
|
||||
for (int j = 0; j < thisCell.mrList[i].Count; j++) thisCell.mrList[i][j].enabled = active;
|
||||
}
|
||||
|
||||
thisCell.currentLod = lodLevel;
|
||||
}
|
||||
}
|
||||
else for (int i = 0; i < 8; ++i) if (cellsUsed[i]) cells[i].LodInternal(lods, lodLevel);
|
||||
} //===============================================================================================================================
|
||||
|
||||
public void DrawGizmos(LOD[] lods)
|
||||
{
|
||||
for (int i = 0; i < lods.Length; i++)
|
||||
{
|
||||
if (i == 0) Gizmos.color = Color.red;
|
||||
else if (i == 1) Gizmos.color = Color.green;
|
||||
else if (i == 2) Gizmos.color = Color.yellow;
|
||||
else if (i == 3) Gizmos.color = Color.blue;
|
||||
|
||||
Gizmos.DrawWireSphere(lods[i].sphere.center, lods[i].sphere.radius);
|
||||
}
|
||||
|
||||
DrawGizmosInternal();
|
||||
}
|
||||
|
||||
public void DrawGizmosInternal()
|
||||
{
|
||||
if (level == maxLevels)
|
||||
{
|
||||
MaxCell thisCell = (MaxCell)this;
|
||||
if (thisCell.currentLod == 0) Gizmos.color = Color.red;
|
||||
else if (thisCell.currentLod == 1) Gizmos.color = Color.green;
|
||||
else if (thisCell.currentLod == 2) Gizmos.color = Color.yellow;
|
||||
else if (thisCell.currentLod == 3) Gizmos.color = Color.blue;
|
||||
|
||||
Gizmos.DrawWireCube(bounds.center, bounds.size - new Vector3(0.25f, 0.25f, 0.25f));
|
||||
|
||||
Gizmos.color = Color.white;
|
||||
}
|
||||
else for (int i = 0; i < 8; ++i) if (cellsUsed[i]) cells[i].DrawGizmosInternal();
|
||||
}
|
||||
}
|
||||
|
||||
public class MaxCell : Cell
|
||||
{
|
||||
public List<MeshRenderer>[] mrList;
|
||||
public int currentLod;
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/CombinedLODManager.cs.meta
vendored
Normal file
12
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/CombinedLODManager.cs.meta
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 01b543286c6d4484c9335dbf57a0b586
|
||||
timeCreated: 1496162540
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
37
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/ListMeshVertCount.cs
vendored
Normal file
37
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/ListMeshVertCount.cs
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
[ExecuteInEditMode]
|
||||
public class ListMeshVertCount : MonoBehaviour {
|
||||
|
||||
public bool includeInActive;
|
||||
public bool listVertCount;
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (listVertCount)
|
||||
{
|
||||
listVertCount = false;
|
||||
ListVertCount();
|
||||
}
|
||||
}
|
||||
|
||||
void ListVertCount()
|
||||
{
|
||||
MeshFilter[] mfs = GetComponentsInChildren<MeshFilter>(includeInActive);
|
||||
|
||||
int vertCount = 0;
|
||||
int triangleCount = 0;
|
||||
|
||||
for (int i = 0; i < mfs.Length; i++)
|
||||
{
|
||||
Mesh m = mfs[i].sharedMesh;
|
||||
if (m == null) continue;
|
||||
vertCount += m.vertexCount;
|
||||
triangleCount += m.triangles.Length;
|
||||
}
|
||||
|
||||
Debug.Log(gameObject.name + " Vertices " + vertCount + " Triangles " + triangleCount);
|
||||
}
|
||||
}
|
||||
12
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/ListMeshVertCount.cs.meta
vendored
Normal file
12
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/ListMeshVertCount.cs.meta
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d9eaad923cc4fca4396a6e2ec092b9e9
|
||||
timeCreated: 1507213037
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1401
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/MeshCombineJobManager.cs
vendored
Normal file
1401
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/MeshCombineJobManager.cs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
12
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/MeshCombineJobManager.cs.meta
vendored
Normal file
12
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/MeshCombineJobManager.cs.meta
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 409bc0be2fd0301499c7685349d5eef7
|
||||
timeCreated: 1509346503
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1047
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/MeshCombiner.cs
vendored
Normal file
1047
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/MeshCombiner.cs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
10
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/MeshCombiner.cs.meta
vendored
Normal file
10
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/MeshCombiner.cs.meta
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c7fb52db265e28e4eb22d6300d01e030
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
111
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/ObjectSpawner.cs
vendored
Normal file
111
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/ObjectSpawner.cs
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MeshCombineStudio
|
||||
{
|
||||
[ExecuteInEditMode]
|
||||
public class ObjectSpawner : MonoBehaviour
|
||||
{
|
||||
public GameObject[] objects;
|
||||
|
||||
public float density = 0.5f;
|
||||
public Vector2 scaleRange = new Vector2(0.5f, 2f);
|
||||
public Vector3 rotationRange = new Vector3(5, 360, 5);
|
||||
public Vector2 heightRange = new Vector2(0, 1);
|
||||
|
||||
public float scaleMulti = 1;
|
||||
|
||||
public float resolutionPerMeter = 2;
|
||||
public bool spawnInRuntime;
|
||||
public bool spawn;
|
||||
public bool deleteChildren;
|
||||
|
||||
|
||||
Transform t;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
t = transform;
|
||||
|
||||
if (spawnInRuntime && Application.isPlaying)
|
||||
{
|
||||
Spawn();
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (spawn)
|
||||
{
|
||||
spawn = false;
|
||||
Spawn();
|
||||
}
|
||||
if (deleteChildren)
|
||||
{
|
||||
deleteChildren = false;
|
||||
DeleteChildren();
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteChildren()
|
||||
{
|
||||
Transform[] transforms = GetComponentsInChildren<Transform>();
|
||||
|
||||
for (int i = 0; i < transforms.Length; i++)
|
||||
{
|
||||
if (t != transforms[i] && transforms[i] != null) DestroyImmediate(transforms[i].gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
public void Spawn()
|
||||
{
|
||||
Bounds bounds = new Bounds();
|
||||
bounds.center = transform.position;
|
||||
bounds.size = transform.lossyScale;
|
||||
|
||||
float xStart = bounds.min.x;
|
||||
float xEnd = bounds.max.x;
|
||||
float yStart = bounds.min.y;
|
||||
float yEnd = bounds.max.y;
|
||||
float zStart = bounds.min.z;
|
||||
float zEnd = bounds.max.z;
|
||||
|
||||
int objectCount = objects.Length;
|
||||
float halfRes = resolutionPerMeter * 0.5f;
|
||||
float heightOffset = transform.lossyScale.y * 0.5f;
|
||||
int count = 0;
|
||||
|
||||
for (float z = zStart; z < zEnd; z += resolutionPerMeter)
|
||||
{
|
||||
for (float x = xStart; x < xEnd; x += resolutionPerMeter)
|
||||
{
|
||||
for (float y = yStart; y < yEnd; y += resolutionPerMeter)
|
||||
{
|
||||
int index = Random.Range(0, objectCount);
|
||||
float spawnValue = Random.value;
|
||||
if (spawnValue < density)
|
||||
{
|
||||
Vector3 pos = new Vector3(x + Random.Range(-halfRes, halfRes), yStart + (Random.Range(0, bounds.size.y) * Random.Range(heightRange.x, heightRange.y)), z + Random.Range(-halfRes, halfRes));
|
||||
if (pos.x < xStart || pos.x > xEnd || pos.y < yStart || pos.y > yEnd || pos.z < zStart || pos.z > zEnd) continue;
|
||||
pos.y += heightOffset;
|
||||
Vector3 eulerAngles = new Vector3(Random.Range(0, rotationRange.x), Random.Range(0, rotationRange.y), Random.Range(0, rotationRange.z));
|
||||
GameObject go = (GameObject)Instantiate(objects[index], pos, Quaternion.Euler(eulerAngles));
|
||||
float scale = Random.Range(scaleRange.x, scaleRange.y) * scaleMulti;
|
||||
go.transform.localScale = new Vector3(scale, scale, scale);
|
||||
go.transform.parent = t;
|
||||
++count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log("Spawned " + count);
|
||||
}
|
||||
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
Gizmos.DrawWireCube(transform.position + new Vector3(0, transform.lossyScale.y * 0.5f, 0), transform.lossyScale);
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/ObjectSpawner.cs.meta
vendored
Normal file
12
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/ObjectSpawner.cs.meta
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 80e3d5613a0399b4b87617ecc61c7c94
|
||||
timeCreated: 1505205806
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
276
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/RemoveGeometryBelowTerrain.cs
vendored
Normal file
276
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/RemoveGeometryBelowTerrain.cs
vendored
Normal file
@@ -0,0 +1,276 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
// This feature will be added in the next update
|
||||
|
||||
namespace MeshCombineStudio
|
||||
{
|
||||
public class RemoveGeometryBelowTerrain : MonoBehaviour
|
||||
{
|
||||
int totalTriangles;
|
||||
int removeTriangles;
|
||||
int skippedObjects;
|
||||
|
||||
public List<Transform> terrains = new List<Transform>();
|
||||
public List<Transform> meshTerrains = new List<Transform>();
|
||||
|
||||
public Bounds[] terrainBounds, meshBounds;
|
||||
|
||||
Terrain[] terrainComponents;
|
||||
Terrain[] terrainArray;
|
||||
Bounds[] terrainBoundsArray; //, meshBoundsArray;
|
||||
|
||||
MeshRenderer[] mrs;
|
||||
Mesh[] meshTerrainComponents;
|
||||
Mesh[] meshArray;
|
||||
|
||||
public bool runOnStart;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (runOnStart)
|
||||
{
|
||||
Remove(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove(GameObject go)
|
||||
{
|
||||
MeshFilter[] mfs = go.GetComponentsInChildren<MeshFilter>(true);
|
||||
totalTriangles = 0;
|
||||
removeTriangles = 0;
|
||||
skippedObjects = 0;
|
||||
|
||||
for (int i = 0; i < mfs.Length; i++)
|
||||
{
|
||||
RemoveMesh(mfs[i].transform, mfs[i].mesh);
|
||||
}
|
||||
|
||||
Debug.Log("Removeable " + removeTriangles + " total " + totalTriangles + " improvement " + (((float)removeTriangles / totalTriangles) * 100).ToString("F2"));
|
||||
Debug.Log("Skipped Objects " + skippedObjects);
|
||||
}
|
||||
|
||||
public void RemoveMesh(Transform t, Mesh mesh)
|
||||
{
|
||||
if (mesh == null) return;
|
||||
if (!(IsMeshUnderTerrain(t, mesh))) { ++skippedObjects; return; }
|
||||
|
||||
Vector3[] vertices = mesh.vertices;
|
||||
List<int> newTriangles = new List<int>();
|
||||
|
||||
for (int i = 0; i < mesh.subMeshCount; i++)
|
||||
{
|
||||
newTriangles.AddRange(mesh.GetTriangles(i));
|
||||
int length = newTriangles.Count;
|
||||
RemoveTriangles(t, newTriangles, vertices);
|
||||
|
||||
if (newTriangles.Count < length) mesh.SetTriangles(newTriangles.ToArray(), i);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsMeshUnderTerrain(Transform t, Mesh mesh)
|
||||
{
|
||||
Bounds bounds = mesh.bounds;
|
||||
bounds.center += t.position;
|
||||
|
||||
Vector3 min = bounds.min;
|
||||
Vector3 max = bounds.max;
|
||||
//Vector3 center = bounds.center;
|
||||
|
||||
Vector2 delta = new Vector2(max.x - min.x, max.z - min.z);
|
||||
|
||||
for (float z = 0; z < 1; z += 0.125f)
|
||||
{
|
||||
for (float x = 0; x < 1; x += 0.125f)
|
||||
{
|
||||
Vector3 p = new Vector3(min.x + (x * delta.x), min.y, min.z + (z * delta.y));
|
||||
float height = 0;// terrainColliderCam.GetHeight(p);
|
||||
if (p.y < height) return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void GetTerrainComponents()
|
||||
{
|
||||
terrainComponents = new Terrain[terrains.Count];
|
||||
|
||||
for (int i = 0; i < terrains.Count; i++)
|
||||
{
|
||||
Terrain terrain = terrains[i].GetComponent<Terrain>();
|
||||
terrainComponents[i] = terrain;
|
||||
}
|
||||
}
|
||||
|
||||
public void GetMeshRenderersAndComponents()
|
||||
{
|
||||
mrs = new MeshRenderer[meshTerrains.Count];
|
||||
meshTerrainComponents = new Mesh[meshTerrains.Count];
|
||||
|
||||
for (int i = 0; i < meshTerrains.Count; i++)
|
||||
{
|
||||
mrs[i] = meshTerrains[i].GetComponent<MeshRenderer>();
|
||||
MeshFilter mf = meshTerrains[i].GetComponent<MeshFilter>();
|
||||
meshTerrainComponents[i] = mf.sharedMesh;
|
||||
}
|
||||
}
|
||||
|
||||
public void CreateTerrainBounds()
|
||||
{
|
||||
terrainBounds = new Bounds[terrainComponents.Length];
|
||||
|
||||
for (int i = 0; i < terrainBounds.Length; i++)
|
||||
{
|
||||
terrainBounds[i] = new Bounds();
|
||||
terrainBounds[i].min = terrains[i].position;
|
||||
terrainBounds[i].max = terrainBounds[i].min + terrainComponents[i].terrainData.size;
|
||||
}
|
||||
|
||||
meshBounds = new Bounds[meshTerrains.Count];
|
||||
|
||||
for (int i = 0; i < meshTerrains.Count; i++)
|
||||
{
|
||||
meshBounds[i] = mrs[i].bounds;
|
||||
}
|
||||
}
|
||||
|
||||
public void MakeIntersectLists(Bounds bounds)
|
||||
{
|
||||
List<Terrain> terrainList = new List<Terrain>();
|
||||
List<Mesh> meshList = new List<Mesh>();
|
||||
List<Bounds> terrainBoundsList = new List<Bounds>();
|
||||
List<Bounds> meshBoundsList = new List<Bounds>();
|
||||
|
||||
Vector3[] pos = new Vector3[8];
|
||||
Vector3 size = bounds.size;
|
||||
|
||||
pos[0] = bounds.min;
|
||||
pos[1] = pos[0] + new Vector3(size.x, 0, 0);
|
||||
pos[2] = pos[0] + new Vector3(0, 0, size.z);
|
||||
pos[3] = pos[0] + new Vector3(size.x, 0, size.z);
|
||||
pos[4] = pos[0] + new Vector3(0, size.y, 0);
|
||||
pos[5] = pos[0] + new Vector3(size.x, size.y, 0);
|
||||
pos[6] = pos[0] + new Vector3(0, size.y, size.z);
|
||||
pos[7] = pos[0] + size;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
int index = InterectTerrain(pos[i]);
|
||||
if (index != -1)
|
||||
{
|
||||
terrainList.Add(terrainArray[index]);
|
||||
terrainBoundsList.Add(terrainBounds[index]);
|
||||
}
|
||||
|
||||
index = InterectMesh(pos[i]);
|
||||
if (index != -1)
|
||||
{
|
||||
meshList.Add(meshArray[index]);
|
||||
meshBoundsList.Add(meshBounds[index]);
|
||||
}
|
||||
}
|
||||
|
||||
terrainArray = terrainList.ToArray();
|
||||
meshArray = meshList.ToArray();
|
||||
terrainBoundsArray = terrainBoundsList.ToArray();
|
||||
// meshBoundsArray = meshBoundsList.ToArray();
|
||||
}
|
||||
|
||||
public int InterectTerrain(Vector3 pos)
|
||||
{
|
||||
for (int i = 0; i < terrainBounds.Length; i++)
|
||||
{
|
||||
if (terrainBounds[i].Contains(pos)) return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int InterectMesh(Vector3 pos)
|
||||
{
|
||||
for (int i = 0; i < meshBounds.Length; i++)
|
||||
{
|
||||
if (meshBounds[i].Contains(pos)) return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Ray ray = new Ray(Vector3.zero, Vector3.down);
|
||||
|
||||
public float GetTerrainHeight(Vector3 pos)
|
||||
{
|
||||
int index = -1;
|
||||
|
||||
for (int i = 0; i < terrainArray.Length; i++)
|
||||
{
|
||||
if (terrainBoundsArray[i].Contains(pos)) { index = i; break; }
|
||||
}
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
return terrainArray[index].SampleHeight(pos);
|
||||
}
|
||||
return Mathf.Infinity;
|
||||
}
|
||||
|
||||
public void RemoveTriangles(Transform t, List<int> newTriangles, Vector3[] vertices)
|
||||
{
|
||||
bool[] verticeIsBelow = new bool[vertices.Length];
|
||||
|
||||
Vector3 pos = Vector3.zero;
|
||||
float height = 0;
|
||||
|
||||
for (int j = 0; j < newTriangles.Count; j += 3)
|
||||
{
|
||||
++totalTriangles;
|
||||
int verticeIndex = newTriangles[j];
|
||||
bool isBelow = verticeIsBelow[verticeIndex];
|
||||
|
||||
if (!isBelow)
|
||||
{
|
||||
pos = t.TransformPoint(vertices[verticeIndex]);
|
||||
height = GetTerrainHeight(pos);
|
||||
isBelow = pos.y < height;
|
||||
}
|
||||
|
||||
if (isBelow)
|
||||
{
|
||||
verticeIsBelow[verticeIndex] = true;
|
||||
verticeIndex = newTriangles[j + 1];
|
||||
isBelow = verticeIsBelow[verticeIndex];
|
||||
if (!isBelow)
|
||||
{
|
||||
pos = t.TransformPoint(vertices[verticeIndex]);
|
||||
height = GetTerrainHeight(pos);
|
||||
isBelow = pos.y < height;
|
||||
}
|
||||
if (isBelow)
|
||||
{
|
||||
verticeIsBelow[verticeIndex] = true;
|
||||
verticeIndex = newTriangles[j + 2];
|
||||
isBelow = verticeIsBelow[verticeIndex];
|
||||
if (!isBelow)
|
||||
{
|
||||
pos = t.TransformPoint(vertices[verticeIndex]);
|
||||
height = GetTerrainHeight(pos);
|
||||
isBelow = pos.y < height;
|
||||
}
|
||||
if (isBelow)
|
||||
{
|
||||
verticeIsBelow[verticeIndex] = true;
|
||||
++removeTriangles;
|
||||
newTriangles.RemoveAt(j + 2);
|
||||
newTriangles.RemoveAt(j + 1);
|
||||
newTriangles.RemoveAt(j);
|
||||
|
||||
if (j + 3 < newTriangles.Count) j -= 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/RemoveGeometryBelowTerrain.cs.meta
vendored
Normal file
12
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/RemoveGeometryBelowTerrain.cs.meta
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f47068a0804dcdf41a46c89f754480ed
|
||||
timeCreated: 1496067184
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
56
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/SwapCombineKey.cs
vendored
Normal file
56
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/SwapCombineKey.cs
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MeshCombineStudio
|
||||
{
|
||||
public class SwapCombineKey : MonoBehaviour
|
||||
{
|
||||
static public SwapCombineKey instance;
|
||||
public List<MeshCombiner> meshCombinerList = new List<MeshCombiner>();
|
||||
MeshCombiner meshCombiner;
|
||||
GUIStyle textStyle;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
instance = this;
|
||||
meshCombiner = GetComponent<MeshCombiner>();
|
||||
meshCombinerList.Add(meshCombiner);
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
instance = null;
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (Input.GetKeyDown(KeyCode.Tab))
|
||||
{
|
||||
QualitySettings.vSyncCount = 0;
|
||||
meshCombiner.SwapCombine();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
if (textStyle == null)
|
||||
{
|
||||
textStyle = new GUIStyle("label");
|
||||
textStyle.fontStyle = FontStyle.Bold;
|
||||
textStyle.fontSize = 16;
|
||||
}
|
||||
|
||||
textStyle.normal.textColor = this.meshCombiner.combinedActive ? Color.green : Color.red;
|
||||
|
||||
GUI.Label(new Rect(10, 45 + (meshCombinerList.Count * 22), 200, 30), "Toggle with 'Tab' key.", textStyle);
|
||||
|
||||
for (int i = 0; i < meshCombinerList.Count; i++)
|
||||
{
|
||||
MeshCombiner meshCombiner = meshCombinerList[i];
|
||||
if (meshCombiner.combinedActive) GUI.Label(new Rect(10, 30 + (i * 22), 300, 30), meshCombiner.gameObject.name + " is Enabled.", textStyle);
|
||||
else GUI.Label(new Rect(10, 30 + (i * 22), 300, 30), meshCombiner.gameObject.name + " is Disabled.", textStyle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/SwapCombineKey.cs.meta
vendored
Normal file
12
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/SwapCombineKey.cs.meta
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3c430fd3101f200428cac71e6b69b0dc
|
||||
timeCreated: 1505065196
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
372
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/Voxelize.cs
vendored
Normal file
372
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/Voxelize.cs
vendored
Normal file
@@ -0,0 +1,372 @@
|
||||
//using System.Collections;
|
||||
//using System.Collections.Generic;
|
||||
//using UnityEngine;
|
||||
//using MeshCombineStudio;
|
||||
//using System;
|
||||
|
||||
//namespace MeshCombineStudio
|
||||
//{
|
||||
// static public class Voxelize
|
||||
// {
|
||||
// static readonly byte[] bits = new byte[] { 1, 2, 4, 8, 16, 32, 64, 128 };
|
||||
|
||||
// static Dictionary<Mesh, VoxelizedMesh> voxelizedLookup = new Dictionary<Mesh, VoxelizedMesh>();
|
||||
|
||||
// static List<float> intersectList = new List<float>();
|
||||
|
||||
// const byte insideVoxel = 1;
|
||||
// const byte outsideVoxel = 2;
|
||||
|
||||
// public class VoxelizedMesh
|
||||
// {
|
||||
// public byte[,,] volume;
|
||||
// public Bounds bounds;
|
||||
// public Int3 voxels;
|
||||
// }
|
||||
|
||||
// static VoxelizedMesh VoxelizeMesh(Transform t, float voxelResolution, int voxelizeLayer)
|
||||
// {
|
||||
// // TODO ray cast from right/left and top/down
|
||||
|
||||
// MeshRenderer mr = t.GetComponent<MeshRenderer>();
|
||||
// if (mr == null) return null;
|
||||
|
||||
// MeshFilter mf = t.GetComponent<MeshFilter>();
|
||||
// if (mf == null) return null;
|
||||
|
||||
// Mesh mesh = mf.sharedMesh;
|
||||
// if (mesh == null) return null;
|
||||
|
||||
// VoxelizedMesh vm = new VoxelizedMesh();
|
||||
// voxelizedLookup.Add(mesh, vm);
|
||||
|
||||
// Transform oldParent = t.parent;
|
||||
// Vector3 oldPos = t.position;
|
||||
// Quaternion oldRot = t.rotation;
|
||||
// Vector3 oldScale = t.localScale;
|
||||
|
||||
// t.parent = null;
|
||||
// t.position = Vector3.zero;
|
||||
// t.rotation = Quaternion.identity;
|
||||
// t.localScale = Vector3.one;
|
||||
// int oldLayer = t.gameObject.layer;
|
||||
// t.gameObject.layer = voxelizeLayer;
|
||||
|
||||
// LayerMask voxelizeLayerMask = 1 << voxelizeLayer;
|
||||
|
||||
// Bounds bounds = mr.bounds;
|
||||
|
||||
// Vector3 size = bounds.size;
|
||||
// Int3 voxels = new Int3(Mathf.CeilToInt(size.x / voxelResolution), Mathf.CeilToInt(size.y / voxelResolution), Mathf.CeilToInt(size.z / voxelResolution));
|
||||
// voxels += new Int3(2, 2, 2);
|
||||
// int voxelsX = Mathf.CeilToInt(voxels.x / 8f);
|
||||
|
||||
// vm.voxels = voxels;
|
||||
|
||||
// size = new Vector3(voxels.x * voxelResolution, voxels.y * voxelResolution, voxels.z * voxelResolution);
|
||||
// bounds.size = size;
|
||||
// vm.bounds = bounds;
|
||||
|
||||
// byte[,,] volume = new byte[voxelsX, voxels.y, voxels.z];
|
||||
|
||||
// Ray ray = new Ray();
|
||||
// Ray ray2 = new Ray();
|
||||
|
||||
// ray.direction = Vector3.forward;
|
||||
// ray2.direction = Vector3.back;
|
||||
// Vector3 pos = bounds.min;
|
||||
// Vector3 pos2 = pos;
|
||||
// pos2.z = bounds.max.z;
|
||||
|
||||
// // Debug.Log(PrintVector3(mr.bounds.size) + " new size " + PrintVector3(size) + " voxels " + voxels);
|
||||
// int voxelCount = 0;
|
||||
|
||||
// Vector3 halfVoxel = Vector3.one * voxelResolution * 0.5f;
|
||||
// Vector3 minBoundsVoxel = pos + halfVoxel;
|
||||
|
||||
// try
|
||||
// {
|
||||
// for (int x = 0; x < voxels.x; x++)
|
||||
// {
|
||||
// int xGrid = x / 8;
|
||||
// byte bit = bits[x - (xGrid * 8)];
|
||||
|
||||
// for (int y = 0; y < voxels.y; y++)
|
||||
// {
|
||||
// Vector3 origin = pos + new Vector3((x + 0.5f) * voxelResolution, (y + 0.5f) * voxelResolution, 0);
|
||||
// ray.origin = origin;
|
||||
// origin.z = pos2.z;
|
||||
// ray2.origin = origin;
|
||||
|
||||
// intersectList.Clear();
|
||||
|
||||
// MultiCast(ray, intersectList, 0.001f, size.z, voxelizeLayerMask);
|
||||
// MultiCast(ray2, intersectList, -0.001f, size.z, voxelizeLayerMask);
|
||||
|
||||
// intersectList.Sort();
|
||||
|
||||
// float half = (float)intersectList.Count / 2;
|
||||
// if (half != (int)half) { continue; }
|
||||
|
||||
// // Debug.Log(hitInfos.Length +" " + hitInfos2.Length +" " + list.Count);
|
||||
|
||||
// for (int i = 0; i < intersectList.Count; i += 2)
|
||||
// {
|
||||
// int z1 = Mathf.RoundToInt((intersectList[i] - pos.z) / voxelResolution);
|
||||
// int z2 = Mathf.RoundToInt((intersectList[i + 1] - pos.z) / voxelResolution);
|
||||
|
||||
// for (int z = z1; z < z2; z++)
|
||||
// {
|
||||
// Vector3 voxelPos = new Vector3(x * voxelResolution, y * voxelResolution, z * voxelResolution) + minBoundsVoxel;
|
||||
// voxelPos = t.TransformPoint(voxelPos);
|
||||
|
||||
// // volume[xGrid, y, z] |= bit;
|
||||
// // if (!Physics.CheckBox(voxelPos, halfVoxel, Quaternion.identity, voxelizeLayerMask))
|
||||
// {
|
||||
// volume[xGrid, y, z] |= bit;
|
||||
// ++voxelCount;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// Debug.LogError(e.ToString());
|
||||
// }
|
||||
|
||||
// // Debug.Log(t.name + " voxels " + voxelCount);
|
||||
|
||||
// vm.volume = volume;
|
||||
|
||||
// t.gameObject.layer = oldLayer;
|
||||
// t.parent = oldParent;
|
||||
// t.position = oldPos;
|
||||
// t.rotation = oldRot;
|
||||
// t.localScale = oldScale;
|
||||
|
||||
// return vm;
|
||||
// }
|
||||
|
||||
// static string PrintVector3(Vector3 v)
|
||||
// {
|
||||
// return "(" + v.x + ", " + v.y + ", " + v.z + ")";
|
||||
// }
|
||||
|
||||
// static void MultiCast(Ray ray, List<float> points, float hitOffset, float maxDistance, LayerMask voxelizeLayerMask)
|
||||
// {
|
||||
// RaycastHit hitInfo;
|
||||
|
||||
// while (Physics.Raycast(ray, out hitInfo, maxDistance, voxelizeLayerMask))
|
||||
// {
|
||||
// points.Add(hitInfo.point.z);
|
||||
|
||||
// Vector3 origin = ray.origin;
|
||||
// ray.origin = new Vector3(origin.x, origin.y, hitInfo.point.z + hitOffset);
|
||||
// }
|
||||
// }
|
||||
|
||||
// static void Report(VoxelizedMesh vm, float voxelResolution)
|
||||
// {
|
||||
// int voxelResolutionX = (int)voxelResolution / 8;
|
||||
|
||||
// for (int x = 0; x < voxelResolutionX; x++)
|
||||
// {
|
||||
// for (int y = 0; y < voxelResolution; y++)
|
||||
// {
|
||||
// for (int z = 0; z < voxelResolution; z++)
|
||||
// {
|
||||
// Debug.Log(vm.volume[x, y, z]);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// static public void RemoveOverlap(Transform t, MeshCombineJobManager.MeshCombineJob meshCombineJob, MeshCache.SubMeshCache newMeshCache, ref byte[] vertexIsInsideVoxels)
|
||||
// {
|
||||
// if (vertexIsInsideVoxels == null) vertexIsInsideVoxels = new byte[65534];
|
||||
|
||||
// float voxelResolution = meshCombineJob.meshCombiner.voxelResolution;
|
||||
// int voxelizeLayer = meshCombineJob.meshCombiner.voxelizeLayer;
|
||||
|
||||
// Vector3[] newVertices = newMeshCache.vertices;
|
||||
// int[] newTriangles = newMeshCache.triangles;
|
||||
|
||||
// List<MeshObject> meshObjects = meshCombineJob.meshObjectsHolder.meshObjects;
|
||||
|
||||
// int startIndex = meshCombineJob.startIndex;
|
||||
// int endIndex = meshCombineJob.endIndex;
|
||||
|
||||
// for (int a = startIndex; a < endIndex; a++)
|
||||
// {
|
||||
// MeshObject meshObject = meshObjects[a];
|
||||
// CachedGameObject cachedGO = meshObject.cachedGO;
|
||||
|
||||
// // Get array of intersections
|
||||
// // Bounds bounds = cachedGO.mr.bounds;
|
||||
// Collider[] colliders = null;//!! Physics.OverlapBox(bounds.center, bounds.extents, Quaternion.identity, meshCombineJob.meshCombiner.overlapLayerMask);
|
||||
|
||||
// if (colliders.Length == 0)
|
||||
// {
|
||||
// // Debug.Log("No overlap " + cachedGO.go.name);
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// // Debug.Log("Overlaps " + colliders.Length);
|
||||
|
||||
// Transform[] colliderTs = new Transform[colliders.Length];
|
||||
// VoxelizedMesh[] colliderVms = new VoxelizedMesh[colliders.Length];
|
||||
|
||||
// for (int i = 0; i < colliderVms.Length; i++)
|
||||
// {
|
||||
// colliderTs[i] = colliders[i].transform;
|
||||
|
||||
// if (colliderTs[i] == cachedGO.t) continue;
|
||||
|
||||
// MeshFilter mf = colliderTs[i].GetComponent<MeshFilter>();
|
||||
// if (mf == null) continue;
|
||||
|
||||
// Mesh mesh = mf.sharedMesh;
|
||||
// if (mesh == null) continue;
|
||||
|
||||
// voxelizedLookup.TryGetValue(mesh, out colliderVms[i]);
|
||||
|
||||
// if (colliderVms[i] == null) colliderVms[i] = VoxelizeMesh(colliderTs[i], voxelResolution, voxelizeLayer);
|
||||
|
||||
// // Debug.LogError("Couldn't find voxelized mesh for " + mo.m + " " + child.name);
|
||||
// }
|
||||
|
||||
// float invVoxelResolution = 1 / voxelResolution;
|
||||
|
||||
// int startTriangleIndex = meshObject.startNewTriangleIndex;
|
||||
// int endTriangleIndex = meshObject.newTriangleCount + startTriangleIndex;
|
||||
|
||||
// // Debug.Log("start " + startTriangleIndex + " end " + endTriangleIndex);
|
||||
|
||||
// for (int i = startTriangleIndex; i < endTriangleIndex; i += 3)
|
||||
// {
|
||||
// bool insideAllVoxels = true;
|
||||
|
||||
// for (int k = 0; k < 3; k++)
|
||||
// {
|
||||
// int vertexIndex = newTriangles[i + k];
|
||||
// if (vertexIndex == -1) continue;
|
||||
|
||||
// byte isInsideVoxel = vertexIsInsideVoxels[vertexIndex];
|
||||
|
||||
// if (isInsideVoxel == 0)
|
||||
// {
|
||||
// bool inside = false;
|
||||
|
||||
// for (int j = 0; j < colliders.Length; j++)
|
||||
// {
|
||||
// Transform colliderT = colliderTs[j];
|
||||
// VoxelizedMesh colliderVm = colliderVms[j];
|
||||
// if (colliderVm == null) continue;
|
||||
|
||||
// Vector3 boundsMin = colliderVm.bounds.min;
|
||||
|
||||
// Vector3 vertPos = t.TransformPoint(newVertices[vertexIndex]);
|
||||
|
||||
// Vector3 pos = colliderT.InverseTransformPoint(vertPos) - boundsMin;
|
||||
// Vector3 grid = new Vector3(pos.x * invVoxelResolution, pos.y * invVoxelResolution, pos.z * invVoxelResolution);
|
||||
|
||||
// if (grid.x < 0 || grid.x >= colliderVm.voxels.x || grid.y < 0 || grid.y >= colliderVm.voxels.y || grid.z < 0 || grid.z >= colliderVm.voxels.z) continue;
|
||||
|
||||
// int xGrid = (int)grid.x;
|
||||
// int xxGrid = xGrid / 8;
|
||||
// byte bit = bits[(xGrid - (xxGrid * 8))];
|
||||
|
||||
// if ((colliderVm.volume[xxGrid, (int)grid.y, (int)grid.z] & bit) == 0) continue;
|
||||
|
||||
// inside = true;
|
||||
// break;
|
||||
// }
|
||||
|
||||
// vertexIsInsideVoxels[vertexIndex] = isInsideVoxel = (inside ? insideVoxel : outsideVoxel);
|
||||
// }
|
||||
|
||||
// if (isInsideVoxel == outsideVoxel)
|
||||
// {
|
||||
// insideAllVoxels = false;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (insideAllVoxels)
|
||||
// {
|
||||
// meshCombineJob.trianglesRemoved += 3;
|
||||
// newTriangles[i] = -1;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// Array.Clear(vertexIsInsideVoxels, 0, newMeshCache.vertexCount);
|
||||
|
||||
// // Debug.Log("Removed " + meshCombineJob.trianglesRemoved);
|
||||
|
||||
// newMeshCache.triangles = newTriangles;
|
||||
// }
|
||||
|
||||
// static public void DrawGizmos(GameObject go, float voxelResolution)
|
||||
// {
|
||||
// Transform[] ts = go.GetComponentsInChildren<Transform>();
|
||||
|
||||
// Gizmos.color = Color.red;
|
||||
|
||||
// for (int i = 0; i < ts.Length; i++) DrawVolume(ts[i], voxelResolution);
|
||||
|
||||
// Gizmos.color = Color.white;
|
||||
// }
|
||||
|
||||
// static public void DrawVolume(Transform t, float voxelResolution)
|
||||
// {
|
||||
// MeshRenderer mr = t.GetComponent<MeshRenderer>();
|
||||
// if (mr == null) return;
|
||||
|
||||
// MeshFilter mf = t.GetComponent<MeshFilter>();
|
||||
// if (mf == null) return;
|
||||
|
||||
// Mesh m = mf.sharedMesh;
|
||||
// if (m == null) return;
|
||||
|
||||
// VoxelizedMesh vm;
|
||||
// voxelizedLookup.TryGetValue(m, out vm);
|
||||
// if (vm == null) return;
|
||||
|
||||
// byte[,,] volume = vm.volume;
|
||||
// if (volume == null) return;
|
||||
|
||||
// Vector3 pos = vm.bounds.min;
|
||||
|
||||
// Vector3 voxel = t.lossyScale * voxelResolution;
|
||||
// Vector3 halfVoxel = Vector3.one * voxelResolution * 0.5f;
|
||||
|
||||
// Int3 voxels = vm.voxels;
|
||||
// // Debug.Log(voxels);
|
||||
// // Debug.Log(volume.Length);
|
||||
|
||||
// Gizmos.DrawWireCube(mr.bounds.center, mr.bounds.size);
|
||||
|
||||
// for (int x = 0; x < voxels.x; x++)
|
||||
// {
|
||||
// int xGrid = x / 8;
|
||||
// int bit = x - (xGrid * 8);
|
||||
|
||||
// for (int y = 0; y < voxels.y; y++)
|
||||
// {
|
||||
// for (int z = 0; z < voxels.z; z++)
|
||||
// {
|
||||
// if ((volume[xGrid, y, z] & bits[bit]) > 0)
|
||||
// {
|
||||
// Vector3 localPos = new Vector3(pos.x + (x * voxelResolution), pos.y + (y * voxelResolution), pos.z + (z * voxelResolution)) + halfVoxel;
|
||||
// Gizmos.DrawWireCube(t.TransformPoint(localPos), voxel);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
11
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/Voxelize.cs.meta
vendored
Normal file
11
Assets/ThirdParty/Tools/MeshCombineStudio/Scripts/Mesh/Voxelize.cs.meta
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1abfeedba8fba6241b5632cfa2ad5222
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user