You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
95 lines
2.7 KiB
95 lines
2.7 KiB
using System;
|
|
using System.Collections.Generic;
|
|
|
|
using UnityEngine;
|
|
|
|
namespace MeshVoxelizerProject
|
|
{
|
|
|
|
public class MeshVoxelizer
|
|
{
|
|
|
|
public int Count { get; private set; }
|
|
|
|
public int Width { get; private set; }
|
|
|
|
public int Height { get; private set; }
|
|
|
|
public int Depth { get; private set; }
|
|
|
|
public int[,,] Voxels { get; private set; }
|
|
|
|
public List<Box3> Bounds { get; private set; }
|
|
|
|
public MeshVoxelizer(int width, int height, int depth)
|
|
{
|
|
|
|
Width = width;
|
|
Height = height;
|
|
Depth = depth;
|
|
Bounds = new List<Box3>();
|
|
Voxels = new int[width, height, depth];
|
|
}
|
|
public void Voxelize(IList<Vector3> vertices, IList<int> indices, Box3 bounds)
|
|
{
|
|
Array.Clear(Voxels, 0, Voxels.Length);
|
|
|
|
// build an aabb tree of the mesh
|
|
MeshRayTracer tree = new MeshRayTracer(vertices, indices);
|
|
Bounds = tree.GetBounds();
|
|
|
|
// parity count method, single pass
|
|
Vector3 extents = bounds.Size;
|
|
Vector3 delta = new Vector3(extents.x/Width, extents.y/Height, extents.z/Depth);
|
|
Vector3 offset = new Vector3(0.5f/Width, 0.5f/Height, 0.5f/Depth);
|
|
|
|
float eps = 1e-7f * extents.z;
|
|
|
|
for (int x = 0; x < Width; ++x)
|
|
{
|
|
for (int y = 0; y < Height; ++y)
|
|
{
|
|
bool inside = false;
|
|
Vector3 rayDir = new Vector3(0.0f, 0.0f, 1.0f);
|
|
|
|
// z-coord starts somewhat outside bounds
|
|
Vector3 rayStart = bounds.Min + new Vector3(x*delta.x + offset.x, y*delta.y + offset.y, -0.0f*extents.z);
|
|
|
|
while(true)
|
|
{
|
|
MeshRay ray = tree.TraceRay(rayStart, rayDir);
|
|
|
|
if (ray.hit)
|
|
{
|
|
// calculate cell in which intersection occurred
|
|
float zpos = rayStart.z + ray.distance * rayDir.z;
|
|
float zhit = (zpos - bounds.Min.z) / delta.z;
|
|
|
|
int z = (int)((rayStart.z - bounds.Min.z) / delta.z);
|
|
int zend = (int)Math.Min(zhit, Depth - 1);
|
|
|
|
if (inside)
|
|
{
|
|
for (int k = z; k <= zend; ++k)
|
|
{
|
|
Voxels[x, y, k] = 1;
|
|
Count++;
|
|
}
|
|
}
|
|
|
|
inside = !inside;
|
|
rayStart += rayDir*(ray.distance + eps);
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//end
|
|
}
|
|
|
|
}
|
|
|
|
}
|