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:
authorJacques Lucke <jacques@blender.org>2021-02-17 14:07:59 +0300
committerJacques Lucke <jacques@blender.org>2021-02-17 14:13:30 +0300
commit3a6d6299d7a0f2a6a156bce6731a0b29804d911d (patch)
tree90b108ad10a913de37f0f343e969287b4c535302 /intern/cycles
parent9419452f859117aa17dda7d89810c83bbdcda288 (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
Diffstat (limited to 'intern/cycles')
-rw-r--r--intern/cycles/blender/blender_mesh.cpp128
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);