修改水

This commit is contained in:
2026-01-01 22:00:33 +08:00
parent 040a222bd6
commit 9ceffccd39
1800 changed files with 103929 additions and 139495 deletions

View File

@@ -80,7 +80,7 @@ namespace Obi
};
public readonly static Vector3Int[] faceNeighborhood =
{
{
new Vector3Int(-1,0,0),
new Vector3Int(1,0,0),
new Vector3Int(0,-1,0),
@@ -226,15 +226,15 @@ namespace Obi
}
public IEnumerator Voxelize(Matrix4x4 transform, Vector3Int axisMask, bool generateTriangleIndices = false)
public IEnumerator Voxelize(Matrix4x4 transform, bool generateTriangleIndices = false)
{
voxelSize = Mathf.Max(0.0001f, voxelSize);
var xfBounds = input.bounds.Transform(transform);
// Calculate min and max voxels, adding a 1-voxel margin.
origin = GetPointVoxel(Vector3.Scale(xfBounds.min, axisMask)) - axisMask;
Vector3Int max = GetPointVoxel(Vector3.Scale(xfBounds.max, axisMask)) + axisMask;
origin = GetPointVoxel(xfBounds.min) - new Vector3Int(1, 1, 1);
Vector3Int max = GetPointVoxel(xfBounds.max) + new Vector3Int(1, 1, 1);
resolution = new Vector3Int(max.x - origin.x + 1, max.y - origin.y + 1, max.z - origin.z + 1);
@@ -263,9 +263,9 @@ namespace Obi
// Generate surface voxels:
for (int i = 0; i < triIndices.Length; i += 3)
{
Vector3 v1 = Vector3.Scale(transform.MultiplyPoint3x4(vertices[triIndices[i]]), axisMask);
Vector3 v2 = Vector3.Scale(transform.MultiplyPoint3x4(vertices[triIndices[i + 1]]), axisMask);
Vector3 v3 = Vector3.Scale(transform.MultiplyPoint3x4(vertices[triIndices[i + 2]]), axisMask);
Vector3 v1 = transform.MultiplyPoint3x4(vertices[triIndices[i]]);
Vector3 v2 = transform.MultiplyPoint3x4(vertices[triIndices[i + 1]]);
Vector3 v3 = transform.MultiplyPoint3x4(vertices[triIndices[i + 2]]);
Bounds triBounds = GetTriangleBounds(v1, v2, v3);
@@ -281,7 +281,6 @@ namespace Obi
yield return fillCoroutine.Current;
}
// Ensures boundary is only one voxel thick.
public void BoundaryThinning()
{
for (int x = 0; x < resolution.x; ++x)
@@ -309,212 +308,6 @@ namespace Obi
}
}
// Ensures boundary voxels are 2D.
public void MakeBoundary2D()
{
for (int x = 0; x < resolution.x; ++x)
for (int y = 0; y < resolution.y; ++y)
for (int z = 0; z < resolution.z; ++z)
if (this[x, y, z] == Voxel.Boundary)
this[x, y, z] = Voxel.Inside;
for (int x = 0; x < resolution.x; ++x)
for (int y = 0; y < resolution.y; ++y)
for (int z = 0; z < resolution.z; ++z)
{
int sum = 0;
for (int j = 0; j < faceNeighborhood.Length; ++j)
{
var index = faceNeighborhood[j];
if (VoxelExists(index.x + x, index.y + y, index.z + z) && this[index.x + x, index.y + y, index.z + z] != Voxel.Outside)
{
sum++;
}
}
if (sum <= 3 && this[x, y, z] == Voxel.Inside)
this[x, y, z] = Voxel.Boundary;
}
}
public void CreateMesh(ref Mesh mesh, int smoothingIterations)
{
if (mesh == null)
mesh = new Mesh();
mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
mesh.Clear();
List<Vector3> vertices = new List<Vector3>();
List<Vector3> vertices2 = new List<Vector3>();
List<int> tris = new List<int>();
vertices.Clear();
vertices2.Clear();
tris.Clear();
int[] vtxIndex = new int[voxelCount];
for (int i = 0; i < vtxIndex.Length; ++i)
vtxIndex[i] = -1;
// create vertices:
for (int x = 0; x < resolution.x; ++x)
for (int y = 0; y < resolution.y; ++y)
for (int z = 0; z < resolution.z; ++z)
if (this[x, y, z] == Voxel.Boundary)
{
vtxIndex[GetVoxelIndex(x, y, z)] = vertices.Count;
var vtx = new Vector3(Origin.x + x + 0.5f, Origin.y + y + 0.5f, Origin.z + z + 0.5f) * voxelSize;
vertices.Add(vtx);
vertices2.Add(vtx);
}
List<Vector3> inputVertices = vertices;
List<Vector3> outputVertices = vertices2;
for (int i = 0; i < smoothingIterations; ++i)
{
for (int x = 0; x < resolution.x; ++x)
for (int y = 0; y < resolution.y; ++y)
for (int z = 0; z < resolution.z; ++z)
if (this[x, y, z] == Voxel.Boundary)
{
Vector3 avg = Vector3.zero;
int count = 0;
for (int j = 0; j < faceNeighborhood.Length; ++j)
{
var index = faceNeighborhood[j];
if (VoxelExists(index.x + x, index.y + y, index.z + z) && this[index.x + x, index.y + y, index.z + z] == Voxel.Boundary)
{
avg += inputVertices[vtxIndex[GetVoxelIndex(index.x + x, index.y + y, index.z + z)]];
count++;
}
}
if (count > 0)
outputVertices[vtxIndex[GetVoxelIndex(x, y, z)]] = avg / count;
}
var aux = inputVertices;
inputVertices = outputVertices;
outputVertices = aux;
}
// triangulate
for (int x = 0; x < resolution.x; ++x)
for (int y = 0; y < resolution.y; ++y)
for (int z = 0; z < resolution.z; ++z)
if (this[x, y, z] == Voxel.Boundary)
{
int x0y0z0 = GetVoxelIndex(x, y, z);
int x1y0z0 = VoxelExists(x + 1, y, z) ? GetVoxelIndex(x+1, y, z) : -1;
int x1y1z0 = VoxelExists(x + 1, y + 1, z) ? GetVoxelIndex(x+1, y+1, z) : -1;
int x0y1z0 = VoxelExists(x, y + 1, z) ? GetVoxelIndex(x, y+1, z) : -1;
int x0y0z1 = VoxelExists(x, y, z + 1) ? GetVoxelIndex(x, y , z + 1) : -1;
int x0y1z1 = VoxelExists(x, y + 1, z + 1) ? GetVoxelIndex(x, y + 1, z + 1) : -1;
int x1y0z1 = VoxelExists(x + 1, y, z + 1) ? GetVoxelIndex(x+1, y, z + 1) : -1;
int x1y1z1 = VoxelExists(x + 1, y + 1, z + 1) ? GetVoxelIndex(x + 1, y + 1, z + 1) : -1;
// XY plane
if (x1y0z0 >= 0 && x1y1z0 >= 0 && x0y1z0 >= 0 &&
voxels[x1y0z0] == Voxel.Boundary &&
voxels[x1y1z0] == Voxel.Boundary &&
voxels[x0y1z0] == Voxel.Boundary)
{
if (x0y1z1 < 0 || voxels[x0y1z1] == Voxel.Outside ||
x0y0z1 < 0 || voxels[x0y0z1] == Voxel.Outside ||
x1y0z1 < 0 || voxels[x1y0z1] == Voxel.Outside ||
x1y1z1 < 0 || voxels[x1y1z1] == Voxel.Outside)
{
tris.Add(vtxIndex[x0y0z0]);
tris.Add(vtxIndex[x1y0z0]);
tris.Add(vtxIndex[x0y1z0]);
tris.Add(vtxIndex[x0y1z0]);
tris.Add(vtxIndex[x1y0z0]);
tris.Add(vtxIndex[x1y1z0]);
}
else
{
tris.Add(vtxIndex[x1y0z0]);
tris.Add(vtxIndex[x0y0z0]);
tris.Add(vtxIndex[x0y1z0]);
tris.Add(vtxIndex[x1y0z0]);
tris.Add(vtxIndex[x0y1z0]);
tris.Add(vtxIndex[x1y1z0]);
}
}
// XZ plane
if (x1y0z0 >= 0 && x1y0z1 >= 0 && x0y0z1 >= 0 &&
voxels[x1y0z0] == Voxel.Boundary &&
voxels[x1y0z1] == Voxel.Boundary &&
voxels[x0y0z1] == Voxel.Boundary)
{
if (x0y1z0 < 0 || voxels[x0y1z0] == Voxel.Outside ||
x0y1z1 < 0 || voxels[x0y1z1] == Voxel.Outside ||
x1y1z0 < 0 || voxels[x1y1z0] == Voxel.Outside ||
x1y1z1 < 0 || voxels[x1y1z1] == Voxel.Outside)
{
tris.Add(vtxIndex[x1y0z0]);
tris.Add(vtxIndex[x0y0z0]);
tris.Add(vtxIndex[x0y0z1]);
tris.Add(vtxIndex[x1y0z0]);
tris.Add(vtxIndex[x0y0z1]);
tris.Add(vtxIndex[x1y0z1]);
}
else
{
tris.Add(vtxIndex[x0y0z0]);
tris.Add(vtxIndex[x1y0z0]);
tris.Add(vtxIndex[x0y0z1]);
tris.Add(vtxIndex[x0y0z1]);
tris.Add(vtxIndex[x1y0z0]);
tris.Add(vtxIndex[x1y0z1]);
}
}
// XY plane
if (x0y0z1 >= 0 && x0y1z1 >= 0 && x0y1z0 >= 0 &&
voxels[x0y0z1] == Voxel.Boundary &&
voxels[x0y1z1] == Voxel.Boundary &&
voxels[x0y1z0] == Voxel.Boundary)
{
if (x1y0z0 < 0 || voxels[x1y0z0] == Voxel.Outside ||
x1y0z1 < 0 || voxels[x1y0z1] == Voxel.Outside ||
x1y1z0 < 0 || voxels[x1y1z0] == Voxel.Outside ||
x1y1z1 < 0 || voxels[x1y1z1] == Voxel.Outside)
{
tris.Add(vtxIndex[x0y0z1]);
tris.Add(vtxIndex[x0y0z0]);
tris.Add(vtxIndex[x0y1z0]);
tris.Add(vtxIndex[x0y0z1]);
tris.Add(vtxIndex[x0y1z0]);
tris.Add(vtxIndex[x0y1z1]);
}
else
{
tris.Add(vtxIndex[x0y0z0]);
tris.Add(vtxIndex[x0y0z1]);
tris.Add(vtxIndex[x0y1z0]);
tris.Add(vtxIndex[x0y1z0]);
tris.Add(vtxIndex[x0y0z1]);
tris.Add(vtxIndex[x0y1z1]);
}
}
}
mesh.SetVertices(outputVertices);
mesh.SetIndices(tris, MeshTopology.Triangles, 0);
mesh.RecalculateNormals();
}
private IEnumerator FloodFill()
{
Queue<Vector3Int> queue = new Queue<Vector3Int>();
@@ -631,5 +424,6 @@ namespace Obi
return !(Mathf.Max(-maxP, minP) > r);
}
}
}
}