void sprite_move(sprite_t *spr) { // screen edge x if (spr->x + spr->xv > (SCREEN_WIDTH - 8) || spr->x + spr->xv < 0) { if (spr->flags & SPRITE_FLAG_BOUNCE) spr->xv = -spr->xv; else spr->xv = 0; } else { uint8_t tile; if ( (!gridAt(spr->x + spr->xv + 0, spr->y + spr->yv + 0, &tile)) || !IS_EMPTY(tile) || (!gridAt(spr->x + spr->xv + 7, spr->y + spr->yv + 0, &tile)) || !IS_EMPTY(tile) || (!gridAt(spr->x + spr->xv + 0, spr->y + spr->yv + 7, &tile)) || !IS_EMPTY(tile) || (!gridAt(spr->x + spr->xv + 7, spr->y + spr->yv + 7, &tile)) || !IS_EMPTY(tile) ) { // FIXME, budge edge if (spr->flags & SPRITE_FLAG_BOUNCE) spr->xv = -spr->xv; } else { spr->x += spr->xv; } } // screen edge y if (spr->y + spr->yv > (SCREEN_HEIGHT - 8) || spr->y + spr->yv < 0) { if (spr->flags & SPRITE_FLAG_BOUNCE) spr->yv = -spr->yv; else spr->yv = 0; } else { uint8_t tile; if ( (!gridAt(spr->x + spr->xv + 0, spr->y + spr->yv + 0, &tile)) || !IS_EMPTY(tile) || (!gridAt(spr->x + spr->xv + 7, spr->y + spr->yv + 0, &tile)) || !IS_EMPTY(tile) || (!gridAt(spr->x + spr->xv + 0, spr->y + spr->yv + 7, &tile)) || !IS_EMPTY(tile) || (!gridAt(spr->x + spr->xv + 7, spr->y + spr->yv + 7, &tile)) || !IS_EMPTY(tile) ) { // FIXME, budge edge if (spr->flags & SPRITE_FLAG_BOUNCE) spr->yv = -spr->yv; } else { spr->y += spr->yv; } } }
Vec3f VdbGrid::transmittance(PathSampleGenerator &sampler, Vec3f p, Vec3f w, float t0, float t1, Vec3f sigmaT) const { auto accessor = _grid->getConstAccessor(); if (_integrationMethod == IntegrationMethod::ExactNearest) { VdbRaymarcher<openvdb::FloatGrid::TreeType, 3> dda; float integral = 0.0f; dda.march(DdaRay(p + 0.5f, w), t0, t1, accessor, [&](openvdb::Coord voxel, float ta, float tb) { integral += accessor.getValue(voxel)*(tb - ta); return false; }); return std::exp(-integral*sigmaT); } else if (_integrationMethod == IntegrationMethod::ExactLinear) { VdbRaymarcher<openvdb::FloatGrid::TreeType, 3> dda; float integral = 0.0f; float fa = gridAt(accessor, p + w*t0); dda.march(DdaRay(p, w), t0, t1, accessor, [&](openvdb::Coord /*voxel*/, float ta, float tb) { float fb = gridAt(accessor, p + w*tb); integral += (fa + fb)*0.5f*(tb - ta); fa = fb; return false; }); return std::exp(-integral*sigmaT); } else if (_integrationMethod == IntegrationMethod::ResidualRatio) { VdbRaymarcher<Vec2fGrid::TreeType, 3> dda; float scale = _supergridSubsample; float invScale = 1.0f/scale; sigmaT *= scale; float sigmaTc = sigmaT.max(); auto superAccessor = _superGrid->getConstAccessor(); UniformSampler &generator = sampler.uniformGenerator(); float controlIntegral = 0.0f; Vec3f Tr(1.0f); dda.march(DdaRay(p*invScale + 0.5f, w), t0*invScale, t1*invScale, superAccessor, [&](openvdb::Coord voxel, float ta, float tb) { openvdb::Vec2s v = superAccessor.getValue(voxel); float muC = v.x(); float muR = v.y(); muR *= sigmaTc; controlIntegral += muC*(tb - ta); while (true) { ta -= BitManip::normalizedLog(generator.nextI())/muR; if (ta >= tb) break; Tr *= 1.0f - sigmaT*((gridAt(accessor, p + w*ta*scale) - muC)/muR); } return false; }); return std::exp(-controlIntegral*sigmaT)*Tr; } else { float ta = t0; float fa = gridAt(accessor, p + w*t0); float integral = 0.0f; float dT = sampler.next1D()*_stepSize; do { float tb = min(ta + dT, t1); float fb = gridAt(accessor, p + w*tb); integral += (fa + fb)*0.5f*(tb - ta); ta = tb; fa = fb; dT = _stepSize; } while (ta < t1); return std::exp(-integral*sigmaT); } }
Vec2f VdbGrid::inverseOpticalDepth(PathSampleGenerator &sampler, Vec3f p, Vec3f w, float t0, float t1, float sigmaT, float xi) const { auto accessor = _grid->getConstAccessor(); if (_sampleMethod == SampleMethod::ExactNearest) { VdbRaymarcher<openvdb::FloatGrid::TreeType, 3> dda; float integral = 0.0f; Vec2f result(t1, 0.0f); bool exited = !dda.march(DdaRay(p + 0.5f, w), t0, t1, accessor, [&](openvdb::Coord voxel, float ta, float tb) { float v = accessor.getValue(voxel); float delta = v*sigmaT*(tb - ta); if (integral + delta >= xi) { result = Vec2f(ta + (tb - ta)*(xi - integral)/delta, v); return true; } integral += delta; return false; }); return exited ? Vec2f(t1, integral) : result; } else if (_sampleMethod == SampleMethod::ExactLinear) { VdbRaymarcher<openvdb::FloatGrid::TreeType, 3> dda; float integral = 0.0f; float fa = gridAt(accessor, p + w*t0); Vec2f result(t1, 0.0f); bool exited = !dda.march(DdaRay(p + 0.5f, w), t0, t1, accessor, [&](openvdb::Coord /*voxel*/, float ta, float tb) { float fb = gridAt(accessor, p + tb*w); float delta = (fb + fa)*0.5f*sigmaT*(tb - ta); if (integral + delta >= xi) { float a = (fb - fa)*sigmaT; float b = fa*sigmaT; float c = (integral - xi)/(tb - ta); float mantissa = max(b*b - 2.0f*a*c, 0.0f); float x1 = (-b + std::sqrt(mantissa))/a; result = Vec2f(ta + (tb - ta)*x1, fa + (fb - fa)*x1); return true; } integral += delta; fa = fb; return false; }); return exited ? Vec2f(t1, integral) : result; } else { float ta = t0; float fa = gridAt(accessor, p + w*t0); float integral = 0.0f; float dT = sampler.next1D()*_stepSize; do { float tb = min(ta + dT, t1); float fb = gridAt(accessor, p + w*tb); float delta = (fa + fb)*sigmaT*0.5f*(tb - ta); if (integral + delta >= xi) { float a = (fb - fa)*sigmaT; float b = fa*sigmaT; float c = (integral - xi)/(tb - ta); float mantissa = max(b*b - 2.0f*a*c, 0.0f); float x1 = (-b + std::sqrt(mantissa))/a; return Vec2f(ta + (tb - ta)*x1, fa + (fb - fa)*x1); } integral += delta; ta = tb; fa = fb; dT = _stepSize; } while (ta < t1); return Vec2f(t1, integral); } }
float VdbGrid::density(Vec3f p) const { return gridAt(_grid->tree(), p); }