Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAras Pranckevicius <aras@nesnausk.org>2022-06-14 10:19:02 +0300
committerAras Pranckevicius <aras@nesnausk.org>2022-06-14 10:19:02 +0300
commit1b4f35f6a5889d8d2e65c6231e84f8b1744c4f96 (patch)
treecfae52865680308729ad955ad623c3151188097a
parent827fa8176737f822b7f8d2354b05e59976c7101a (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
-rw-r--r--source/blender/editors/io/io_obj.c3
-rw-r--r--source/blender/io/wavefront_obj/IO_wavefront_obj.h1
-rw-r--r--source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc37
-rw-r--r--source/blender/io/wavefront_obj/exporter/obj_export_file_writer.hh6
-rw-r--r--source/blender/io/wavefront_obj/exporter/obj_export_io.hh4
-rw-r--r--source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh5
-rw-r--r--source/blender/io/wavefront_obj/exporter/obj_exporter.cc2
-rw-r--r--source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc51
-rw-r--r--source/blender/io/wavefront_obj/importer/obj_import_mesh.cc24
-rw-r--r--source/blender/io/wavefront_obj/importer/obj_import_mesh.hh1
-rw-r--r--source/blender/io/wavefront_obj/importer/obj_import_objects.hh3
-rw-r--r--source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc14
-rw-r--r--source/blender/io/wavefront_obj/tests/obj_exporter_tests.hh1
-rw-r--r--source/blender/io/wavefront_obj/tests/obj_importer_tests.cc121
14 files changed, 263 insertions, 10 deletions
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,
+ const char *p,
+ const char *end,
+ GlobalVertices &r_global_vertices)
+{
+ /* MRGB color extension, in the form of
+ * "#MRGB MMRRGGBBMMRRGGBB ..."
+ * http://paulbourke.net/dataformats/obj/colour.html */
+ p = drop_whitespace(p, end);
+ const int mrgb_length = 8;
+ while (p + mrgb_length <= end) {
+ uint32_t value = 0;
+ std::from_chars_result res = std::from_chars(p, p + mrgb_length, value, 16);
+ if (res.ec == std::errc::invalid_argument || res.ec == std::errc::result_out_of_range) {
+ return;
+ }
+ unsigned char srgb[4];
+ srgb[0] = (value >> 16) & 0xFF;
+ srgb[1] = (value >> 8) & 0xFF;
+ srgb[2] = value & 0xFF;
+ srgb[3] = 0xFF;
+ float linear[4];
+ srgb_to_linearrgb_uchar4(linear, srgb);
+ r_global_vertices.vertex_colors.append({linear[0], linear[1], linear[2]});
+ geom->vertex_color_count_++;
+ p += mrgb_length;
+ }
}
static void geom_add_vertex_normal(Geometry *geom,
@@ -482,6 +528,9 @@ void OBJParser::parse(Vector<std::unique_ptr<Geometry>> &r_all_geometries,
else if (parse_keyword(p, end, "mtllib")) {
add_mtl_library(StringRef(p, end).trim());
}
+ else if (parse_keyword(p, end, "#MRGB")) {
+ geom_add_mrgb_colors(curr_geom, p, end, r_global_vertices);
+ }
/* Comments. */
else if (*p == '#') {
/* Nothing to do. */
diff --git a/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc b/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc
index 854ab96e39f..acc35ad46e1 100644
--- a/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc
+++ b/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc
@@ -8,6 +8,7 @@
#include "DNA_mesh_types.h"
#include "DNA_scene_types.h"
+#include "BKE_attribute.h"
#include "BKE_customdata.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
@@ -50,6 +51,7 @@ Object *MeshFromGeometry::create_mesh(Main *bmain,
create_edges(mesh);
create_uv_verts(mesh);
create_normals(mesh);
+ create_colors(mesh);
create_materials(bmain, materials, created_materials, obj);
if (import_params.validate_meshes || mesh_geometry_.has_invalid_polys_) {
@@ -345,4 +347,26 @@ void MeshFromGeometry::create_normals(Mesh *mesh)
MEM_freeN(loop_normals);
}
+void MeshFromGeometry::create_colors(Mesh *mesh)
+{
+ /* Nothing to do if we don't have vertex colors. */
+ if (mesh_geometry_.vertex_color_count_ < 1) {
+ return;
+ }
+ if (mesh_geometry_.vertex_color_count_ != mesh_geometry_.vertex_count_) {
+ std::cerr << "Mismatching number of vertices (" << mesh_geometry_.vertex_count_
+ << ") and colors (" << mesh_geometry_.vertex_color_count_ << ") on object '"
+ << mesh_geometry_.geometry_name_ << "', ignoring colors." << std::endl;
+ return;
+ }
+
+ CustomDataLayer *color_layer = BKE_id_attribute_new(
+ &mesh->id, "Color", CD_PROP_COLOR, ATTR_DOMAIN_POINT, nullptr);
+ float4 *colors = (float4 *)color_layer->data;
+ for (int i = 0; i < mesh_geometry_.vertex_color_count_; ++i) {
+ float3 c = global_vertices_.vertex_colors[mesh_geometry_.vertex_color_start_ + i];
+ colors[i] = float4(c.x, c.y, c.z, 1.0f);
+ }
+}
+
} // namespace blender::io::obj
diff --git a/source/blender/io/wavefront_obj/importer/obj_import_mesh.hh b/source/blender/io/wavefront_obj/importer/obj_import_mesh.hh
index cf4a2aee394..216717f3578 100644
--- a/source/blender/io/wavefront_obj/importer/obj_import_mesh.hh
+++ b/source/blender/io/wavefront_obj/importer/obj_import_mesh.hh
@@ -65,6 +65,7 @@ class MeshFromGeometry : NonMovable, NonCopyable {
Map<std::string, Material *> &created_materials,
Object *obj);
void create_normals(Mesh *mesh);
+ void create_colors(Mesh *mesh);
};
} // namespace blender::io::obj
diff --git a/source/blender/io/wavefront_obj/importer/obj_import_objects.hh b/source/blender/io/wavefront_obj/importer/obj_import_objects.hh
index b67ba46af03..69babc26bb0 100644
--- a/source/blender/io/wavefront_obj/importer/obj_import_objects.hh
+++ b/source/blender/io/wavefront_obj/importer/obj_import_objects.hh
@@ -26,6 +26,7 @@ struct GlobalVertices {
Vector<float3> vertices;
Vector<float2> uv_vertices;
Vector<float3> vertex_normals;
+ Vector<float3> vertex_colors;
};
/**
@@ -102,6 +103,8 @@ struct Geometry {
int vertex_start_ = 0;
int vertex_count_ = 0;
+ int vertex_color_start_ = 0;
+ int vertex_color_count_ = 0;
/** Edges written in the file in addition to (or even without polygon) elements. */
Vector<MEdge> edges_;
diff --git a/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc b/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc
index b384d934c82..6aec848573f 100644
--- a/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc
+++ b/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc
@@ -436,6 +436,19 @@ TEST_F(obj_exporter_regression_test, cubes_positioned)
_export.params);
}
+TEST_F(obj_exporter_regression_test, cubes_vertex_colors)
+{
+ OBJExportParamsDefault _export;
+ _export.params.export_colors = true;
+ _export.params.export_normals = false;
+ _export.params.export_uv = false;
+ _export.params.export_materials = false;
+ compare_obj_export_to_golden("io_tests/blend_geometry/cubes_vertex_colors.blend",
+ "io_tests/obj/cubes_vertex_colors.obj",
+ "",
+ _export.params);
+}
+
TEST_F(obj_exporter_regression_test, cubes_with_textures_strip)
{
OBJExportParamsDefault _export;
@@ -494,6 +507,7 @@ TEST_F(obj_exporter_regression_test, all_objects)
_export.params.forward_axis = IO_AXIS_Y;
_export.params.up_axis = IO_AXIS_Z;
_export.params.export_smooth_groups = true;
+ _export.params.export_colors = true;
compare_obj_export_to_golden("io_tests/blend_scene/all_objects.blend",
"io_tests/obj/all_objects.obj",
"io_tests/obj/all_objects.mtl",
diff --git a/source/blender/io/wavefront_obj/tests/obj_exporter_tests.hh b/source/blender/io/wavefront_obj/tests/obj_exporter_tests.hh
index 42f7620999d..7d3b41ed527 100644
--- a/source/blender/io/wavefront_obj/tests/obj_exporter_tests.hh
+++ b/source/blender/io/wavefront_obj/tests/obj_exporter_tests.hh
@@ -26,6 +26,7 @@ struct OBJExportParamsDefault {
params.export_selected_objects = false;
params.export_uv = true;
params.export_normals = true;
+ params.export_colors = false;
params.export_materials = true;
params.path_mode = PATH_REFERENCE_AUTO;
params.export_triangulated_mesh = false;
diff --git a/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc b/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc
index 6d09f522028..7cc528d4f3d 100644
--- a/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc
+++ b/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc
@@ -39,6 +39,7 @@ struct Expectation {
float3 vert_first, vert_last;
float3 normal_first;
float2 uv_first;
+ float4 color_first = {-1, -1, -1, -1};
};
class obj_importer_test : public BlendfileLoadingBaseTest {
@@ -98,6 +99,15 @@ class obj_importer_test : public BlendfileLoadingBaseTest {
CustomData_get_layer(&mesh->ldata, CD_MLOOPUV));
float2 uv_first = mloopuv ? float2(mloopuv->uv) : float2(0, 0);
EXPECT_V2_NEAR(uv_first, exp.uv_first, 0.0001f);
+ if (exp.color_first.x >= 0) {
+ const float4 *colors = (const float4 *)(CustomData_get_layer(&mesh->vdata,
+ CD_PROP_COLOR));
+ EXPECT_TRUE(colors != nullptr);
+ EXPECT_V4_NEAR(colors[0], exp.color_first, 0.0001f);
+ }
+ else {
+ EXPECT_FALSE(CustomData_has_layer(&mesh->vdata, CD_PROP_COLOR));
+ }
}
if (object->type == OB_CURVES_LEGACY) {
Curve *curve = static_cast<Curve *>(DEG_get_evaluated_object(depsgraph, object)->data);
@@ -434,7 +444,17 @@ TEST_F(obj_importer_test, import_all_objects)
float3(16, 1, -1),
float3(14, 1, 1),
float3(0, 0, 1)},
- {"OBVColCube", OB_MESH, 8, 13, 7, 26, float3(13, 1, -1), float3(11, 1, 1), float3(0, 0, 1)},
+ {"OBVColCube",
+ OB_MESH,
+ 8,
+ 13,
+ 7,
+ 26,
+ float3(13, 1, -1),
+ float3(11, 1, 1),
+ float3(0, 0, 1),
+ float2(0, 0),
+ float4(0.0f, 0.002125f, 1.0f, 1.0f)},
{"OBUVCube",
OB_MESH,
8,
@@ -490,4 +510,103 @@ TEST_F(obj_importer_test, import_all_objects)
import_and_check("all_objects.obj", expect, std::size(expect), 7);
}
+TEST_F(obj_importer_test, import_cubes_vertex_colors)
+{
+ Expectation expect[] = {
+ {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
+ {"OBCubeVertexByte",
+ OB_MESH,
+ 8,
+ 12,
+ 6,
+ 24,
+ float3(1.0f, 1.0f, -1.0f),
+ float3(-1.0f, -1.0f, 1.0f),
+ float3(0, 0, 0),
+ float2(0, 0),
+ float4(0.846873f, 0.027321f, 0.982251f, 1.0f)},
+ {"OBCubeVertexFloat",
+ OB_MESH,
+ 8,
+ 12,
+ 6,
+ 24,
+ float3(3.392028f, 1.0f, -1.0f),
+ float3(1.392028f, -1.0f, 1.0f),
+ float3(0, 0, 0),
+ float2(0, 0),
+ float4(49.99558f, 0.027321f, 0.982251f, 1.0f)},
+ {"OBCubeCornerByte",
+ OB_MESH,
+ 8,
+ 12,
+ 6,
+ 24,
+ float3(1.0f, 1.0f, -3.812445f),
+ float3(-1.0f, -1.0f, -1.812445f),
+ float3(0, 0, 0),
+ float2(0, 0),
+ float4(0.89627f, 0.036889f, 0.47932f, 1.0f)},
+ {"OBCubeCornerFloat",
+ OB_MESH,
+ 8,
+ 12,
+ 6,
+ 24,
+ float3(3.481967f, 1.0f, -3.812445f),
+ float3(1.481967f, -1.0f, -1.812445f),
+ float3(0, 0, 0),
+ float2(0, 0),
+ float4(1.564582f, 0.039217f, 0.664309f, 1.0f)},
+ {"OBCubeMultiColorAttribs",
+ OB_MESH,
+ 8,
+ 12,
+ 6,
+ 24,
+ float3(-4.725068f, -1.0f, 1.0f),
+ float3(-2.725068f, 1.0f, -1.0f),
+ float3(0, 0, 0),
+ float2(0, 0),
+ float4(0.270498f, 0.47932f, 0.262251f, 1.0f)},
+ {"OBCubeNoColors",
+ OB_MESH,
+ 8,
+ 12,
+ 6,
+ 24,
+ float3(-4.550208f, -1.0f, -1.918042f),
+ float3(-2.550208f, 1.0f, -3.918042f)},
+ };
+ import_and_check("cubes_vertex_colors.obj", expect, std::size(expect), 0);
+}
+
+TEST_F(obj_importer_test, import_cubes_vertex_colors_mrgb)
+{
+ Expectation expect[] = {{"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)},
+ {"OBCubeXYZRGB",
+ OB_MESH,
+ 8,
+ 12,
+ 6,
+ 24,
+ float3(1, 1, -1),
+ float3(-1, -1, 1),
+ float3(0, 0, 0),
+ float2(0, 0),
+ float4(0.6038f, 0.3185f, 0.1329f, 1.0f)},
+ {"OBCubeMRGB",
+ OB_MESH,
+ 8,
+ 12,
+ 6,
+ 24,
+ float3(4, 1, -1),
+ float3(2, -1, 1),
+ float3(0, 0, 0),
+ float2(0, 0),
+ float4(0.8714f, 0.6308f, 0.5271f, 1.0f)}};
+ import_and_check("cubes_vertex_colors_mrgb.obj", expect, std::size(expect), 0);
+}
+
} // namespace blender::io::obj