public GridAccelerator(IEnumerable<Primitive> primitives, bool refineImmediately) { // Initialize _primitives_ with primitives for grid _primitives = refineImmediately ? primitives.SelectMany(prim => prim.FullyRefine()).ToArray() : primitives.ToArray(); // Compute bounds and choose grid resolution _bounds = BBox.Empty; for (var i = 0; i < _primitives.Length; ++i) _bounds = BBox.Union(_bounds, _primitives[i].WorldBound); Vector delta = _bounds.Max - _bounds.Min; // Find _voxelsPerUnitDist_ for grid int maxAxis = _bounds.MaximumExtent(); float invMaxWidth = 1.0f / delta[maxAxis]; Debug.Assert(invMaxWidth > 0.0f); float cubeRoot = 3.0f * MathUtility.Pow(_primitives.Length, 1.0f / 3.0f); float voxelsPerUnitDist = cubeRoot * invMaxWidth; _numVoxels = new int[3]; for (int axis = 0; axis < 3; ++axis) { _numVoxels[axis] = MathUtility.Round(delta[axis] * voxelsPerUnitDist); _numVoxels[axis] = MathUtility.Clamp(_numVoxels[axis], 1, 64); } // Compute voxel widths and allocate voxels for (int axis = 0; axis < 3; ++axis) { _width[axis] = delta[axis] / _numVoxels[axis]; _inverseWidth[axis] = (_width[axis] == 0.0f) ? 0.0f : 1.0f / _width[axis]; } int nv = _numVoxels[0] * _numVoxels[1] * _numVoxels[2]; _voxels = new GridVoxel[nv]; // Add primitives to grid voxels for (var i = 0; i < _primitives.Length; ++i) { // Find voxel extent of primitive BBox pb = _primitives[i].WorldBound; int[] vmin = new int[3], vmax = new int[3]; for (int axis = 0; axis < 3; ++axis) { vmin[axis] = PosToVoxel(ref pb.Min, axis); vmax[axis] = PosToVoxel(ref pb.Max, axis); } // Add primitive to overlapping voxels for (int z = vmin[2]; z <= vmax[2]; ++z) for (int y = vmin[1]; y <= vmax[1]; ++y) for (int x = vmin[0]; x <= vmax[0]; ++x) { int o = Offset(x, y, z); if (_voxels[o] == null) { // Allocate new voxel and store primitive in it _voxels[o] = new GridVoxel(_primitives[i]); } else { // Add primitive to already-allocated voxel _voxels[o].AddPrimitive(_primitives[i]); } } } }
public GridAccelerator(IEnumerable <Primitive> primitives, bool refineImmediately) { // Initialize _primitives_ with primitives for grid _primitives = refineImmediately ? primitives.SelectMany(prim => prim.FullyRefine()).ToArray() : primitives.ToArray(); // Compute bounds and choose grid resolution _bounds = BBox.Empty; for (var i = 0; i < _primitives.Length; ++i) { _bounds = BBox.Union(_bounds, _primitives[i].WorldBound); } Vector delta = _bounds.Max - _bounds.Min; // Find _voxelsPerUnitDist_ for grid int maxAxis = _bounds.MaximumExtent(); float invMaxWidth = 1.0f / delta[maxAxis]; Debug.Assert(invMaxWidth > 0.0f); float cubeRoot = 3.0f * MathUtility.Pow(_primitives.Length, 1.0f / 3.0f); float voxelsPerUnitDist = cubeRoot * invMaxWidth; _numVoxels = new int[3]; for (int axis = 0; axis < 3; ++axis) { _numVoxels[axis] = MathUtility.Round(delta[axis] * voxelsPerUnitDist); _numVoxels[axis] = MathUtility.Clamp(_numVoxels[axis], 1, 64); } // Compute voxel widths and allocate voxels for (int axis = 0; axis < 3; ++axis) { _width[axis] = delta[axis] / _numVoxels[axis]; _inverseWidth[axis] = (_width[axis] == 0.0f) ? 0.0f : 1.0f / _width[axis]; } int nv = _numVoxels[0] * _numVoxels[1] * _numVoxels[2]; _voxels = new GridVoxel[nv]; // Add primitives to grid voxels for (var i = 0; i < _primitives.Length; ++i) { // Find voxel extent of primitive BBox pb = _primitives[i].WorldBound; int[] vmin = new int[3], vmax = new int[3]; for (int axis = 0; axis < 3; ++axis) { vmin[axis] = PosToVoxel(ref pb.Min, axis); vmax[axis] = PosToVoxel(ref pb.Max, axis); } // Add primitive to overlapping voxels for (int z = vmin[2]; z <= vmax[2]; ++z) { for (int y = vmin[1]; y <= vmax[1]; ++y) { for (int x = vmin[0]; x <= vmax[0]; ++x) { int o = Offset(x, y, z); if (_voxels[o] == null) { // Allocate new voxel and store primitive in it _voxels[o] = new GridVoxel(_primitives[i]); } else { // Add primitive to already-allocated voxel _voxels[o].AddPrimitive(_primitives[i]); } } } } } }