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:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2020-03-17 18:30:48 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2020-03-18 13:23:05 +0300
commit9d20f170c7c07ac38e86130de591ae98e9c0cf80 (patch)
treefa8a59419d11a1163a11b0caec33150c38c004da
parent994eb1ec17efc6d0a035356d04354bfc97bf8077 (diff)
Cycles: support for rendering of new Hair object prototype
Ref T68981
-rw-r--r--intern/cycles/blender/blender_curves.cpp305
-rw-r--r--intern/cycles/blender/blender_geometry.cpp17
-rw-r--r--intern/cycles/blender/blender_object.cpp4
-rw-r--r--intern/cycles/blender/blender_sync.h1
4 files changed, 278 insertions, 49 deletions
diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp
index fe0f8f3b88a..0c87808d880 100644
--- a/intern/cycles/blender/blender_curves.cpp
+++ b/intern/cycles/blender/blender_curves.cpp
@@ -595,40 +595,6 @@ static void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, in
/* texture coords still needed */
}
-static void export_hair_motion_validate_attribute(Hair *hair,
- int motion_step,
- int num_motion_keys,
- bool have_motion)
-{
- Attribute *attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- const int num_keys = hair->curve_keys.size();
-
- if (num_motion_keys != num_keys || !have_motion) {
- /* No motion or hair "topology" changed, remove attributes again. */
- if (num_motion_keys != num_keys) {
- VLOG(1) << "Hair topology changed, removing attribute.";
- }
- else {
- VLOG(1) << "No motion, removing attribute.";
- }
- hair->attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION);
- }
- else if (motion_step > 0) {
- VLOG(1) << "Filling in new motion vertex position for motion_step " << motion_step;
-
- /* Motion, fill up previous steps that we might have skipped because
- * they had no motion, but we need them anyway now. */
- for (int step = 0; step < motion_step; step++) {
- float4 *mP = attr_mP->data_float4() + step * num_keys;
-
- for (int key = 0; key < num_keys; key++) {
- mP[key] = float3_to_float4(hair->curve_keys[key]);
- mP[key].w = hair->curve_radius[key];
- }
- }
- }
-}
-
static void ExportCurveSegments(Scene *scene, Hair *hair, ParticleCurveData *CData)
{
int num_keys = 0;
@@ -748,6 +714,40 @@ static float4 LerpCurveSegmentMotionCV(ParticleCurveData *CData, int sys, int cu
return lerp(mP, mP2, remainder);
}
+static void export_hair_motion_validate_attribute(Hair *hair,
+ int motion_step,
+ int num_motion_keys,
+ bool have_motion)
+{
+ Attribute *attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ const int num_keys = hair->curve_keys.size();
+
+ if (num_motion_keys != num_keys || !have_motion) {
+ /* No motion or hair "topology" changed, remove attributes again. */
+ if (num_motion_keys != num_keys) {
+ VLOG(1) << "Hair topology changed, removing attribute.";
+ }
+ else {
+ VLOG(1) << "No motion, removing attribute.";
+ }
+ hair->attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION);
+ }
+ else if (motion_step > 0) {
+ VLOG(1) << "Filling in new motion vertex position for motion_step " << motion_step;
+
+ /* Motion, fill up previous steps that we might have skipped because
+ * they had no motion, but we need them anyway now. */
+ for (int step = 0; step < motion_step; step++) {
+ float4 *mP = attr_mP->data_float4() + step * num_keys;
+
+ for (int key = 0; key < num_keys; key++) {
+ mP[key] = float3_to_float4(hair->curve_keys[key]);
+ mP[key].w = hair->curve_radius[key];
+ }
+ }
+ }
+}
+
static void ExportCurveSegmentsMotion(Hair *hair, ParticleCurveData *CData, int motion_step)
{
VLOG(1) << "Exporting curve motion segments for hair " << hair->name << ", motion step "
@@ -817,7 +817,7 @@ static void ExportCurveSegmentsMotion(Hair *hair, ParticleCurveData *CData, int
}
}
- /* in case of new attribute, we verify if there really was any motion */
+ /* In case of new attribute, we verify if there really was any motion. */
if (new_attribute) {
export_hair_motion_validate_attribute(hair, motion_step, i, have_motion);
}
@@ -1154,6 +1154,194 @@ void BlenderSync::sync_particle_hair(
}
}
+#ifdef WITH_NEW_OBJECT_TYPES
+static float4 hair_point_as_float4(BL::HairPoint b_point)
+{
+ float4 mP = float3_to_float4(get_float3(b_point.co()));
+ mP.w = b_point.radius();
+ return mP;
+}
+
+static float4 interpolate_hair_points(BL::Hair b_hair,
+ const int first_point_index,
+ const int num_points,
+ const float step)
+{
+ const float curve_t = step * (num_points - 1);
+ 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_hair.points[first_point_index + point_a]),
+ hair_point_as_float4(b_hair.points[first_point_index + point_b]),
+ t);
+}
+
+static void export_hair_curves(Scene *scene, Hair *hair, BL::Hair b_hair)
+{
+ /* TODO: optimize so we can straight memcpy arrays from Blender? */
+
+ /* Add requested attributes. */
+ Attribute *attr_intercept = NULL;
+ Attribute *attr_random = NULL;
+
+ if (hair->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT)) {
+ attr_intercept = hair->attributes.add(ATTR_STD_CURVE_INTERCEPT);
+ }
+ if (hair->need_attribute(scene, ATTR_STD_CURVE_RANDOM)) {
+ attr_random = hair->attributes.add(ATTR_STD_CURVE_RANDOM);
+ }
+
+ /* Reserve memory. */
+ const int num_keys = b_hair.points.length();
+ const int num_curves = b_hair.curves.length();
+
+ if (num_curves > 0) {
+ VLOG(1) << "Exporting curve segments for hair " << hair->name;
+ }
+
+ hair->reserve_curves(num_curves, num_keys);
+
+ /* Export curves and points. */
+ vector<float> points_length;
+
+ BL::Hair::curves_iterator b_curve_iter;
+ for (b_hair.curves.begin(b_curve_iter); b_curve_iter != b_hair.curves.end(); ++b_curve_iter) {
+ BL::HairCurve b_curve = *b_curve_iter;
+ const int first_point_index = b_curve.first_point_index();
+ const int num_points = b_curve.num_points();
+
+ float3 prev_co = make_float3(0.0f, 0.0f, 0.0f);
+ 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++) {
+ BL::HairPoint b_point = b_hair.points[first_point_index + i];
+
+ const float3 co = get_float3(b_point.co());
+ const float radius = b_point.radius();
+ hair->add_curve_key(co, radius);
+
+ if (attr_intercept) {
+ if (i > 0) {
+ length += len(co - prev_co);
+ points_length.push_back(length);
+ }
+ prev_co = co;
+ }
+ }
+
+ /* 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);
+ }
+ }
+
+ /* Random number per curve. */
+ if (attr_random != NULL) {
+ attr_random->add(hash_uint2_to_float(b_curve.index(), 0));
+ }
+
+ /* Curve. */
+ const int shader_index = 0;
+ hair->add_curve(first_point_index, shader_index);
+ }
+}
+
+static void export_hair_curves_motion(Hair *hair, BL::Hair b_hair, int motion_step)
+{
+ VLOG(1) << "Exporting curve motion segments for hair " << hair->name << ", motion step "
+ << motion_step;
+
+ /* Find or add attribute. */
+ Attribute *attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ bool new_attribute = false;
+
+ if (!attr_mP) {
+ VLOG(1) << "Creating new motion vertex position attribute";
+ attr_mP = hair->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
+ new_attribute = true;
+ }
+
+ /* Export motion keys. */
+ const int num_keys = hair->curve_keys.size();
+ float4 *mP = attr_mP->data_float4() + motion_step * num_keys;
+ bool have_motion = false;
+ int num_motion_keys = 0;
+ int curve_index = 0;
+
+ BL::Hair::curves_iterator b_curve_iter;
+ for (b_hair.curves.begin(b_curve_iter); b_curve_iter != b_hair.curves.end(); ++b_curve_iter) {
+ BL::HairCurve b_curve = *b_curve_iter;
+ const int first_point_index = b_curve.first_point_index();
+ const int num_points = b_curve.num_points();
+
+ Hair::Curve curve = hair->get_curve(curve_index);
+ curve_index++;
+
+ if (num_points == curve.num_keys) {
+ /* Number of keys matches. */
+ for (int i = 0; i < num_points; i++) {
+ int point_index = first_point_index + i;
+
+ if (point_index < num_keys) {
+ mP[num_motion_keys] = hair_point_as_float4(b_hair.points[point_index]);
+ num_motion_keys++;
+
+ if (!have_motion) {
+ /* TODO: use epsilon for comparison? Was needed for particles due to
+ * transform, but ideally should not happen anymore. */
+ float4 curve_key = float3_to_float4(hair->curve_keys[i]);
+ curve_key.w = hair->curve_radius[i];
+ have_motion = !(mP[i] == curve_key);
+ }
+ }
+ }
+ }
+ else {
+ /* Number of keys has changed. Generate an interpolated version
+ * to preserve motion blur. */
+ const float step_size = curve.num_keys > 1 ? 1.0f / (curve.num_keys - 1) : 0.0f;
+ for (int i = 0; i < curve.num_keys; i++) {
+ const float step = i * step_size;
+ mP[num_motion_keys] = interpolate_hair_points(b_hair, first_point_index, num_points, step);
+ num_motion_keys++;
+ }
+ have_motion = true;
+ }
+ }
+
+ /* In case of new attribute, we verify if there really was any motion. */
+ if (new_attribute) {
+ export_hair_motion_validate_attribute(hair, motion_step, num_motion_keys, have_motion);
+ }
+}
+#endif /* WITH_NEW_OBJECT_TYPES */
+
+/* Hair object. */
+void BlenderSync::sync_hair(Hair *hair, BL::Object &b_ob, bool motion, int motion_step)
+{
+#ifdef WITH_NEW_OBJECT_TYPES
+ /* Convert Blender hair to Cycles curves. */
+ BL::Hair b_hair(b_ob.data());
+ if (motion) {
+ export_hair_curves_motion(hair, b_hair, motion_step);
+ }
+ else {
+ export_hair_curves(scene, hair, b_hair);
+ }
+#else
+ (void)hair;
+ (void)b_ob;
+ (void)motion;
+ (void)motion_step;
+#endif /* WITH_NEW_OBJECT_TYPES */
+}
+
void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph,
BL::Object b_ob,
Geometry *geom,
@@ -1179,14 +1367,24 @@ void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph,
geom->used_shaders = used_shaders;
if (view_layer.use_hair && scene->curve_system_manager->use_curves) {
- /* Particle hair. */
- bool need_undeformed = geom->need_attribute(scene, ATTR_STD_GENERATED);
- BL::Mesh b_mesh = object_to_mesh(
- b_data, b_ob, b_depsgraph, need_undeformed, Mesh::SUBDIVISION_NONE);
-
- if (b_mesh) {
- sync_particle_hair(geom, b_mesh, b_ob, false);
- free_object_to_mesh(b_data, b_ob, b_mesh);
+#ifdef WITH_NEW_OBJECT_TYPES
+ if (b_ob.type() == BL::Object::type_HAIR) {
+ /* Hair object. */
+ sync_hair(hair, b_ob, false);
+ assert(mesh == NULL);
+ }
+ else
+#endif
+ {
+ /* Particle hair. */
+ bool need_undeformed = geom->need_attribute(scene, ATTR_STD_GENERATED);
+ BL::Mesh b_mesh = object_to_mesh(
+ b_data, b_ob, b_depsgraph, need_undeformed, Mesh::SUBDIVISION_NONE);
+
+ if (b_mesh) {
+ sync_particle_hair(geom, b_mesh, b_ob, false);
+ free_object_to_mesh(b_data, b_ob, b_mesh);
+ }
}
}
@@ -1213,13 +1411,24 @@ void BlenderSync::sync_hair_motion(BL::Depsgraph b_depsgraph,
/* Export deformed coordinates. */
if (ccl::BKE_object_is_deform_modified(b_ob, b_scene, preview)) {
- /* Particle hair. */
- BL::Mesh b_mesh = object_to_mesh(b_data, b_ob, b_depsgraph, false, Mesh::SUBDIVISION_NONE);
- if (b_mesh) {
- sync_particle_hair(geom, b_mesh, b_ob, true, motion_step);
- free_object_to_mesh(b_data, b_ob, b_mesh);
+#ifdef WITH_NEW_OBJECT_TYPES
+ if (b_ob.type() == BL::Object::type_HAIR) {
+ /* Hair object. */
+ sync_hair(hair, b_ob, true, motion_step);
+ assert(mesh == NULL);
return;
}
+ else
+#endif
+ {
+ /* Particle hair. */
+ BL::Mesh b_mesh = object_to_mesh(b_data, b_ob, b_depsgraph, false, Mesh::SUBDIVISION_NONE);
+ if (b_mesh) {
+ sync_particle_hair(geom, b_mesh, b_ob, true, motion_step);
+ free_object_to_mesh(b_data, b_ob, b_mesh);
+ return;
+ }
+ }
}
/* No deformation on this frame, copy coordinates if other frames did have it. */
diff --git a/intern/cycles/blender/blender_geometry.cpp b/intern/cycles/blender/blender_geometry.cpp
index ac5bae4bc66..7ca35cff961 100644
--- a/intern/cycles/blender/blender_geometry.cpp
+++ b/intern/cycles/blender/blender_geometry.cpp
@@ -40,10 +40,17 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
BL::Material material_override = view_layer.material_override;
Shader *default_shader = (b_ob.type() == BL::Object::type_VOLUME) ? scene->default_volume :
scene->default_surface;
- Geometry::Type geom_type = (use_particle_hair &&
+#ifdef WITH_NEW_OBJECT_TYPES
+ Geometry::Type geom_type = ((b_ob.type() == BL::Object::type_HAIR || use_particle_hair) &&
(scene->curve_system_manager->primitive != CURVE_TRIANGLES)) ?
Geometry::HAIR :
Geometry::MESH;
+#else
+ Geometry::Type geom_type = ((use_particle_hair) &&
+ (scene->curve_system_manager->primitive != CURVE_TRIANGLES)) ?
+ Geometry::HAIR :
+ Geometry::MESH;
+#endif
/* Find shader indices. */
vector<Shader *> used_shaders;
@@ -122,7 +129,11 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
geom->name = ustring(b_ob_data.name().c_str());
+#ifdef WITH_NEW_OBJECT_TYPES
+ if (b_ob.type() == BL::Object::type_HAIR || use_particle_hair) {
+#else
if (use_particle_hair) {
+#endif
sync_hair(b_depsgraph, b_ob, geom, used_shaders);
}
else if (b_ob.type() == BL::Object::type_VOLUME || object_fluid_gas_domain_find(b_ob)) {
@@ -162,7 +173,11 @@ void BlenderSync::sync_geometry_motion(BL::Depsgraph &b_depsgraph,
return;
}
+#ifdef WITH_NEW_OBJECT_TYPES
+ if (b_ob.type() == BL::Object::type_HAIR || use_particle_hair) {
+#else
if (use_particle_hair) {
+#endif
sync_hair_motion(b_depsgraph, b_ob, geom, motion_step);
}
else if (b_ob.type() == BL::Object::type_VOLUME || object_fluid_gas_domain_find(b_ob)) {
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index 48d309c259b..4e488f12d0d 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -69,7 +69,11 @@ bool BlenderSync::object_is_mesh(BL::Object &b_ob)
BL::Object::type_enum type = b_ob.type();
+#ifdef WITH_NEW_OBJECT_TYPES
+ if (type == BL::Object::type_VOLUME || type == BL::Object::type_HAIR) {
+#else
if (type == BL::Object::type_VOLUME) {
+#endif
/* Will be exported attached to mesh. */
return true;
}
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index d212caa69f7..25e933dc599 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -157,6 +157,7 @@ class BlenderSync {
BL::Object b_ob,
Geometry *geom,
int motion_step);
+ void sync_hair(Hair *hair, BL::Object &b_ob, bool motion, int motion_step = 0);
void sync_particle_hair(
Geometry *geom, BL::Mesh &b_mesh, BL::Object &b_ob, bool motion, int motion_step = 0);
void sync_curve_settings();