diff --git a/libs/yocto/yocto_sampling.h b/libs/yocto/yocto_sampling.h index f9a3566bd..3838ec789 100644 --- a/libs/yocto/yocto_sampling.h +++ b/libs/yocto/yocto_sampling.h @@ -168,6 +168,43 @@ inline float sample_discrete_pdf(const vector& cdf, int idx); } // namespace yocto +// ----------------------------------------------------------------------------- +// SHAPE SAMPLING +// ----------------------------------------------------------------------------- +namespace yocto { + +// Pick a point in a point set uniformly. +inline int sample_points(int npoints, float re); +inline int sample_points(const vector& cdf, float re); +inline vector sample_points_cdf(int npoints); +inline void sample_points_cdf(vector& cdf, int npoints); + +// Pick a point on lines uniformly. +inline pair sample_lines( + const vector& cdf, float re, float ru); +inline vector sample_lines_cdf( + const vector& lines, const vector& positions); +inline void sample_lines_cdf(vector& cdf, const vector& lines, + const vector& positions); + +// Pick a point on a triangle mesh uniformly. +inline pair sample_triangles( + const vector& cdf, float re, vec2f ruv); +inline vector sample_triangles_cdf( + const vector& triangles, const vector& positions); +inline void sample_triangles_cdf(vector& cdf, + const vector& triangles, const vector& positions); + +// Pick a point on a quad mesh uniformly. +inline pair sample_quads( + const vector& cdf, float re, vec2f ruv); +inline vector sample_quads_cdf( + const vector& quads, const vector& positions); +inline void sample_quads_cdf(vector& cdf, const vector& quads, + const vector& positions); + +} // namespace yocto + // ----------------------------------------------------------------------------- // // @@ -254,7 +291,7 @@ inline void shuffle(vector& vals, rng_state& rng) { } // namespace yocto // ----------------------------------------------------------------------------- -// IMPLEMENTATION OF MONETACARLO SAMPLING FUNCTIONS +// IMPLEMENTATION OF MONTECARLO SAMPLING FUNCTIONS // ----------------------------------------------------------------------------- namespace yocto { @@ -404,6 +441,112 @@ inline float sample_discrete_pdf(const vector& cdf, int idx) { } // namespace yocto +// ----------------------------------------------------------------------------- +// IMPLEMENTATION OF SHAPE SAMPLING +// ----------------------------------------------------------------------------- +namespace yocto { + +// Pick a point in a point set uniformly. +inline int sample_points(int npoints, float re) { + return sample_uniform(npoints, re); +} +inline int sample_points(const vector& cdf, float re) { + return sample_discrete(cdf, re); +} +inline vector sample_points_cdf(int npoints) { + auto cdf = vector(npoints); + for (auto i : range(cdf.size())) cdf[i] = 1 + (i != 0 ? cdf[i - 1] : 0); + return cdf; +} +inline void sample_points_cdf(vector& cdf, int npoints) { + for (auto i : range(cdf.size())) cdf[i] = 1 + (i != 0 ? cdf[i - 1] : 0); +} + +// Pick a point on lines uniformly. +inline pair sample_lines( + const vector& cdf, float re, float ru) { + return {sample_discrete(cdf, re), ru}; +} +inline vector sample_lines_cdf( + const vector& lines, const vector& positions) { + auto cdf = vector(lines.size()); + for (auto i : range(cdf.size())) { + auto& l = lines[i]; + auto w = line_length(positions[l.x], positions[l.y]); + cdf[i] = w + (i != 0 ? cdf[i - 1] : 0); + } + return cdf; +} +inline void sample_lines_cdf(vector& cdf, const vector& lines, + const vector& positions) { + for (auto i : range(cdf.size())) { + auto& l = lines[i]; + auto w = line_length(positions[l.x], positions[l.y]); + cdf[i] = w + (i != 0 ? cdf[i - 1] : 0); + } +} + +// Pick a point on a triangle mesh uniformly. +inline pair sample_triangles( + const vector& cdf, float re, vec2f ruv) { + return {sample_discrete(cdf, re), sample_triangle(ruv)}; +} +inline vector sample_triangles_cdf( + const vector& triangles, const vector& positions) { + auto cdf = vector(triangles.size()); + for (auto i : range(cdf.size())) { + auto& t = triangles[i]; + auto w = triangle_area(positions[t.x], positions[t.y], positions[t.z]); + cdf[i] = w + (i != 0 ? cdf[i - 1] : 0); + } + return cdf; +} +inline void sample_triangles_cdf(vector& cdf, + const vector& triangles, const vector& positions) { + for (auto i : range(cdf.size())) { + auto& t = triangles[i]; + auto w = triangle_area(positions[t.x], positions[t.y], positions[t.z]); + cdf[i] = w + (i != 0 ? cdf[i - 1] : 0); + } +} + +// Pick a point on a quad mesh uniformly. +inline pair sample_quads( + const vector& cdf, float re, vec2f ruv) { + return {sample_discrete(cdf, re), ruv}; +} +inline pair sample_quads( + const vector& quads, const vector& cdf, float re, vec2f ruv) { + auto element = sample_discrete(cdf, re); + if (quads[element].z == quads[element].w) { + return {element, sample_triangle(ruv)}; + } else { + return {element, ruv}; + } +} +inline vector sample_quads_cdf( + const vector& quads, const vector& positions) { + auto cdf = vector(quads.size()); + for (auto i : range(cdf.size())) { + auto& q = quads[i]; + auto w = quad_area( + positions[q.x], positions[q.y], positions[q.z], positions[q.w]); + cdf[i] = w + (i ? cdf[i - 1] : 0); + } + return cdf; +} +inline void sample_quads_cdf(vector& cdf, const vector& quads, + const vector& positions) { + for (auto i : range(cdf.size())) { + auto& q = quads[i]; + auto w = quad_area( + positions[q.x], positions[q.y], positions[q.z], positions[q.w]); + cdf[i] = w + (i ? cdf[i - 1] : 0); + } +} + +} // namespace yocto + // ----------------------------------------------------------------------------- // CUDA SUPPORT // ----------------------------------------------------------------------------- diff --git a/libs/yocto/yocto_shape.cpp b/libs/yocto/yocto_shape.cpp index d4262454f..0990fcde3 100644 --- a/libs/yocto/yocto_shape.cpp +++ b/libs/yocto/yocto_shape.cpp @@ -1742,178 +1742,6 @@ void split_facevarying(vector& split_quads, } // namespace yocto -// ----------------------------------------------------------------------------- -// IMPLEMENTATION OF SHAPE SAMPLING -// ----------------------------------------------------------------------------- -namespace yocto { - -// Pick a point in a point set uniformly. -int sample_points(int npoints, float re) { return sample_uniform(npoints, re); } -int sample_points(const vector& cdf, float re) { - return sample_discrete(cdf, re); -} -vector sample_points_cdf(int npoints) { - auto cdf = vector(npoints); - for (auto i : range(cdf.size())) cdf[i] = 1 + (i != 0 ? cdf[i - 1] : 0); - return cdf; -} -void sample_points_cdf(vector& cdf, int npoints) { - for (auto i : range(cdf.size())) cdf[i] = 1 + (i != 0 ? cdf[i - 1] : 0); -} - -// Pick a point on lines uniformly. -pair sample_lines(const vector& cdf, float re, float ru) { - return {sample_discrete(cdf, re), ru}; -} -vector sample_lines_cdf( - const vector& lines, const vector& positions) { - auto cdf = vector(lines.size()); - for (auto i : range(cdf.size())) { - auto& l = lines[i]; - auto w = line_length(positions[l.x], positions[l.y]); - cdf[i] = w + (i != 0 ? cdf[i - 1] : 0); - } - return cdf; -} -void sample_lines_cdf(vector& cdf, const vector& lines, - const vector& positions) { - for (auto i : range(cdf.size())) { - auto& l = lines[i]; - auto w = line_length(positions[l.x], positions[l.y]); - cdf[i] = w + (i != 0 ? cdf[i - 1] : 0); - } -} - -// Pick a point on a triangle mesh uniformly. -pair sample_triangles( - const vector& cdf, float re, vec2f ruv) { - return {sample_discrete(cdf, re), sample_triangle(ruv)}; -} -vector sample_triangles_cdf( - const vector& triangles, const vector& positions) { - auto cdf = vector(triangles.size()); - for (auto i : range(cdf.size())) { - auto& t = triangles[i]; - auto w = triangle_area(positions[t.x], positions[t.y], positions[t.z]); - cdf[i] = w + (i != 0 ? cdf[i - 1] : 0); - } - return cdf; -} -void sample_triangles_cdf(vector& cdf, const vector& triangles, - const vector& positions) { - for (auto i : range(cdf.size())) { - auto& t = triangles[i]; - auto w = triangle_area(positions[t.x], positions[t.y], positions[t.z]); - cdf[i] = w + (i != 0 ? cdf[i - 1] : 0); - } -} - -// Pick a point on a quad mesh uniformly. -pair sample_quads(const vector& cdf, float re, vec2f ruv) { - return {sample_discrete(cdf, re), ruv}; -} -pair sample_quads( - const vector& quads, const vector& cdf, float re, vec2f ruv) { - auto element = sample_discrete(cdf, re); - if (quads[element].z == quads[element].w) { - return {element, sample_triangle(ruv)}; - } else { - return {element, ruv}; - } -} -vector sample_quads_cdf( - const vector& quads, const vector& positions) { - auto cdf = vector(quads.size()); - for (auto i : range(cdf.size())) { - auto& q = quads[i]; - auto w = quad_area( - positions[q.x], positions[q.y], positions[q.z], positions[q.w]); - cdf[i] = w + (i ? cdf[i - 1] : 0); - } - return cdf; -} -void sample_quads_cdf(vector& cdf, const vector& quads, - const vector& positions) { - for (auto i : range(cdf.size())) { - auto& q = quads[i]; - auto w = quad_area( - positions[q.x], positions[q.y], positions[q.z], positions[q.w]); - cdf[i] = w + (i ? cdf[i - 1] : 0); - } -} - -// Samples a set of points over a triangle mesh uniformly. The rng function -// takes the point index and returns vec3f numbers uniform directibuted in -// [0,1]^3. unorm and texcoord are optional. -void sample_triangles(vector& sampled_positions, - vector& sampled_normals, vector& sampled_texcoords, - const vector& triangles, const vector& positions, - const vector& normals, const vector& texcoords, int npoints, - int seed) { - sampled_positions.resize(npoints); - sampled_normals.resize(npoints); - sampled_texcoords.resize(npoints); - auto cdf = sample_triangles_cdf(triangles, positions); - auto rng = make_rng(seed); - for (auto i : range(npoints)) { - auto sample = sample_triangles(cdf, rand1f(rng), rand2f(rng)); - auto& t = triangles[sample.first]; - auto uv = sample.second; - sampled_positions[i] = interpolate_triangle( - positions[t.x], positions[t.y], positions[t.z], uv); - if (!sampled_normals.empty()) { - sampled_normals[i] = normalize( - interpolate_triangle(normals[t.x], normals[t.y], normals[t.z], uv)); - } else { - sampled_normals[i] = triangle_normal( - positions[t.x], positions[t.y], positions[t.z]); - } - if (!sampled_texcoords.empty()) { - sampled_texcoords[i] = interpolate_triangle( - texcoords[t.x], texcoords[t.y], texcoords[t.z], uv); - } else { - sampled_texcoords[i] = vec2f{0, 0}; - } - } -} - -// Samples a set of points over a triangle mesh uniformly. The rng function -// takes the point index and returns vec3f numbers uniform directibuted in -// [0,1]^3. unorm and texcoord are optional. -void sample_quads(vector& sampled_positions, - vector& sampled_normals, vector& sampled_texcoords, - const vector& quads, const vector& positions, - const vector& normals, const vector& texcoords, int npoints, - int seed) { - sampled_positions.resize(npoints); - sampled_normals.resize(npoints); - sampled_texcoords.resize(npoints); - auto cdf = sample_quads_cdf(quads, positions); - auto rng = make_rng(seed); - for (auto i : range(npoints)) { - auto sample = sample_quads(cdf, rand1f(rng), rand2f(rng)); - auto& q = quads[sample.first]; - auto uv = sample.second; - sampled_positions[i] = interpolate_quad( - positions[q.x], positions[q.y], positions[q.z], positions[q.w], uv); - if (!sampled_normals.empty()) { - sampled_normals[i] = normalize(interpolate_quad( - normals[q.x], normals[q.y], normals[q.z], normals[q.w], uv)); - } else { - sampled_normals[i] = quad_normal( - positions[q.x], positions[q.y], positions[q.z], positions[q.w]); - } - if (!sampled_texcoords.empty()) { - sampled_texcoords[i] = interpolate_quad( - texcoords[q.x], texcoords[q.y], texcoords[q.z], texcoords[q.w], uv); - } else { - sampled_texcoords[i] = vec2f{0, 0}; - } - } -} - -} // namespace yocto - // ----------------------------------------------------------------------------- // SHAPE DATA // ----------------------------------------------------------------------------- diff --git a/libs/yocto/yocto_shape.h b/libs/yocto/yocto_shape.h index 67bead962..f2977f495 100644 --- a/libs/yocto/yocto_shape.h +++ b/libs/yocto/yocto_shape.h @@ -419,54 +419,6 @@ void split_facevarying(vector& split_quads, } // namespace yocto -// ----------------------------------------------------------------------------- -// SHAPE SAMPLING -// ----------------------------------------------------------------------------- -namespace yocto { - -// Pick a point in a point set uniformly. -int sample_points(int npoints, float re); -int sample_points(const vector& cdf, float re); -vector sample_points_cdf(int npoints); -void sample_points_cdf(vector& cdf, int npoints); - -// Pick a point on lines uniformly. -pair sample_lines(const vector& cdf, float re, float ru); -vector sample_lines_cdf( - const vector& lines, const vector& positions); -void sample_lines_cdf(vector& cdf, const vector& lines, - const vector& positions); - -// Pick a point on a triangle mesh uniformly. -pair sample_triangles( - const vector& cdf, float re, vec2f ruv); -vector sample_triangles_cdf( - const vector& triangles, const vector& positions); -void sample_triangles_cdf(vector& cdf, const vector& triangles, - const vector& positions); - -// Pick a point on a quad mesh uniformly. -pair sample_quads(const vector& cdf, float re, vec2f ruv); -vector sample_quads_cdf( - const vector& quads, const vector& positions); -void sample_quads_cdf(vector& cdf, const vector& quads, - const vector& positions); - -// Samples a set of points over a triangle/quad mesh uniformly. Returns pos, -// norm and texcoord of the sampled points. -void sample_triangles(vector& sampled_positions, - vector& sampled_normals, vector& sampled_texcoords, - const vector& triangles, const vector& positions, - const vector& normals, const vector& texcoords, int npoints, - int seed = 7); -void sample_quads(vector& sampled_positions, - vector& sampled_normals, vector& sampled_texcoords, - const vector& quads, const vector& positions, - const vector& normals, const vector& texcoords, int npoints, - int seed = 7); - -} // namespace yocto - // ----------------------------------------------------------------------------- // //