def __mul__(self, other): from core.bbox import BoundingBox from maths.point3d import Point3d if isinstance(other, Transform): return Transform(self.mat * other.mat, other.mat_inv * self.mat_inv) elif isinstance(other, BoundingBox): ret = BoundingBox.create_from_point3d(Point3d(other.point_min.x, other.point_min.y, other.point_min.z)*self.mat) ret = BoundingBox.get_union_bbox(ret, BoundingBox.create_from_point3d(Point3d(other.point_max.x, other.point_min.y, other.point_min.z)*self.mat)) ret = BoundingBox.get_union_bbox(ret, BoundingBox.create_from_point3d(Point3d(other.point_min.x, other.point_max.y, other.point_min.z)*self.mat)) ret = BoundingBox.get_union_bbox(ret, BoundingBox.create_from_point3d(Point3d(other.point_min.x, other.point_min.y, other.point_max.z)*self.mat)) ret = BoundingBox.get_union_bbox(ret, BoundingBox.create_from_point3d(Point3d(other.point_min.x, other.point_max.y, other.point_max.z)*self.mat)) ret = BoundingBox.get_union_bbox(ret, BoundingBox.create_from_point3d(Point3d(other.point_max.x, other.point_max.y, other.point_min.z)*self.mat)) ret = BoundingBox.get_union_bbox(ret, BoundingBox.create_from_point3d(Point3d(other.point_max.x, other.point_min.y, other.point_max.z)*self.mat)) ret = BoundingBox.get_union_bbox(ret, BoundingBox.create_from_point3d(Point3d(other.point_max.x, other.point_max.y, other.point_max.z)*self.mat)) return ret # invert of matrix product is : (AxB)-1 = B-1 x A-1 # see: https://proofwiki.org/wiki/Inverse_of_Matrix_Product raise NotImplemented
def __init__(self, primitives: [Primitive], refine_immediately: bool): super().__init__() self.voxels = [] self.bounds = BoundingBox() self.width = Vector3d() self.inv_width = Vector3d() self.nVoxels = [int] * 3 self.primitives = [] # Initialize _primitives_ with primitives for grid if refine_immediately: for p in primitives: p.get_fully_refine(self.primitives) else: self.primitives = primitives # Compute bounds and choose grid resolution for p in self.primitives: self.bounds = BoundingBox.get_union_bbox(self.bounds, p.get_world_bound()) delta = self.bounds.point_max - self.bounds.point_min #Find _voxelsPerUnitDist_ for grid maxAxis = self.bounds.get_maximum_extent() invMaxWidth = 1.0 / delta[maxAxis] assert (invMaxWidth > 0.0) cubeRoot = 3.0 * pow(float(len(self.primitives)), 1.0 / 3.0) voxelsPerUnitDist = cubeRoot * invMaxWidth for axis in range(3): self.nVoxels[axis] = int(math.floor(delta[axis] * voxelsPerUnitDist)) self.nVoxels[axis] = maths.tools.get_clamp(self.nVoxels[axis], 1, 64) # Compute voxel widths and allocate voxels for axis in range(3): self.width[axis] = delta[axis] / self.nVoxels[axis] if self.width[axis] == 0.0: self.inv_width[axis] = 0.0 else: self.inv_width[axis] = 1.0 / self.width[axis] nv = self.nVoxels[0] * self.nVoxels[1] * self.nVoxels[2] self.voxels = [None] * nv #Add primitives to grid voxels for p in self.primitives: # Find voxel extent of primitive pb = p.get_world_bound() vmin = [int] * 3 vmax = [int] * 3 for axis in range(3): vmin[axis] = self.get_pos_to_voxel(pb.point_min, axis) vmax[axis] = self.get_pos_to_voxel(pb.point_max, axis) # Add primitive to overlapping voxels for z in range(vmin[2], vmax[2]+1): for y in range(vmin[1], vmax[1]+1): for x in range(vmin[0], vmax[0]+1): o = self.get_offset(x, y, z) if self.voxels[o] is None: # Allocate new voxel and store primitive in it self.voxels[o] = Voxel(p) else: # Add primitive to already-allocated voxel self.voxels[o].add_primitive(p)