diff options
Diffstat (limited to 'intern/cycles/blender/curves.cpp')
-rw-r--r-- | intern/cycles/blender/curves.cpp | 165 |
1 files changed, 100 insertions, 65 deletions
diff --git a/intern/cycles/blender/curves.cpp b/intern/cycles/blender/curves.cpp index b01cb85711a..6158ed78598 100644 --- a/intern/cycles/blender/curves.cpp +++ b/intern/cycles/blender/curves.cpp @@ -55,7 +55,7 @@ static bool ObtainCacheParticleData( return false; Transform tfm = get_transform(b_ob->matrix_world()); - Transform itfm = transform_quick_inverse(tfm); + Transform itfm = transform_inverse(tfm); for (BL::Modifier &b_mod : b_ob->modifiers) { if ((b_mod.type() == b_mod.type_PARTICLE_SYSTEM) && @@ -613,8 +613,6 @@ void BlenderSync::sync_particle_hair( } } -#ifdef WITH_NEW_CURVES_TYPE - static std::optional<BL::FloatAttribute> find_curves_radius_attribute(BL::Curves b_curves) { for (BL::Attribute &b_attribute : b_curves.attributes) { @@ -632,6 +630,25 @@ static std::optional<BL::FloatAttribute> find_curves_radius_attribute(BL::Curves return std::nullopt; } +static BL::FloatVectorAttribute find_curves_position_attribute(BL::Curves b_curves) +{ + for (BL::Attribute &b_attribute : b_curves.attributes) { + if (b_attribute.name() != "position") { + continue; + } + if (b_attribute.domain() != BL::Attribute::domain_POINT) { + continue; + } + if (b_attribute.data_type() != BL::Attribute::data_type_FLOAT_VECTOR) { + continue; + } + return BL::FloatVectorAttribute{b_attribute}; + } + /* The position attribute must exist. */ + assert(false); + return BL::FloatVectorAttribute{b_curves.attributes[0]}; +} + template<typename TypeInCycles, typename GetValueAtIndex> static void fill_generic_attribute(BL::Curves &b_curves, TypeInCycles *data, @@ -690,6 +707,21 @@ static void attr_create_motion(Hair *hair, BL::Attribute &b_attribute, const flo } } +static void attr_create_uv(AttributeSet &attributes, + BL::Curves &b_curves, + BL::Attribute &b_attribute, + const ustring name) +{ + BL::Float2Attribute b_float2_attribute{b_attribute}; + Attribute *attr = attributes.add(ATTR_STD_UV, name); + + float2 *data = attr->data_float2(); + fill_generic_attribute(b_curves, data, ATTR_ELEMENT_CURVE, [&](int i) { + BL::Array<float, 2> v = b_float2_attribute.data[i].vector(); + return make_float2(v[0], v[1]); + }); +} + static void attr_create_generic(Scene *scene, Hair *hair, BL::Curves &b_curves, @@ -698,12 +730,26 @@ static void attr_create_generic(Scene *scene, { AttributeSet &attributes = hair->attributes; static const ustring u_velocity("velocity"); + const bool need_uv = hair->need_attribute(scene, ATTR_STD_UV); + bool have_uv = false; for (BL::Attribute &b_attribute : b_curves.attributes) { const ustring name{b_attribute.name().c_str()}; + const BL::Attribute::domain_enum b_domain = b_attribute.domain(); + const BL::Attribute::data_type_enum b_data_type = b_attribute.data_type(); + if (need_motion && name == u_velocity) { attr_create_motion(hair, b_attribute, motion_scale); + continue; + } + + /* Weak, use first float2 attribute as standard UV. */ + if (need_uv && !have_uv && b_data_type == BL::Attribute::data_type_FLOAT2 && + b_domain == BL::Attribute::domain_CURVE) { + attr_create_uv(attributes, b_curves, b_attribute, name); + have_uv = true; + continue; } if (!hair->need_attribute(scene, name)) { @@ -713,9 +759,6 @@ static void attr_create_generic(Scene *scene, 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_POINT: @@ -795,16 +838,16 @@ static void attr_create_generic(Scene *scene, } } -static float4 hair_point_as_float4(BL::Curves b_curves, +static float4 hair_point_as_float4(BL::FloatVectorAttribute b_attr_position, std::optional<BL::FloatAttribute> b_attr_radius, const int index) { - float4 mP = float3_to_float4(get_float3(b_curves.position_data[index].vector())); - mP.w = b_attr_radius ? b_attr_radius->data[index].value() : 0.0f; + float4 mP = float3_to_float4(get_float3(b_attr_position.data[index].vector())); + mP.w = b_attr_radius ? b_attr_radius->data[index].value() : 0.005f; return mP; } -static float4 interpolate_hair_points(BL::Curves b_curves, +static float4 interpolate_hair_points(BL::FloatVectorAttribute b_attr_position, std::optional<BL::FloatAttribute> b_attr_radius, const int first_point_index, const int num_points, @@ -814,8 +857,8 @@ static float4 interpolate_hair_points(BL::Curves b_curves, const int point_a = clamp((int)curve_t, 0, num_points - 1); const int point_b = min(point_a + 1, num_points - 1); const float t = curve_t - (float)point_a; - return lerp(hair_point_as_float4(b_curves, b_attr_radius, first_point_index + point_a), - hair_point_as_float4(b_curves, b_attr_radius, first_point_index + point_b), + return lerp(hair_point_as_float4(b_attr_position, b_attr_radius, first_point_index + point_a), + hair_point_as_float4(b_attr_position, b_attr_radius, first_point_index + point_b), t); } @@ -827,78 +870,84 @@ static void export_hair_curves(Scene *scene, { /* TODO: optimize so we can straight memcpy arrays from Blender? */ + const int num_keys = b_curves.points.length(); + const int num_curves = b_curves.curves.length(); + + hair->resize_curves(num_curves, num_keys); + + float3 *curve_keys = hair->get_curve_keys().data(); + float *curve_radius = hair->get_curve_radius().data(); + int *curve_first_key = hair->get_curve_first_key().data(); + int *curve_shader = hair->get_curve_shader().data(); + /* Add requested attributes. */ - Attribute *attr_intercept = NULL; - Attribute *attr_length = NULL; - Attribute *attr_random = NULL; + float *attr_intercept = NULL; + float *attr_length = NULL; + float *attr_random = NULL; if (hair->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT)) { - attr_intercept = hair->attributes.add(ATTR_STD_CURVE_INTERCEPT); + attr_intercept = hair->attributes.add(ATTR_STD_CURVE_INTERCEPT)->data_float(); } if (hair->need_attribute(scene, ATTR_STD_CURVE_LENGTH)) { - attr_length = hair->attributes.add(ATTR_STD_CURVE_LENGTH); + attr_length = hair->attributes.add(ATTR_STD_CURVE_LENGTH)->data_float(); } if (hair->need_attribute(scene, ATTR_STD_CURVE_RANDOM)) { - attr_random = hair->attributes.add(ATTR_STD_CURVE_RANDOM); + attr_random = hair->attributes.add(ATTR_STD_CURVE_RANDOM)->data_float(); } - /* Reserve memory. */ - const int num_keys = b_curves.points.length(); - const int num_curves = b_curves.curves.length(); - - hair->reserve_curves(num_curves, num_keys); - + BL::FloatVectorAttribute b_attr_position = find_curves_position_attribute(b_curves); std::optional<BL::FloatAttribute> b_attr_radius = find_curves_radius_attribute(b_curves); /* Export curves and points. */ - vector<float> points_length; - for (int i = 0; i < num_curves; i++) { const int first_point_index = b_curves.curve_offset_data[i].value(); const int num_points = b_curves.curve_offset_data[i + 1].value() - first_point_index; float3 prev_co = zero_float3(); float length = 0.0f; - if (attr_intercept) { - points_length.clear(); - points_length.reserve(num_points); - } /* Position and radius. */ - for (int i = 0; i < num_points; i++) { - const float3 co = get_float3(b_curves.position_data[first_point_index + i].vector()); - const float radius = b_attr_radius ? b_attr_radius->data[first_point_index + i].value() : - 0.0f; - hair->add_curve_key(co, radius); - - if (attr_intercept) { - if (i > 0) { + for (int j = 0; j < num_points; j++) { + const int point_offset = first_point_index + j; + const float3 co = get_float3(b_attr_position.data[point_offset].vector()); + const float radius = b_attr_radius ? b_attr_radius->data[point_offset].value() : 0.005f; + + curve_keys[point_offset] = co; + curve_radius[point_offset] = radius; + + if (attr_length || attr_intercept) { + if (j > 0) { length += len(co - prev_co); - points_length.push_back(length); } prev_co = co; + + if (attr_intercept) { + attr_intercept[point_offset] = length; + } } } /* Normalized 0..1 attribute along curve. */ - if (attr_intercept) { - for (int i = 0; i < num_points; i++) { - attr_intercept->add((length == 0.0f) ? 0.0f : points_length[i] / length); + if (attr_intercept && length > 0.0f) { + for (int j = 1; j < num_points; j++) { + const int point_offset = first_point_index + j; + attr_intercept[point_offset] /= length; } } + /* Curve length. */ if (attr_length) { - attr_length->add(length); + attr_length[i] = length; } /* Random number per curve. */ if (attr_random != NULL) { - attr_random->add(hash_uint2_to_float(i, 0)); + attr_random[i] = hash_uint2_to_float(i, 0); } /* Curve. */ - const int shader_index = 0; - hair->add_curve(first_point_index, shader_index); + curve_shader[i] = 0; + curve_first_key[i] = first_point_index; } attr_create_generic(scene, hair, b_curves, need_motion, motion_scale); @@ -923,6 +972,7 @@ static void export_hair_curves_motion(Hair *hair, BL::Curves b_curves, int motio int num_motion_keys = 0; int curve_index = 0; + BL::FloatVectorAttribute b_attr_position = find_curves_position_attribute(b_curves); std::optional<BL::FloatAttribute> b_attr_radius = find_curves_radius_attribute(b_curves); for (int i = 0; i < num_curves; i++) { @@ -938,7 +988,7 @@ static void export_hair_curves_motion(Hair *hair, BL::Curves b_curves, int motio int point_index = first_point_index + i; if (point_index < num_keys) { - mP[num_motion_keys] = hair_point_as_float4(b_curves, b_attr_radius, point_index); + mP[num_motion_keys] = hair_point_as_float4(b_attr_position, b_attr_radius, point_index); num_motion_keys++; if (!have_motion) { @@ -958,7 +1008,7 @@ static void export_hair_curves_motion(Hair *hair, BL::Curves b_curves, int motio for (int i = 0; i < curve.num_keys; i++) { const float step = i * step_size; mP[num_motion_keys] = interpolate_hair_points( - b_curves, b_attr_radius, first_point_index, num_points, step); + b_attr_position, b_attr_radius, first_point_index, num_points, step); num_motion_keys++; } have_motion = true; @@ -990,15 +1040,6 @@ void BlenderSync::sync_hair(Hair *hair, BObjectInfo &b_ob_info, bool motion, int export_hair_curves(scene, hair, b_curves, need_motion, motion_scale); } } -#else -void BlenderSync::sync_hair(Hair *hair, BObjectInfo &b_ob_info, bool motion, int motion_step) -{ - (void)hair; - (void)b_ob_info; - (void)motion; - (void)motion_step; -} -#endif void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, Hair *hair) { @@ -1010,14 +1051,11 @@ void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, H new_hair.set_used_shaders(used_shaders); if (view_layer.use_hair) { -#ifdef WITH_NEW_CURVES_TYPE if (b_ob_info.object_data.is_a(&RNA_Curves)) { /* Hair object. */ sync_hair(&new_hair, b_ob_info, false); } - else -#endif - { + else { /* Particle hair. */ bool need_undeformed = new_hair.need_attribute(scene, ATTR_STD_GENERATED); BL::Mesh b_mesh = object_to_mesh( @@ -1064,15 +1102,12 @@ void BlenderSync::sync_hair_motion(BL::Depsgraph b_depsgraph, /* Export deformed coordinates. */ if (ccl::BKE_object_is_deform_modified(b_ob_info, b_scene, preview)) { -#ifdef WITH_NEW_CURVES_TYPE if (b_ob_info.object_data.is_a(&RNA_Curves)) { /* Hair object. */ sync_hair(hair, b_ob_info, true, motion_step); return; } - else -#endif - { + else { /* Particle hair. */ BL::Mesh b_mesh = object_to_mesh( b_data, b_ob_info, b_depsgraph, false, Mesh::SUBDIVISION_NONE); |