pookiefoof's picture
Public release: SkinTokens 路 TokenRig demo
9d7cf7f
from dataclasses import dataclass
from numpy import ndarray
from typing import Optional
import numpy as np
@dataclass
class Voxel():
# coordinates of mesh
coords: ndarray
# origin of the voxel
origin: ndarray
# grid size
voxel_size: float
# a boolen array
_voxel: Optional[ndarray]=None
@property
def voxel(self) -> ndarray:
if self._voxel is None:
max_coords = np.max(self.coords, axis=0)
shape = tuple(max_coords + 1)
voxel = np.zeros(shape, dtype=bool)
voxel[tuple(self.coords.T)] = True
self._voxel = voxel
return self._voxel
@property
def pc(self) -> ndarray:
return self.origin + (self.coords + 0.5) * self.voxel_size
def projection_fill(self, rigid: bool=True):
"""
Fill up holes in the voxel.
"""
grids = np.indices(self.voxel.shape)
x_coord = grids[0, ...]
y_coord = grids[1, ...]
z_coord = grids[2, ...]
INF = 2147483647
x_tmp = x_coord.copy()
x_tmp[~self.voxel] = INF
x_min = x_tmp.min(axis=0)
x_tmp[~self.voxel] = -1
x_max = x_tmp.max(axis=0)
y_tmp = y_coord.copy()
y_tmp[~self.voxel] = INF
y_min = y_tmp.min(axis=1)
y_tmp[~self.voxel] = -1
y_max = y_tmp.max(axis=1)
z_tmp = z_coord.copy()
z_tmp[~self.voxel] = INF
z_min = z_tmp.min(axis=2)
z_tmp[~self.voxel] = -1
z_max = z_tmp.max(axis=2)
in_x = (x_coord >= x_min[None, :, :]) & (x_coord <= x_max[None, :, :])
in_y = (y_coord >= y_min[:, None, :]) & (y_coord <= y_max[:, None, :])
in_z = (z_coord >= z_min[:, :, None]) & (z_coord <= z_max[:, :, None])
count = in_x.astype(int) + in_y.astype(int) + in_z.astype(int)
fill_mask = count >= (3 if rigid else 2)
self._voxel = self.voxel | fill_mask
x, y, z = np.where(self.voxel)
self.coords = np.stack([x, y, z], axis=1)
def inside(self, points: ndarray) -> ndarray:
if points.ndim == 1:
points = points[None, :]
points = np.asarray(points)
idx = np.floor((points - self.origin) / self.voxel_size).astype(int)
invalid = (
(idx < 0).any(axis=1) |
(idx >= np.array(self.voxel.shape)).any(axis=1)
)
result = np.zeros(len(points), dtype=bool)
valid_idx = np.where(~invalid)[0]
valid_voxel_idx = idx[valid_idx]
result[valid_idx] = self.voxel[valid_voxel_idx[:, 0], valid_voxel_idx[:, 1], valid_voxel_idx[:, 2]]
return result