diff options
author | Aras Pranckevicius <aras@nesnausk.org> | 2022-06-14 10:19:02 +0300 |
---|---|---|
committer | Aras Pranckevicius <aras@nesnausk.org> | 2022-06-14 10:19:02 +0300 |
commit | 1b4f35f6a5889d8d2e65c6231e84f8b1744c4f96 (patch) | |
tree | cfae52865680308729ad955ad623c3151188097a /source/blender/io/wavefront_obj/exporter | |
parent | 827fa8176737f822b7f8d2354b05e59976c7101a (diff) |
obj: vertex colors support in importer and exporter
Adds support for vertex colors to OBJ I/O.
Importer:
- Supports both "xyzrgb" and "MRGB" vertex color formats.
- Whenever vertex color is present in the file for a model, it is
imported and a Color attribute is created (per-vertex, full float
color data type). Color coming from the file is assumed to be sRGB,
and is converted to linear upon import.
Exporter:
- Option to export the vertex colors. Defaults to "off", since not
all 3rd party software supports vertex colors.
- When the option is "on", if a mesh has a color attribute layer,
the active one is exported in "xyzrgb" form. If the mesh has
per-face-corner colors, they are averaged on the vertices.
Colors are converted from linear to sRGB upon export.
Reviewed By: Howard Trickey
Differential Revision: https://developer.blender.org/D15159
Diffstat (limited to 'source/blender/io/wavefront_obj/exporter')
5 files changed, 46 insertions, 8 deletions
diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc index 11d1bafdafe..cb95c561547 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc @@ -8,7 +8,9 @@ #include <cstdio> #include "BKE_blender_version.h" +#include "BKE_geometry_set.hh" +#include "BLI_color.hh" #include "BLI_enumerable_thread_specific.hh" #include "BLI_path_util.h" #include "BLI_task.hh" @@ -241,13 +243,38 @@ void obj_parallel_chunked_output(FormatHandler<eFileType::OBJ> &fh, } void OBJWriter::write_vertex_coords(FormatHandler<eFileType::OBJ> &fh, - const OBJMesh &obj_mesh_data) const + const OBJMesh &obj_mesh_data, + bool write_colors) const { const int tot_count = obj_mesh_data.tot_vertices(); - obj_parallel_chunked_output(fh, tot_count, [&](FormatHandler<eFileType::OBJ> &buf, int i) { - float3 vertex = obj_mesh_data.calc_vertex_coords(i, export_params_.scaling_factor); - buf.write<eOBJSyntaxElement::vertex_coords>(vertex[0], vertex[1], vertex[2]); - }); + + Mesh *mesh = obj_mesh_data.get_mesh(); + CustomDataLayer *colors_layer = nullptr; + if (write_colors) { + colors_layer = BKE_id_attributes_active_color_get(&mesh->id); + } + if (write_colors && (colors_layer != nullptr)) { + MeshComponent component; + component.replace(mesh, GeometryOwnershipType::ReadOnly); + VArray<ColorGeometry4f> attribute = component.attribute_get_for_read<ColorGeometry4f>( + colors_layer->name, ATTR_DOMAIN_POINT, {0.0f, 0.0f, 0.0f, 0.0f}); + + BLI_assert(tot_count == attribute.size()); + obj_parallel_chunked_output(fh, tot_count, [&](FormatHandler<eFileType::OBJ> &buf, int i) { + float3 vertex = obj_mesh_data.calc_vertex_coords(i, export_params_.scaling_factor); + ColorGeometry4f linear = attribute.get(i); + float srgb[3]; + linearrgb_to_srgb_v3_v3(srgb, linear); + buf.write<eOBJSyntaxElement::vertex_coords_color>( + vertex[0], vertex[1], vertex[2], srgb[0], srgb[1], srgb[2]); + }); + } + else { + obj_parallel_chunked_output(fh, tot_count, [&](FormatHandler<eFileType::OBJ> &buf, int i) { + float3 vertex = obj_mesh_data.calc_vertex_coords(i, export_params_.scaling_factor); + buf.write<eOBJSyntaxElement::vertex_coords>(vertex[0], vertex[1], vertex[2]); + }); + } } void OBJWriter::write_uv_coords(FormatHandler<eFileType::OBJ> &fh, OBJMesh &r_obj_mesh_data) const diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.hh b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.hh index 77da7b44276..97c23484426 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.hh +++ b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.hh @@ -72,9 +72,11 @@ class OBJWriter : NonMovable, NonCopyable { */ void write_mtllib_name(const StringRefNull mtl_filepath) const; /** - * Write vertex coordinates for all vertices as "v x y z". + * Write vertex coordinates for all vertices as "v x y z" or "v x y z r g b". */ - void write_vertex_coords(FormatHandler<eFileType::OBJ> &fh, const OBJMesh &obj_mesh_data) const; + void write_vertex_coords(FormatHandler<eFileType::OBJ> &fh, + const OBJMesh &obj_mesh_data, + bool write_colors) const; /** * Write UV vertex coordinates for all vertices as `vt u v`. * \note UV indices are stored here, but written with polygons later. diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_io.hh b/source/blender/io/wavefront_obj/exporter/obj_export_io.hh index f0263989bfc..157d7760307 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_io.hh +++ b/source/blender/io/wavefront_obj/exporter/obj_export_io.hh @@ -30,6 +30,7 @@ enum class eFileType { enum class eOBJSyntaxElement { vertex_coords, + vertex_coords_color, uv_vertex_coords, normal, poly_element_begin, @@ -130,6 +131,9 @@ constexpr FormattingSyntax syntax_elem_to_formatting(const eOBJSyntaxElement key case eOBJSyntaxElement::vertex_coords: { return {"v {:.6f} {:.6f} {:.6f}\n", 3, is_type_float<T...>}; } + case eOBJSyntaxElement::vertex_coords_color: { + return {"v {:.6f} {:.6f} {:.6f} {:.6f} {:.6f} {:.6f}\n", 6, is_type_float<T...>}; + } case eOBJSyntaxElement::uv_vertex_coords: { return {"vt {:.6f} {:.6f}\n", 2, is_type_float<T...>}; } diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh index 91213ec8152..ee2e6227700 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh +++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh @@ -241,6 +241,11 @@ class OBJMesh : NonCopyable { return i < 0 || i >= poly_order_.size() ? i : poly_order_[i]; } + Mesh *get_mesh() const + { + return export_mesh_eval_; + } + private: /** * Free the mesh if _the exporter_ created it. diff --git a/source/blender/io/wavefront_obj/exporter/obj_exporter.cc b/source/blender/io/wavefront_obj/exporter/obj_exporter.cc index b6e636b389d..b0938084efb 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_exporter.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_exporter.cc @@ -195,7 +195,7 @@ static void write_mesh_objects(Vector<std::unique_ptr<OBJMesh>> exportable_as_me auto &fh = buffers[i]; obj_writer.write_object_name(fh, obj); - obj_writer.write_vertex_coords(fh, obj); + obj_writer.write_vertex_coords(fh, obj, export_params.export_colors); if (obj.tot_polygons() > 0) { if (export_params.export_smooth_groups) { |