Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/blender/blender_curves.cpp
| Show First 20 Lines • Show All 283 Lines • ▼ Show 20 Lines | static void ExportCurveSegments(Scene *scene, Hair *hair, ParticleCurveData *CData) | ||||
| if (hair->num_curves()) | if (hair->num_curves()) | ||||
| return; | return; | ||||
| Attribute *attr_intercept = NULL; | Attribute *attr_intercept = NULL; | ||||
| Attribute *attr_random = NULL; | Attribute *attr_random = NULL; | ||||
| if (hair->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT)) | if (hair->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT)) | ||||
| attr_intercept = hair->attributes.add(ATTR_STD_CURVE_INTERCEPT); | attr_intercept = hair->get_attributes().add(ATTR_STD_CURVE_INTERCEPT); | ||||
| if (hair->need_attribute(scene, ATTR_STD_CURVE_RANDOM)) | if (hair->need_attribute(scene, ATTR_STD_CURVE_RANDOM)) | ||||
| attr_random = hair->attributes.add(ATTR_STD_CURVE_RANDOM); | attr_random = hair->get_attributes().add(ATTR_STD_CURVE_RANDOM); | ||||
| /* compute and reserve size of arrays */ | /* compute and reserve size of arrays */ | ||||
| for (int sys = 0; sys < CData->psys_firstcurve.size(); sys++) { | for (int sys = 0; sys < CData->psys_firstcurve.size(); sys++) { | ||||
| for (int curve = CData->psys_firstcurve[sys]; | for (int curve = CData->psys_firstcurve[sys]; | ||||
| curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys]; | curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys]; | ||||
| curve++) { | curve++) { | ||||
| num_keys += CData->curve_keynum[curve]; | num_keys += CData->curve_keynum[curve]; | ||||
| num_curves++; | num_curves++; | ||||
| } | } | ||||
| } | } | ||||
| if (num_curves > 0) { | if (num_curves > 0) { | ||||
| VLOG(1) << "Exporting curve segments for mesh " << hair->name; | VLOG(1) << "Exporting curve segments for mesh " << hair->get_name(); | ||||
| } | } | ||||
| hair->reserve_curves(hair->num_curves() + num_curves, hair->get_curve_keys().size() + num_keys); | hair->reserve_curves(hair->num_curves() + num_curves, hair->get_curve_keys().size() + num_keys); | ||||
| num_keys = 0; | num_keys = 0; | ||||
| num_curves = 0; | num_curves = 0; | ||||
| /* actually export */ | /* actually export */ | ||||
| ▲ Show 20 Lines • Show All 80 Lines • ▼ Show 20 Lines | static float4 LerpCurveSegmentMotionCV(ParticleCurveData *CData, int sys, int curve, float step) | ||||
| return lerp(mP, mP2, remainder); | return lerp(mP, mP2, remainder); | ||||
| } | } | ||||
| static void export_hair_motion_validate_attribute(Hair *hair, | static void export_hair_motion_validate_attribute(Hair *hair, | ||||
| int motion_step, | int motion_step, | ||||
| int num_motion_keys, | int num_motion_keys, | ||||
| bool have_motion) | bool have_motion) | ||||
| { | { | ||||
| Attribute *attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); | Attribute *attr_mP = hair->get_attributes().find(ATTR_STD_MOTION_VERTEX_POSITION); | ||||
| const int num_keys = hair->get_curve_keys().size(); | const int num_keys = hair->get_curve_keys().size(); | ||||
| if (num_motion_keys != num_keys || !have_motion) { | if (num_motion_keys != num_keys || !have_motion) { | ||||
| /* No motion or hair "topology" changed, remove attributes again. */ | /* No motion or hair "topology" changed, remove attributes again. */ | ||||
| if (num_motion_keys != num_keys) { | if (num_motion_keys != num_keys) { | ||||
| VLOG(1) << "Hair topology changed, removing attribute."; | VLOG(1) << "Hair topology changed, removing attribute."; | ||||
| } | } | ||||
| else { | else { | ||||
| VLOG(1) << "No motion, removing attribute."; | VLOG(1) << "No motion, removing attribute."; | ||||
| } | } | ||||
| hair->attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION); | hair->get_attributes().remove(ATTR_STD_MOTION_VERTEX_POSITION); | ||||
| } | } | ||||
| else if (motion_step > 0) { | else if (motion_step > 0) { | ||||
| VLOG(1) << "Filling in new motion vertex position for motion_step " << motion_step; | VLOG(1) << "Filling in new motion vertex position for motion_step " << motion_step; | ||||
| /* Motion, fill up previous steps that we might have skipped because | /* Motion, fill up previous steps that we might have skipped because | ||||
| * they had no motion, but we need them anyway now. */ | * they had no motion, but we need them anyway now. */ | ||||
| for (int step = 0; step < motion_step; step++) { | for (int step = 0; step < motion_step; step++) { | ||||
| float4 *mP = attr_mP->data_float4() + step * num_keys; | float4 *mP = attr_mP->data_float4() + step * num_keys; | ||||
| for (int key = 0; key < num_keys; key++) { | for (int key = 0; key < num_keys; key++) { | ||||
| mP[key] = float3_to_float4(hair->get_curve_keys()[key]); | mP[key] = float3_to_float4(hair->get_curve_keys()[key]); | ||||
| mP[key].w = hair->get_curve_radius()[key]; | mP[key].w = hair->get_curve_radius()[key]; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void ExportCurveSegmentsMotion(Hair *hair, ParticleCurveData *CData, int motion_step) | static void ExportCurveSegmentsMotion(Hair *hair, ParticleCurveData *CData, int motion_step) | ||||
| { | { | ||||
| VLOG(1) << "Exporting curve motion segments for hair " << hair->name << ", motion step " | VLOG(1) << "Exporting curve motion segments for hair " << hair->get_name() << ", motion step " | ||||
| << motion_step; | << motion_step; | ||||
| /* find attribute */ | /* find attribute */ | ||||
| Attribute *attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); | Attribute *attr_mP = hair->get_attributes().find(ATTR_STD_MOTION_VERTEX_POSITION); | ||||
| bool new_attribute = false; | bool new_attribute = false; | ||||
| /* add new attribute if it doesn't exist already */ | /* add new attribute if it doesn't exist already */ | ||||
| if (!attr_mP) { | if (!attr_mP) { | ||||
| VLOG(1) << "Creating new motion vertex position attribute"; | VLOG(1) << "Creating new motion vertex position attribute"; | ||||
| attr_mP = hair->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION); | attr_mP = hair->get_attributes().add(ATTR_STD_MOTION_VERTEX_POSITION); | ||||
| new_attribute = true; | new_attribute = true; | ||||
| } | } | ||||
| /* export motion vectors for curve keys */ | /* export motion vectors for curve keys */ | ||||
| size_t numkeys = hair->get_curve_keys().size(); | size_t numkeys = hair->get_curve_keys().size(); | ||||
| float4 *mP = attr_mP->data_float4() + motion_step * numkeys; | float4 *mP = attr_mP->data_float4() + motion_step * numkeys; | ||||
| bool have_motion = false; | bool have_motion = false; | ||||
| int i = 0; | int i = 0; | ||||
| ▲ Show 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | void BlenderSync::sync_particle_hair( | ||||
| /* generated coordinates from first key. we should ideally get this from | /* generated coordinates from first key. we should ideally get this from | ||||
| * blender to handle deforming objects */ | * blender to handle deforming objects */ | ||||
| if (!motion) { | if (!motion) { | ||||
| if (hair->need_attribute(scene, ATTR_STD_GENERATED)) { | if (hair->need_attribute(scene, ATTR_STD_GENERATED)) { | ||||
| float3 loc, size; | float3 loc, size; | ||||
| mesh_texture_space(b_mesh, loc, size); | mesh_texture_space(b_mesh, loc, size); | ||||
| Attribute *attr_generated = hair->attributes.add(ATTR_STD_GENERATED); | Attribute *attr_generated = hair->get_attributes().add(ATTR_STD_GENERATED); | ||||
| float3 *generated = attr_generated->data_float3(); | float3 *generated = attr_generated->data_float3(); | ||||
| for (size_t i = 0; i < hair->num_curves(); i++) { | for (size_t i = 0; i < hair->num_curves(); i++) { | ||||
| float3 co = hair->get_curve_keys()[hair->get_curve(i).first_key]; | float3 co = hair->get_curve_keys()[hair->get_curve(i).get_first_key()]; | ||||
| generated[i] = co * size - loc; | generated[i] = co * size - loc; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* create vertex color attributes */ | /* create vertex color attributes */ | ||||
| if (!motion) { | if (!motion) { | ||||
| BL::Mesh::vertex_colors_iterator l; | BL::Mesh::vertex_colors_iterator l; | ||||
| int vcol_num = 0; | int vcol_num = 0; | ||||
| for (b_mesh.vertex_colors.begin(l); l != b_mesh.vertex_colors.end(); ++l, vcol_num++) { | for (b_mesh.vertex_colors.begin(l); l != b_mesh.vertex_colors.end(); ++l, vcol_num++) { | ||||
| if (!hair->need_attribute(scene, ustring(l->name().c_str()))) | if (!hair->need_attribute(scene, ustring(l->name().c_str()))) | ||||
| continue; | continue; | ||||
| ObtainCacheParticleVcol(hair, &b_mesh, &b_ob, &CData, !preview, vcol_num); | ObtainCacheParticleVcol(hair, &b_mesh, &b_ob, &CData, !preview, vcol_num); | ||||
| Attribute *attr_vcol = hair->attributes.add( | Attribute *attr_vcol = hair->get_attributes().add( | ||||
| ustring(l->name().c_str()), TypeRGBA, ATTR_ELEMENT_CURVE); | ustring(l->name().c_str()), TypeRGBA, ATTR_ELEMENT_CURVE); | ||||
| float4 *fdata = attr_vcol->data_float4(); | float4 *fdata = attr_vcol->data_float4(); | ||||
| if (fdata) { | if (fdata) { | ||||
| size_t i = 0; | size_t i = 0; | ||||
| /* Encode vertex color using the sRGB curve. */ | /* Encode vertex color using the sRGB curve. */ | ||||
| Show All 16 Lines | for (b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l, uv_num++) { | ||||
| /* UV map */ | /* UV map */ | ||||
| if (hair->need_attribute(scene, name) || hair->need_attribute(scene, std)) { | if (hair->need_attribute(scene, name) || hair->need_attribute(scene, std)) { | ||||
| Attribute *attr_uv; | Attribute *attr_uv; | ||||
| ObtainCacheParticleUV(hair, &b_mesh, &b_ob, &CData, !preview, uv_num); | ObtainCacheParticleUV(hair, &b_mesh, &b_ob, &CData, !preview, uv_num); | ||||
| if (active_render) | if (active_render) | ||||
| attr_uv = hair->attributes.add(std, name); | attr_uv = hair->get_attributes().add(std, name); | ||||
| else | else | ||||
| attr_uv = hair->attributes.add(name, TypeFloat2, ATTR_ELEMENT_CURVE); | attr_uv = hair->get_attributes().add(name, TypeFloat2, ATTR_ELEMENT_CURVE); | ||||
| float2 *uv = attr_uv->data_float2(); | float2 *uv = attr_uv->data_float2(); | ||||
| if (uv) { | if (uv) { | ||||
| size_t i = 0; | size_t i = 0; | ||||
| for (size_t curve = 0; curve < CData.curve_uv.size(); curve++) { | for (size_t curve = 0; curve < CData.curve_uv.size(); curve++) { | ||||
| uv[i++] = CData.curve_uv[curve]; | uv[i++] = CData.curve_uv[curve]; | ||||
| Show All 30 Lines | |||||
| { | { | ||||
| /* TODO: optimize so we can straight memcpy arrays from Blender? */ | /* TODO: optimize so we can straight memcpy arrays from Blender? */ | ||||
| /* Add requested attributes. */ | /* Add requested attributes. */ | ||||
| Attribute *attr_intercept = NULL; | Attribute *attr_intercept = NULL; | ||||
| Attribute *attr_random = NULL; | Attribute *attr_random = NULL; | ||||
| if (hair->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT)) { | if (hair->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT)) { | ||||
| attr_intercept = hair->attributes.add(ATTR_STD_CURVE_INTERCEPT); | attr_intercept = hair->get_attributes().add(ATTR_STD_CURVE_INTERCEPT); | ||||
| } | } | ||||
| if (hair->need_attribute(scene, ATTR_STD_CURVE_RANDOM)) { | if (hair->need_attribute(scene, ATTR_STD_CURVE_RANDOM)) { | ||||
| attr_random = hair->attributes.add(ATTR_STD_CURVE_RANDOM); | attr_random = hair->get_attributes().add(ATTR_STD_CURVE_RANDOM); | ||||
| } | } | ||||
| /* Reserve memory. */ | /* Reserve memory. */ | ||||
| const int num_keys = b_hair.points.length(); | const int num_keys = b_hair.points.length(); | ||||
| const int num_curves = b_hair.curves.length(); | const int num_curves = b_hair.curves.length(); | ||||
| if (num_curves > 0) { | if (num_curves > 0) { | ||||
| VLOG(1) << "Exporting curve segments for hair " << hair->name; | VLOG(1) << "Exporting curve segments for hair " << hair->get_name(); | ||||
| } | } | ||||
| hair->reserve_curves(num_curves, num_keys); | hair->reserve_curves(num_curves, num_keys); | ||||
| /* Export curves and points. */ | /* Export curves and points. */ | ||||
| vector<float> points_length; | vector<float> points_length; | ||||
| BL::Hair::curves_iterator b_curve_iter; | BL::Hair::curves_iterator b_curve_iter; | ||||
| ▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | for (b_hair.curves.begin(b_curve_iter); b_curve_iter != b_hair.curves.end(); ++b_curve_iter) { | ||||
| /* Curve. */ | /* Curve. */ | ||||
| const int shader_index = 0; | const int shader_index = 0; | ||||
| hair->add_curve(first_point_index, shader_index); | hair->add_curve(first_point_index, shader_index); | ||||
| } | } | ||||
| } | } | ||||
| static void export_hair_curves_motion(Hair *hair, BL::Hair b_hair, int motion_step) | 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 " | VLOG(1) << "Exporting curve motion segments for hair " << hair->get_name() << ", motion step " | ||||
| << motion_step; | << motion_step; | ||||
| /* Find or add attribute. */ | /* Find or add attribute. */ | ||||
| Attribute *attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); | Attribute *attr_mP = hair->get_attributes().find(ATTR_STD_MOTION_VERTEX_POSITION); | ||||
| bool new_attribute = false; | bool new_attribute = false; | ||||
| if (!attr_mP) { | if (!attr_mP) { | ||||
| VLOG(1) << "Creating new motion vertex position attribute"; | VLOG(1) << "Creating new motion vertex position attribute"; | ||||
| attr_mP = hair->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION); | attr_mP = hair->get_attributes().add(ATTR_STD_MOTION_VERTEX_POSITION); | ||||
| new_attribute = true; | new_attribute = true; | ||||
| } | } | ||||
| /* Export motion keys. */ | /* Export motion keys. */ | ||||
| const int num_keys = hair->get_curve_keys().size(); | const int num_keys = hair->get_curve_keys().size(); | ||||
| float4 *mP = attr_mP->data_float4() + motion_step * num_keys; | float4 *mP = attr_mP->data_float4() + motion_step * num_keys; | ||||
| bool have_motion = false; | bool have_motion = false; | ||||
| int num_motion_keys = 0; | int num_motion_keys = 0; | ||||
| int curve_index = 0; | int curve_index = 0; | ||||
| BL::Hair::curves_iterator b_curve_iter; | 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) { | 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; | BL::HairCurve b_curve = *b_curve_iter; | ||||
| const int first_point_index = b_curve.first_point_index(); | const int first_point_index = b_curve.first_point_index(); | ||||
| const int num_points = b_curve.num_points(); | const int num_points = b_curve.num_points(); | ||||
| Hair::Curve curve = hair->get_curve(curve_index); | Hair::Curve curve = hair->get_curve(curve_index); | ||||
| curve_index++; | curve_index++; | ||||
| if (num_points == curve.num_keys) { | if (num_points == curve.get_num_keys()) { | ||||
| /* Number of keys matches. */ | /* Number of keys matches. */ | ||||
| for (int i = 0; i < num_points; i++) { | for (int i = 0; i < num_points; i++) { | ||||
| int point_index = first_point_index + i; | int point_index = first_point_index + i; | ||||
| if (point_index < num_keys) { | if (point_index < num_keys) { | ||||
| mP[num_motion_keys] = hair_point_as_float4(b_hair.points[point_index]); | mP[num_motion_keys] = hair_point_as_float4(b_hair.points[point_index]); | ||||
| num_motion_keys++; | num_motion_keys++; | ||||
| if (!have_motion) { | if (!have_motion) { | ||||
| /* TODO: use epsilon for comparison? Was needed for particles due to | /* TODO: use epsilon for comparison? Was needed for particles due to | ||||
| * transform, but ideally should not happen anymore. */ | * transform, but ideally should not happen anymore. */ | ||||
| float4 curve_key = float3_to_float4(hair->get_curve_keys()[i]); | float4 curve_key = float3_to_float4(hair->get_curve_keys()[i]); | ||||
| curve_key.w = hair->get_curve_radius()[i]; | curve_key.w = hair->get_curve_radius()[i]; | ||||
| have_motion = !(mP[i] == curve_key); | have_motion = !(mP[i] == curve_key); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| /* Number of keys has changed. Generate an interpolated version | /* Number of keys has changed. Generate an interpolated version | ||||
| * to preserve motion blur. */ | * to preserve motion blur. */ | ||||
| const float step_size = curve.num_keys > 1 ? 1.0f / (curve.num_keys - 1) : 0.0f; | const float step_size = curve.get_num_keys() > 1 ? 1.0f / (curve.get_num_keys() - 1) : 0.0f; | ||||
| for (int i = 0; i < curve.num_keys; i++) { | for (int i = 0; i < curve.get_num_keys(); i++) { | ||||
| const float step = i * step_size; | const float step = i * step_size; | ||||
| mP[num_motion_keys] = interpolate_hair_points(b_hair, first_point_index, num_points, step); | mP[num_motion_keys] = interpolate_hair_points(b_hair, first_point_index, num_points, step); | ||||
| num_motion_keys++; | num_motion_keys++; | ||||
| } | } | ||||
| have_motion = true; | have_motion = true; | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | else { | ||||
| sync_particle_hair(&new_hair, b_mesh, b_ob, false); | sync_particle_hair(&new_hair, b_mesh, b_ob, false); | ||||
| free_object_to_mesh(b_data, b_ob, b_mesh); | free_object_to_mesh(b_data, b_ob, b_mesh); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* update original sockets */ | /* update original sockets */ | ||||
| for (const SocketType &socket : new_hair.type->inputs) { | for (const SocketType &socket : new_hair.get_type()->get_inputs()) { | ||||
| /* Those sockets are updated in sync_object, so do not modify them. */ | /* Those sockets are updated in sync_object, so do not modify them. */ | ||||
| if (socket.name == "use_motion_blur" || socket.name == "motion_steps" || | if (socket.get_name() == "use_motion_blur" || socket.get_name() == "motion_steps" || | ||||
| socket.name == "used_shaders") { | socket.get_name() == "used_shaders") { | ||||
| continue; | continue; | ||||
| } | } | ||||
| hair->set_value(socket, new_hair, socket); | hair->set_value(socket, new_hair, socket); | ||||
| } | } | ||||
| hair->attributes.clear(); | hair->get_attributes().clear(); | ||||
| foreach (Attribute &attr, new_hair.attributes.attributes) { | foreach (Attribute &attr, new_hair.get_attributes().get_attributes()) { | ||||
| hair->attributes.attributes.push_back(std::move(attr)); | hair->get_attributes().get_attributes().push_back(std::move(attr)); | ||||
| } | } | ||||
| /* tag update */ | /* tag update */ | ||||
| /* Compares curve_keys rather than strands in order to handle quick hair | /* Compares curve_keys rather than strands in order to handle quick hair | ||||
| * adjustments in dynamic BVH - other methods could probably do this better. */ | * adjustments in dynamic BVH - other methods could probably do this better. */ | ||||
| const bool rebuild = (hair->curve_keys_is_modified() || hair->curve_radius_is_modified()); | const bool rebuild = (hair->curve_keys_is_modified() || hair->curve_radius_is_modified()); | ||||
| Show All 36 Lines | |||||