public static void Voxelize(Vector3[] vertices, int[] indices, Bounds bounds, int resolution, out float unit) { float maxLength = Mathf.Max(bounds.size.x, Mathf.Max(bounds.size.y, bounds.size.z)); unit = maxLength / resolution; float hunit = unit * 0.5f; start = bounds.min - new Vector3(hunit, hunit, hunit); Vector3 end = bounds.max + new Vector3(hunit, hunit, hunit); Vector3 size = end - start; width = Mathf.CeilToInt(size.x / unit); height = Mathf.CeilToInt(size.y / unit); depth = Mathf.CeilToInt(size.z / unit); volume = new Voxel_t[width, height, depth]; Bounds[, ,] boxes = new Bounds[width, height, depth]; Vector3 voxelSize = Vector3.one * unit; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { for (int z = 0; z < depth; z++) { Vector3 p = new Vector3(x, y, z) * unit + start; Bounds aabb = new Bounds(p, voxelSize); boxes[x, y, z] = aabb; volume[x, y, z] = new Voxel_t(); } } } Vector3 direction = Vector3.forward; for (int i = 0, n = indices.Length; i < n; i += 3) { MegaTriangle tri = new MegaTriangle(vertices[indices[i]], vertices[indices[i + 1]], vertices[indices[i + 2]], direction, i); Vector3 min = tri.bounds.min - start; Vector3 max = tri.bounds.max - start; int iminX = (int)(min.x / unit), iminY = (int)(min.y / unit), iminZ = (int)(min.z / unit); int imaxX = (int)(max.x / unit), imaxY = (int)(max.y / unit), imaxZ = (int)(max.z / unit); iminX = Mathf.Clamp(iminX, 0, width - 1); iminY = Mathf.Clamp(iminY, 0, height - 1); iminZ = Mathf.Clamp(iminZ, 0, depth - 1); imaxX = Mathf.Clamp(imaxX, 0, width - 1); imaxY = Mathf.Clamp(imaxY, 0, height - 1); imaxZ = Mathf.Clamp(imaxZ, 0, depth - 1); for (int x = iminX; x <= imaxX; x++) { for (int y = iminY; y <= imaxY; y++) { for (int z = iminZ; z <= imaxZ; z++) { if (Intersects(tri, boxes[x, y, z])) { Voxel_t voxel = volume[x, y, z]; voxel.position = boxes[x, y, z].center; voxel.tris.Add(tri); volume[x, y, z] = voxel; } } } } } }
public static bool Intersects(MegaTriangle tri, Bounds aabb) { float p0, p1, p2, r; Vector3 center = aabb.center, extents = aabb.max - center; Vector3 v0 = tri.a - center, v1 = tri.b - center, v2 = tri.c - center; Vector3 f0 = v1 - v0, f1 = v2 - v1, f2 = v0 - v2; Vector3 a00 = new Vector3(0, -f0.z, f0.y), a01 = new Vector3(0, -f1.z, f1.y), a02 = new Vector3(0, -f2.z, f2.y), a10 = new Vector3(f0.z, 0, -f0.x), a11 = new Vector3(f1.z, 0, -f1.x), a12 = new Vector3(f2.z, 0, -f2.x), a20 = new Vector3(-f0.y, f0.x, 0), a21 = new Vector3(-f1.y, f1.x, 0), a22 = new Vector3(-f2.y, f2.x, 0); // Test axis a00 p0 = Vector3.Dot(v0, a00); p1 = Vector3.Dot(v1, a00); p2 = Vector3.Dot(v2, a00); r = extents.y * Mathf.Abs(f0.z) + extents.z * Mathf.Abs(f0.y); if (Mathf.Max(-Mathf.Max(p0, p1, p2), Mathf.Min(p0, p1, p2)) > r) { return(false); } // Test axis a01 p0 = Vector3.Dot(v0, a01); p1 = Vector3.Dot(v1, a01); p2 = Vector3.Dot(v2, a01); r = extents.y * Mathf.Abs(f1.z) + extents.z * Mathf.Abs(f1.y); if (Mathf.Max(-Mathf.Max(p0, p1, p2), Mathf.Min(p0, p1, p2)) > r) { return(false); } // Test axis a02 p0 = Vector3.Dot(v0, a02); p1 = Vector3.Dot(v1, a02); p2 = Vector3.Dot(v2, a02); r = extents.y * Mathf.Abs(f2.z) + extents.z * Mathf.Abs(f2.y); if (Mathf.Max(-Mathf.Max(p0, p1, p2), Mathf.Min(p0, p1, p2)) > r) { return(false); } // Test axis a10 p0 = Vector3.Dot(v0, a10); p1 = Vector3.Dot(v1, a10); p2 = Vector3.Dot(v2, a10); r = extents.x * Mathf.Abs(f0.z) + extents.z * Mathf.Abs(f0.x); if (Mathf.Max(-Mathf.Max(p0, p1, p2), Mathf.Min(p0, p1, p2)) > r) { return(false); } // Test axis a11 p0 = Vector3.Dot(v0, a11); p1 = Vector3.Dot(v1, a11); p2 = Vector3.Dot(v2, a11); r = extents.x * Mathf.Abs(f1.z) + extents.z * Mathf.Abs(f1.x); if (Mathf.Max(-Mathf.Max(p0, p1, p2), Mathf.Min(p0, p1, p2)) > r) { return(false); } // Test axis a12 p0 = Vector3.Dot(v0, a12); p1 = Vector3.Dot(v1, a12); p2 = Vector3.Dot(v2, a12); r = extents.x * Mathf.Abs(f2.z) + extents.z * Mathf.Abs(f2.x); if (Mathf.Max(-Mathf.Max(p0, p1, p2), Mathf.Min(p0, p1, p2)) > r) { return(false); } // Test axis a20 p0 = Vector3.Dot(v0, a20); p1 = Vector3.Dot(v1, a20); p2 = Vector3.Dot(v2, a20); r = extents.x * Mathf.Abs(f0.y) + extents.y * Mathf.Abs(f0.x); if (Mathf.Max(-Mathf.Max(p0, p1, p2), Mathf.Min(p0, p1, p2)) > r) { return(false); } // Test axis a21 p0 = Vector3.Dot(v0, a21); p1 = Vector3.Dot(v1, a21); p2 = Vector3.Dot(v2, a21); r = extents.x * Mathf.Abs(f1.y) + extents.y * Mathf.Abs(f1.x); if (Mathf.Max(-Mathf.Max(p0, p1, p2), Mathf.Min(p0, p1, p2)) > r) { return(false); } // Test axis a22 p0 = Vector3.Dot(v0, a22); p1 = Vector3.Dot(v1, a22); p2 = Vector3.Dot(v2, a22); r = extents.x * Mathf.Abs(f2.y) + extents.y * Mathf.Abs(f2.x); if (Mathf.Max(-Mathf.Max(p0, p1, p2), Mathf.Min(p0, p1, p2)) > r) { return(false); } if (Mathf.Max(v0.x, v1.x, v2.x) < -extents.x || Mathf.Min(v0.x, v1.x, v2.x) > extents.x) { return(false); } if (Mathf.Max(v0.y, v1.y, v2.y) < -extents.y || Mathf.Min(v0.y, v1.y, v2.y) > extents.y) { return(false); } if (Mathf.Max(v0.z, v1.z, v2.z) < -extents.z || Mathf.Min(v0.z, v1.z, v2.z) > extents.z) { return(false); } Vector3 normal = Vector3.Cross(f1, f0).normalized; Plane pl = new Plane(normal, Vector3.Dot(normal, tri.a)); return(Intersects(pl, aabb)); }