void render8(MathTree* tree, Region region, uint8_t** img, volatile int* halt, void (*callback)()) { // Special interrupt system, set asynchronously by on high if (*halt) return; // Render pixel-by-pixel if we're below a certain size. if (region.voxels > 0 && region.voxels < MIN_VOLUME) { if (callback) (*callback)(); region8(tree, region, img); return; } // Pre-emptively halt evaluation if all the points in this // region are already light. uint8_t L = region.L[region.nk] >> 8; bool cull = true; for (int row = region.jmin; cull && row < region.jmin + region.nj; ++row) { for (int col = region.imin; cull && col < region.imin + region.ni; ++col) { if (L > img[row][col]) { cull = false; break; } } } if (cull) return; Interval X = {region.X[0], region.X[region.ni]}, Y = {region.Y[0], region.Y[region.nj]}, Z = {region.Z[0], region.Z[region.nk]}; Interval result = eval_i(tree, X, Y, Z); // If we're inside the object, fill with color. if (result.upper < 0) { for (int row = region.jmin; row < region.jmin + region.nj; ++row) { for (int col = region.imin; col < region.imin + region.ni; ++col) { if (L > img[row][col]) img[row][col] = L; } } } // In unambiguous cases, return immediately if (result.upper < 0 || result.lower >= 0) return; #if PRUNE disable_nodes(tree); disable_nodes_binary(tree); #endif // Subdivide and recurse if we're not at voxel size. if (region.ni*region.nj*region.nk > 1) { Region A, B; bisect(region, &A, &B); render8(tree, B, img, halt, callback); render8(tree, A, img, halt, callback); } #if PRUNE enable_nodes(tree); #endif }
void Mesher::unload_packed() { enable_nodes(tree); has_data = false; }