diff options
author | Jacques Lucke <jacques@blender.org> | 2021-02-17 14:07:59 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2021-02-17 14:13:30 +0300 |
commit | 3a6d6299d7a0f2a6a156bce6731a0b29804d911d (patch) | |
tree | 90b108ad10a913de37f0f343e969287b4c535302 | |
parent | 9419452f859117aa17dda7d89810c83bbdcda288 (diff) |
Cycles: support accessing custom mesh attributes
This makes custom mesh attributes available in Cycles. Typically,
these attributes are generated by Geometry Nodes, but they can also
be created with a Python script.
* The `subdivision` code path is not yet supported.
* This does not make vertex weights and some other builtin attributes
available in Cycles, even though they are accesible in Geometry Nodes.
All attributes generated in Geometry Nodes should be accessible though.
* In some cases memory consumption could be removed by not storing all
attributes in floats. E.g. booleans and integer attributes for which
all values are within a certain range, could be stored in less than
4 bytes per element.
Differential Revision: https://developer.blender.org/D10210
-rw-r--r-- | intern/cycles/blender/blender_mesh.cpp | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 7edf797e096..e2b18c22d95 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -310,6 +310,133 @@ static void attr_create_sculpt_vertex_color(Scene *scene, } } +template<typename TypeInCycles, typename GetValueAtIndex> +static void fill_generic_attribute(BL::Mesh &b_mesh, + TypeInCycles *data, + const AttributeElement element, + const GetValueAtIndex &get_value_at_index) +{ + switch (element) { + case ATTR_ELEMENT_CORNER: { + for (BL::MeshLoopTriangle &t : b_mesh.loop_triangles) { + const int index = t.index() * 3; + BL::Array<int, 3> loops = t.loops(); + data[index] = get_value_at_index(loops[0]); + data[index + 1] = get_value_at_index(loops[1]); + data[index + 2] = get_value_at_index(loops[2]); + } + break; + } + case ATTR_ELEMENT_VERTEX: { + const int num_verts = b_mesh.vertices.length(); + for (int i = 0; i < num_verts; i++) { + data[i] = get_value_at_index(i); + } + break; + } + case ATTR_ELEMENT_FACE: { + for (BL::MeshLoopTriangle &t : b_mesh.loop_triangles) { + data[t.index()] = get_value_at_index(t.polygon_index()); + } + break; + } + default: { + assert(false); + break; + } + } +} + +static void attr_create_generic(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool subdivision) +{ + if (subdivision) { + /* TODO: Handle subdivison correctly. */ + return; + } + AttributeSet &attributes = mesh->attributes; + + for (BL::Attribute &b_attribute : b_mesh.attributes) { + const ustring name{b_attribute.name().c_str()}; + if (!mesh->need_attribute(scene, name)) { + continue; + } + if (attributes.find(name)) { + continue; + } + + const BL::Attribute::domain_enum b_domain = b_attribute.domain(); + const BL::Attribute::data_type_enum b_data_type = b_attribute.data_type(); + + AttributeElement element = ATTR_ELEMENT_NONE; + switch (b_domain) { + case BL::Attribute::domain_CORNER: + element = ATTR_ELEMENT_CORNER; + break; + case BL::Attribute::domain_POINT: + element = ATTR_ELEMENT_VERTEX; + break; + case BL::Attribute::domain_POLYGON: + element = ATTR_ELEMENT_FACE; + break; + default: + break; + } + if (element == ATTR_ELEMENT_NONE) { + /* Not supported. */ + continue; + } + switch (b_data_type) { + case BL::Attribute::data_type_FLOAT: { + BL::FloatAttribute b_float_attribute{b_attribute}; + Attribute *attr = attributes.add(name, TypeFloat, element); + float *data = attr->data_float(); + fill_generic_attribute( + b_mesh, data, element, [&](int i) { return b_float_attribute.data[i].value(); }); + break; + } + case BL::Attribute::data_type_BOOLEAN: { + BL::BoolAttribute b_bool_attribute{b_attribute}; + Attribute *attr = attributes.add(name, TypeFloat, element); + float *data = attr->data_float(); + fill_generic_attribute( + b_mesh, data, element, [&](int i) { return (float)b_bool_attribute.data[i].value(); }); + break; + } + case BL::Attribute::data_type_INT: { + BL::IntAttribute b_int_attribute{b_attribute}; + Attribute *attr = attributes.add(name, TypeFloat, element); + float *data = attr->data_float(); + fill_generic_attribute( + b_mesh, data, element, [&](int i) { return (float)b_int_attribute.data[i].value(); }); + break; + } + case BL::Attribute::data_type_FLOAT_VECTOR: { + BL::FloatVectorAttribute b_vector_attribute{b_attribute}; + Attribute *attr = attributes.add(name, TypeVector, element); + float3 *data = attr->data_float3(); + fill_generic_attribute(b_mesh, data, element, [&](int i) { + BL::Array<float, 3> v = b_vector_attribute.data[i].vector(); + return make_float3(v[0], v[1], v[2]); + }); + break; + } + case BL::Attribute::data_type_FLOAT_COLOR: { + BL::FloatColorAttribute b_color_attribute{b_attribute}; + Attribute *attr = attributes.add(name, TypeRGBA, element); + float4 *data = attr->data_float4(); + fill_generic_attribute(b_mesh, data, element, [&](int i) { + BL::Array<float, 4> v = b_color_attribute.data[i].color(); + return make_float4(v[0], v[1], v[2], v[3]); + }); + break; + } + default: + /* Not supported. */ + break; + } + } +} + /* Create vertex color attributes. */ static void attr_create_vertex_color(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool subdivision) { @@ -837,6 +964,7 @@ static void create_mesh(Scene *scene, attr_create_vertex_color(scene, mesh, b_mesh, subdivision); attr_create_sculpt_vertex_color(scene, mesh, b_mesh, subdivision); attr_create_random_per_island(scene, mesh, b_mesh, subdivision); + attr_create_generic(scene, mesh, b_mesh, subdivision); if (subdivision) { attr_create_subd_uv_map(scene, mesh, b_mesh, subdivide_uvs); |