[Bf-blender-cvs] [1b4f35f6a58] master: obj: vertex colors support in importer and exporter
Aras Pranckevicius
noreply at git.blender.org
Tue Jun 14 09:19:09 CEST 2022
Commit: 1b4f35f6a5889d8d2e65c6231e84f8b1744c4f96
Author: Aras Pranckevicius
Date: Tue Jun 14 10:19:02 2022 +0300
Branches: master
https://developer.blender.org/rB1b4f35f6a5889d8d2e65c6231e84f8b1744c4f96
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
===================================================================
M source/blender/editors/io/io_obj.c
M source/blender/io/wavefront_obj/IO_wavefront_obj.h
M source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc
M source/blender/io/wavefront_obj/exporter/obj_export_file_writer.hh
M source/blender/io/wavefront_obj/exporter/obj_export_io.hh
M source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh
M source/blender/io/wavefront_obj/exporter/obj_exporter.cc
M source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc
M source/blender/io/wavefront_obj/importer/obj_import_mesh.cc
M source/blender/io/wavefront_obj/importer/obj_import_mesh.hh
M source/blender/io/wavefront_obj/importer/obj_import_objects.hh
M source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc
M source/blender/io/wavefront_obj/tests/obj_exporter_tests.hh
M source/blender/io/wavefront_obj/tests/obj_importer_tests.cc
===================================================================
diff --git a/source/blender/editors/io/io_obj.c b/source/blender/editors/io/io_obj.c
index a8eed136df3..4819ae09785 100644
--- a/source/blender/editors/io/io_obj.c
+++ b/source/blender/editors/io/io_obj.c
@@ -100,6 +100,7 @@ static int wm_obj_export_exec(bContext *C, wmOperator *op)
export_params.export_selected_objects = RNA_boolean_get(op->ptr, "export_selected_objects");
export_params.export_uv = RNA_boolean_get(op->ptr, "export_uv");
export_params.export_normals = RNA_boolean_get(op->ptr, "export_normals");
+ export_params.export_colors = RNA_boolean_get(op->ptr, "export_colors");
export_params.export_materials = RNA_boolean_get(op->ptr, "export_materials");
export_params.path_mode = RNA_enum_get(op->ptr, "path_mode");
export_params.export_triangulated_mesh = RNA_boolean_get(op->ptr, "export_triangulated_mesh");
@@ -160,6 +161,7 @@ static void ui_obj_export_settings(uiLayout *layout, PointerRNA *imfptr)
sub = uiLayoutColumnWithHeading(col, false, IFACE_("Export"));
uiItemR(sub, imfptr, "export_uv", 0, IFACE_("UV Coordinates"), ICON_NONE);
uiItemR(sub, imfptr, "export_normals", 0, IFACE_("Normals"), ICON_NONE);
+ uiItemR(sub, imfptr, "export_colors", 0, IFACE_("Colors"), ICON_NONE);
uiItemR(sub, imfptr, "export_materials", 0, IFACE_("Materials"), ICON_NONE);
uiItemR(sub, imfptr, "export_triangulated_mesh", 0, IFACE_("Triangulated Mesh"), ICON_NONE);
uiItemR(sub, imfptr, "export_curves_as_nurbs", 0, IFACE_("Curves as NURBS"), ICON_NONE);
@@ -315,6 +317,7 @@ void WM_OT_obj_export(struct wmOperatorType *ot)
"Export Normals",
"Export per-face normals if the face is flat-shaded, per-face-per-loop "
"normals if smooth-shaded");
+ RNA_def_boolean(ot->srna, "export_colors", false, "Export Colors", "Export per-vertex colors");
RNA_def_boolean(ot->srna,
"export_materials",
true,
diff --git a/source/blender/io/wavefront_obj/IO_wavefront_obj.h b/source/blender/io/wavefront_obj/IO_wavefront_obj.h
index 0a78cdc714d..a719dff2126 100644
--- a/source/blender/io/wavefront_obj/IO_wavefront_obj.h
+++ b/source/blender/io/wavefront_obj/IO_wavefront_obj.h
@@ -45,6 +45,7 @@ struct OBJExportParams {
eEvaluationMode export_eval_mode;
bool export_uv;
bool export_normals;
+ bool export_colors;
bool export_materials;
bool export_triangulated_mesh;
bool export_curves_as_nurbs;
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) {
diff --git a/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc b/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc
index a627e7261e3..4a27d734819 100644
--- a/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc
+++ b/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc
@@ -5,12 +5,15 @@
*/
#include "BLI_map.hh"
+#include "BLI_math_color.h"
#include "BLI_string_ref.hh"
#include "BLI_vector.hh"
#include "obj_import_file_reader.hh"
#include "obj_import_string_utils.hh"
+#include <charconv>
+
namespace blender::io::obj {
using std::string;
@@ -34,6 +37,7 @@ static Geometry *create_geometry(Geometry *const prev_geometry,
g->geom_type_ = new_type;
g->geometry_name_ = name.is_empty() ? "New object" : name;
g->vertex_start_ = global_vertices.vertices.size();
+ g->vertex_color_start_ = global_vertices.vertex_colors.size();
r_offset.set_index_offset(g->vertex_start_);
return g;
};
@@ -71,9 +75,51 @@ static void geom_add_vertex(Geometry *geom,
GlobalVertices &r_global_vertices)
{
float3 vert;
- parse_floats(p, end, 0.0f, vert, 3);
+ p = parse_floats(p, end, 0.0f, vert, 3);
r_global_vertices.vertices.append(vert);
geom->vertex_count_++;
+ /* OBJ extension: "xyzrgb" vertex colors, when the vertex position
+ * is followed by 3 more RGB color components. See
+ * http://paulbourke.net/dataformats/obj/colour.html */
+ if (p < end) {
+ float3 srgb;
+ p = parse_floats(p, end, -1.0f, srgb, 3);
+ if (srgb.x >= 0 && srgb.y >= 0 && srgb.z >= 0) {
+ float3 linear;
+ srgb_to_linearrgb_v3_v3(linear, srgb);
+ r_global_vertices.vertex_colors.append(linear);
+ geom->vertex_color_count_++;
+ }
+ }
+}
+
+static void geom_add_mrgb_colors(Geometry *geom,
+ co
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list