From cc744c80abe7ea805433b8117efe34c5efffe2e6 Mon Sep 17 00:00:00 2001 From: Fabio Pellacini Date: Wed, 31 Jan 2024 20:43:33 +0100 Subject: [PATCH] updated --- libs/yocto/yocto_scene.cpp | 15 +++++------- libs/yocto/yocto_scene.h | 12 +++++----- libs/yocto/yocto_sceneio.cpp | 46 ++++++++++++++++++------------------ libs/yocto/yocto_sceneio.h | 12 +++++----- libs/yocto/yocto_trace.cpp | 12 ++++------ 5 files changed, 46 insertions(+), 51 deletions(-) diff --git a/libs/yocto/yocto_scene.cpp b/libs/yocto/yocto_scene.cpp index 92d042b3b..6256e3080 100644 --- a/libs/yocto/yocto_scene.cpp +++ b/libs/yocto/yocto_scene.cpp @@ -115,9 +115,7 @@ namespace yocto { // pixel access vec4f lookup_texture( - const texture_data& texture, vec2i ij_, bool ldr_as_linear, bool no_flipv) { - auto size = max(texture.pixelsb.size(), texture.pixelsf.size()); - auto ij = no_flipv ? ij_ : vec2i{ij_.x, size.y - 1 - ij_.y}; + const texture_data& texture, vec2i ij, bool ldr_as_linear) { if (!texture.pixelsf.empty()) return texture.pixelsf[ij]; if (!texture.pixelsb.empty()) return ldr_as_linear ? byte_to_float(texture.pixelsb[ij]) @@ -126,8 +124,7 @@ vec4f lookup_texture( } // Evaluates an image at a point `uv`. -vec4f eval_texture( - const texture_data& texture, vec2f uv, bool ldr_as_linear, bool no_flipv) { +vec4f eval_texture(const texture_data& texture, vec2f uv, bool ldr_as_linear) { if (texture.pixelsf.empty() && texture.pixelsb.empty()) return {0, 0, 0, 0}; // get texture width/height @@ -155,10 +152,10 @@ vec4f eval_texture( } // Helpers -vec4f eval_texture(const scene_data& scene, int texture, vec2f uv, - bool ldr_as_linear, bool no_flipv) { +vec4f eval_texture( + const scene_data& scene, int texture, vec2f uv, bool ldr_as_linear) { if (texture == invalidid) return {1, 1, 1, 1}; - return eval_texture(scene.textures[texture], uv, ldr_as_linear, no_flipv); + return eval_texture(scene.textures[texture], uv, ldr_as_linear); } // conversion from image @@ -573,7 +570,7 @@ vec3f eval_environment(const scene_data& scene, const environment_data& environment, vec3f direction) { auto wl = transform_direction(inverse(environment.frame), direction); auto texcoord = vec2f{ - atan2(wl.z, wl.x) / (2 * pif), acos(-clamp(wl.y, -1.0f, 1.0f)) / pif}; + atan2(wl.z, wl.x) / (2 * pif), acos(clamp(wl.y, -1.0f, 1.0f)) / pif}; if (texcoord.x < 0) texcoord.x += 1; return environment.emission * xyz(eval_texture(scene, environment.emission_tex, texcoord)); diff --git a/libs/yocto/yocto_scene.h b/libs/yocto/yocto_scene.h index e21c3c74a..a95981bc1 100644 --- a/libs/yocto/yocto_scene.h +++ b/libs/yocto/yocto_scene.h @@ -243,14 +243,14 @@ ray3f eval_camera(const camera_data& camera, vec2f image_uv, vec2f lens_uv); namespace yocto { // Evaluates a texture -vec4f eval_texture(const texture_data& texture, vec2f uv, - bool ldr_as_linear = false, bool no_vflip = false); -vec4f eval_texture(const scene_data& scene, int texture, vec2f uv, - bool ldr_as_linear = false, bool no_vflip = false); +vec4f eval_texture( + const texture_data& texture, vec2f uv, bool ldr_as_linear = false); +vec4f eval_texture( + const scene_data& scene, int texture, vec2f uv, bool ldr_as_linear = false); // pixel access -vec4f lookup_texture(const texture_data& texture, vec2i ij, - bool ldr_as_linear = false, bool no_vflip = false); +vec4f lookup_texture( + const texture_data& texture, vec2i ij, bool ldr_as_linear = false); // conversion from image texture_data image_to_texture(const image_t& image, bool linear); diff --git a/libs/yocto/yocto_sceneio.cpp b/libs/yocto/yocto_sceneio.cpp index cfd2b2564..b4096bdb8 100644 --- a/libs/yocto/yocto_sceneio.cpp +++ b/libs/yocto/yocto_sceneio.cpp @@ -700,7 +700,7 @@ void save_imageb(const string& filename, const image_t& image) { namespace yocto { // Load mesh -shape_data load_shape(const string& filename) { +shape_data load_shape(const string& filename, bool flip_texcoords) { auto shape = shape_data{}; auto ext = path_extension(filename); if (ext == ".ply" || ext == ".PLY") { @@ -708,7 +708,8 @@ shape_data load_shape(const string& filename) { // TODO: remove when all as arrays get_positions(ply, (vector>&)shape.positions); get_normals(ply, (vector>&)shape.normals); - get_texcoords(ply, (vector>&)shape.texcoords); + get_texcoords( + ply, (vector>&)shape.texcoords, flip_texcoords); get_colors(ply, (vector>&)shape.colors); get_radius(ply, shape.radius); get_faces(ply, (vector>&)shape.triangles, @@ -724,7 +725,8 @@ shape_data load_shape(const string& filename) { // TODO: remove when all as arrays get_positions(obj, (vector>&)shape.positions); get_normals(obj, (vector>&)shape.normals); - get_texcoords(obj, (vector>&)shape.texcoords); + get_texcoords( + obj, (vector>&)shape.texcoords, flip_texcoords); get_faces(obj, (vector>&)shape.triangles, (vector>&)shape.quads, materials); get_lines(obj, (vector>&)shape.lines, materials); @@ -749,14 +751,16 @@ shape_data load_shape(const string& filename) { } // Save ply mesh -void save_shape(const string& filename, const shape_data& shape, bool ascii) { +void save_shape(const string& filename, const shape_data& shape, + bool flip_texcoords, bool ascii) { auto ext = path_extension(filename); if (ext == ".ply" || ext == ".PLY") { auto ply = ply_model{}; // TODO: remove when all as arrays add_positions(ply, (const vector>&)shape.positions); add_normals(ply, (const vector>&)shape.normals); - add_texcoords(ply, (const vector>&)shape.texcoords); + add_texcoords( + ply, (const vector>&)shape.texcoords, flip_texcoords); add_colors(ply, (const vector>&)shape.colors); add_radius(ply, shape.radius); add_faces(ply, (const vector>&)shape.triangles, @@ -769,7 +773,8 @@ void save_shape(const string& filename, const shape_data& shape, bool ascii) { // TODO: remove when all as arrays add_positions(obj, (const vector>&)shape.positions); add_normals(obj, (const vector>&)shape.normals); - add_texcoords(obj, (const vector>&)shape.texcoords); + add_texcoords( + obj, (const vector>&)shape.texcoords, flip_texcoords); add_triangles(obj, (const vector>&)shape.triangles, 0, !shape.normals.empty(), !shape.texcoords.empty()); add_quads(obj, (const vector>&)shape.quads, 0, @@ -851,7 +856,7 @@ void save_shape(const string& filename, const shape_data& shape, bool ascii) { } // Load face-varying mesh -fvshape_data load_fvshape(const string& filename) { +fvshape_data load_fvshape(const string& filename, bool flip_texcoords) { auto shape = fvshape_data{}; auto ext = path_extension(filename); if (ext == ".ply" || ext == ".PLY") { @@ -859,7 +864,8 @@ fvshape_data load_fvshape(const string& filename) { // TODO: remove when all as arrays get_positions(ply, (vector>&)shape.positions); get_normals(ply, (vector>&)shape.normals); - get_texcoords(ply, (vector>&)shape.texcoords); + get_texcoords( + ply, (vector>&)shape.texcoords, flip_texcoords); get_quads(ply, (vector>&)shape.quadspos); if (!shape.normals.empty()) shape.quadsnorm = shape.quadspos; if (!shape.texcoords.empty()) shape.quadstexcoord = shape.quadspos; @@ -870,7 +876,8 @@ fvshape_data load_fvshape(const string& filename) { auto materials = vector{}; get_positions(obj, (vector>&)shape.positions); get_normals(obj, (vector>&)shape.normals); - get_texcoords(obj, (vector>&)shape.texcoords); + get_texcoords( + obj, (vector>&)shape.texcoords, flip_texcoords); get_fvquads(obj, (vector>&)shape.quadspos, (vector>&)shape.quadsnorm, (vector>&)shape.quadstexcoord, materials); @@ -895,23 +902,24 @@ fvshape_data load_fvshape(const string& filename) { } // Save ply mesh -void save_fvshape( - const string& filename, const fvshape_data& shape, bool ascii) { +void save_fvshape(const string& filename, const fvshape_data& shape, + bool flip_texcoords, bool ascii) { auto ext = path_extension(filename); if (ext == ".ply" || ext == ".PLY") { - return save_shape(filename, fvshape_to_shape(shape), ascii); + return save_shape(filename, fvshape_to_shape(shape), flip_texcoords, ascii); } else if (ext == ".obj" || ext == ".OBJ") { auto obj = obj_shape{}; // TODO: remove when all as arrays add_positions(obj, (const vector>&)shape.positions); add_normals(obj, (const vector>&)shape.normals); - add_texcoords(obj, (const vector>&)shape.texcoords); + add_texcoords( + obj, (const vector>&)shape.texcoords, flip_texcoords); add_fvquads(obj, (const vector>&)shape.quadspos, (const vector>&)shape.quadsnorm, (const vector>&)shape.quadstexcoord, 0); save_obj(filename, obj); } else if (ext == ".stl" || ext == ".STL") { - return save_shape(filename, fvshape_to_shape(shape), ascii); + return save_shape(filename, fvshape_to_shape(shape), flip_texcoords, ascii); } else if (ext == ".cpp" || ext == ".CPP") { auto to_cpp = [](const string& name, const string& vname, const auto& values) -> string { @@ -3706,7 +3714,6 @@ static scene_data load_gltf_scene(const string& filename, bool noparallel) { "cannot load " + filename + " for unsupported primitive type"}; } } - for (auto& texcoord : shape.texcoords) texcoord.y = 1 - texcoord.y; } } @@ -3870,13 +3877,6 @@ static void save_gltf_scene( } } - // UV flip - auto flip_uv = [](const vector& texcoords) { - auto ftexcoords = texcoords; - for (auto& uv : ftexcoords) uv.y = 1 - uv.y; - return ftexcoords; - }; - // buffers auto shape_accessor_start = vector{}; if (!scene.shapes.empty()) { @@ -3943,7 +3943,7 @@ static void save_gltf_scene( add_vertex(cgltf, gbuffer, shape.normals.size(), cgltf_type_vec3, (const float*)shape.normals.data()); add_vertex(cgltf, gbuffer, shape.texcoords.size(), cgltf_type_vec2, - (const float*)flip_uv(shape.texcoords).data()); + (const float*)shape.texcoords.data()); add_vertex(cgltf, gbuffer, shape.colors.size(), cgltf_type_vec4, (const float*)shape.colors.data()); add_vertex(cgltf, gbuffer, shape.radius.size(), cgltf_type_scalar, diff --git a/libs/yocto/yocto_sceneio.h b/libs/yocto/yocto_sceneio.h index 98000efe7..3d12d30aa 100644 --- a/libs/yocto/yocto_sceneio.h +++ b/libs/yocto/yocto_sceneio.h @@ -117,14 +117,14 @@ bool make_texture_preset( namespace yocto { // Load/save a shape -shape_data load_shape(const string& filename); -void save_shape( - const string& filename, const shape_data& shape, bool ascii = false); +shape_data load_shape(const string& filename, bool flip_texcoords = true); +void save_shape(const string& filename, const shape_data& shape, + bool flip_texcoords = true, bool ascii = false); // Load/save a subdiv -fvshape_data load_fvshape(const string& filename); -void save_fvshape( - const string& filename, const fvshape_data& shape, bool ascii = false); +fvshape_data load_fvshape(const string& filename, bool flip_texcoords = true); +void save_fvshape(const string& filename, const fvshape_data& shape, + bool flip_texcoords = true, bool ascii = false); // Make presets. Supported mostly in IO. shape_data make_shape_preset(const string& type); diff --git a/libs/yocto/yocto_trace.cpp b/libs/yocto/yocto_trace.cpp index 0b19b54bc..253fccc6f 100644 --- a/libs/yocto/yocto_trace.cpp +++ b/libs/yocto/yocto_trace.cpp @@ -361,9 +361,8 @@ static vec3f sample_lights(const scene_data& scene, const trace_lights& lights, auto& texture = scene.textures[environment.emission_tex]; auto idx = sample_discrete(light.elements_cdf, rel); auto size = max(texture.pixelsf.size(), texture.pixelsb.size()); - // we avoid flipping twice the v in the uv and returned direction - auto uv = vec2f{((idx % size.x) + 0.5f) / size.x, - 1 - ((idx / size.x) + 0.5f) / size.y}; + auto uv = vec2f{ + ((idx % size.x) + 0.5f) / size.x, ((idx / size.x) + 0.5f) / size.y}; return transform_direction(environment.frame, {cos(uv.x * 2 * pif) * sin(uv.y * pif), cos(uv.y * pif), sin(uv.x * 2 * pif) * sin(uv.y * pif)}); @@ -407,9 +406,8 @@ static float sample_lights_pdf(const scene_data& scene, const trace_bvh& bvh, if (environment.emission_tex != invalidid) { auto& emission_tex = scene.textures[environment.emission_tex]; auto wl = transform_direction(inverse(environment.frame), direction); - // we avoid flipping twice the v in the texcoord and ij - auto texcoord = vec2f{atan2(wl.z, wl.x) / (2 * pif), - acos(-clamp(wl.y, -1.0f, 1.0f)) / pif}; + auto texcoord = vec2f{atan2(wl.z, wl.x) / (2 * pif), + acos(clamp(wl.y, -1.0f, 1.0f)) / pif}; if (texcoord.x < 0) texcoord.x += 1; auto size = max( emission_tex.pixelsf.size(), emission_tex.pixelsb.size()); @@ -1590,7 +1588,7 @@ trace_lights make_trace_lights( light.elements_cdf = vector(size.x * size.y); for (auto idx : range(light.elements_cdf.size())) { auto ij = vec2i{(int)idx % size.x, (int)idx / size.x}; - auto th = pif - (ij.y + 0.5f) * pif / size.y; + auto th = (ij.y + 0.5f) * pif / size.y; auto value = lookup_texture(texture, ij); light.elements_cdf[idx] = max(value) * sin(th); if (idx != 0) light.elements_cdf[idx] += light.elements_cdf[idx - 1];