#pragma once #include "sampler.h" #include #include #include #include #include template class CurlNormS : public Sampler { private: Lattice& _lattice; DeviceBuffer& _mask; SDF _geometry; DeviceBuffer _moments_rho; DeviceBuffer _moments_u; DeviceBuffer _curl_norm; float _scale = 1; float _lower = 0; float _upper = 1; public: CurlNormS(Lattice& lattice, DeviceBuffer& mask, SDF geometry): Sampler("Curl norm", lattice.cuboid()), _lattice(lattice), _mask(mask), _geometry(geometry), _moments_rho(lattice.cuboid().volume), _moments_u(DESCRIPTOR::d * lattice.cuboid().volume), _curl_norm(lattice.cuboid().volume) { } void sample() { _lattice.template inspect(_mask, _moments_rho.device(), _moments_u.device()); _lattice.template inspect(_mask, _moments_u.device(), _sample_surface, _curl_norm.device()); } void render(VolumetricRenderConfig& config) { raymarch<<< dim3(config.canvas_size.x / 32 + 1, config.canvas_size.y / 32 + 1), dim3(32, 32) >>>(config, _geometry, [samples=_sample_texture, scale=_scale, lower=_lower, upper=_upper] __device__ (float3 p) -> float { float sample = scale * tex3D(samples, p.x, p.y, p.z); return sample >= lower && sample <= upper ? sample : 0; }, [] __device__ (float x) -> float { return x; }); } void scale() { auto max = thrust::max_element(thrust::device_pointer_cast(_curl_norm.device()), thrust::device_pointer_cast(_curl_norm.device() + _lattice.cuboid().volume)); _scale = 1 / max[0]; } void interact() { ImGui::SliderFloat("Scale", &_scale, 0.01f, 100.f); ImGui::SameLine(); if (ImGui::Button("Auto")) { scale(); } ImGui::DragFloatRange2("Bounds", &_lower, &_upper, 0.01f, 0.f, 1.f, "%.2f", "%.2f"); } }; template CurlNormS(Lattice&, DeviceBuffer&, SDF) -> CurlNormS;