def __init__(self, primitives, refine_immediately): """Default constructor for GridAccel.""" # initialize self.primitives with primitives for grid if refine_immediately: self.primitives = [] for primitive in primitives: primitive.fully_refine(self.primitives) else: self.primitives = list(primitives) # compute bounds and choose grid resolution self.bounds = BBox() for primitive in self.primitives: self.bounds = union(self.bounds, primitive.world_bound()) delta = self.bounds.p_max - self.bounds.p_min # find voxels_per_unit_dist for grid max_axis = self.bounds.maximum_extent() inv_max_width = 1.0 / delta[max_axis] cube_root = 3.0 * pow(len(self.primitives), 1.0 / 3.0) voxels_per_unit_dist = cube_root * inv_max_width self.n_voxels = [] for axis in range(3): self.n_voxels.append( clamp(round_to_int(delta[axis] * voxels_per_unit_dist), 1, 64)) # compute voxel widths and allocate voxels self.width = Vector() self.inv_width = Vector() for axis in range(3): self.width[axis] = delta[axis] / self.n_voxels[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.n_voxels[0] * self.n_voxels[1] * self.n_voxels[2] # array of voxels, initialized at None self.voxels = [None] * nv # add primitives to grid voxels for primitive in self.primitives: # find voxel extent of primitive primitive_bound = primitive.world_bound() v_min = [] v_max = [] for axis in range(3): v_min.append(self._pos_to_voxel(primitive_bound.p_min, axis)) v_max.append(self._pos_to_voxel(primitive_bound.p_max, axis)) # add primitive to overlapping voxels for z in range(v_min[2], v_max[2] + 1): for y in range(v_min[1], v_max[1] + 1): for x in range(v_min[0], v_max[0] + 1): index = self._offset(x, y, z) if self.voxels[index] is None: self.voxels[index] = Voxel(primitive) else: self.voxels[index].add_primitive(primitive) # create reader-writer mutex for grid self.rw_lock = DummyRWLock()