From ec640510a8c8ef5de8daea907da2351ef1988915 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sat, 14 Jul 2018 17:01:02 +0300 Subject: Fix T55958: allow the user to select between spring and spring2. The old springs with damping 1.0 operate in a special way that is more similar to plastic deformation than a spring. Some users rely on that, so let the user choose which implementation to use. This also restores full backward compatibility with 2.79. Reviewers: sergof Differential Revision: https://developer.blender.org/D3544 --- intern/rigidbody/RBI_api.h | 9 +- intern/rigidbody/rb_bullet_api.cpp | 55 ++++++++++- .../properties_physics_rigidbody_constraint.py | 5 + source/blender/blenkernel/intern/rigidbody.c | 66 ++++++++----- source/blender/makesdna/DNA_rigidbody_types.h | 11 ++- source/blender/makesrna/intern/rna_rigidbody.c | 102 +++++++++++++-------- 6 files changed, 181 insertions(+), 67 deletions(-) diff --git a/intern/rigidbody/RBI_api.h b/intern/rigidbody/RBI_api.h index 556ca959e64..eec94bcea50 100644 --- a/intern/rigidbody/RBI_api.h +++ b/intern/rigidbody/RBI_api.h @@ -268,6 +268,7 @@ rbConstraint *RB_constraint_new_slider(float pivot[3], float orn[4], rbRigidBody rbConstraint *RB_constraint_new_piston(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2); rbConstraint *RB_constraint_new_6dof(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2); rbConstraint *RB_constraint_new_6dof_spring(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2); +rbConstraint *RB_constraint_new_6dof_spring2(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2); rbConstraint *RB_constraint_new_motor(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2); /* ............ */ @@ -299,12 +300,18 @@ void RB_constraint_set_limits_piston(rbConstraint *con, float lin_lower, float l void RB_constraint_set_limits_6dof(rbConstraint *con, int axis, float lower, float upper); /* 6dof spring specific */ -void RB_constraint_set_limits_6dof_spring(rbConstraint *con, int axis, float lower, float upper); void RB_constraint_set_stiffness_6dof_spring(rbConstraint *con, int axis, float stiffness); void RB_constraint_set_damping_6dof_spring(rbConstraint *con, int axis, float damping); void RB_constraint_set_spring_6dof_spring(rbConstraint *con, int axis, int enable); void RB_constraint_set_equilibrium_6dof_spring(rbConstraint *con); +/* 6dof spring 2 specific */ +void RB_constraint_set_limits_6dof_spring2(rbConstraint *con, int axis, float lower, float upper); +void RB_constraint_set_stiffness_6dof_spring2(rbConstraint *con, int axis, float stiffness); +void RB_constraint_set_damping_6dof_spring2(rbConstraint *con, int axis, float damping); +void RB_constraint_set_spring_6dof_spring2(rbConstraint *con, int axis, int enable); +void RB_constraint_set_equilibrium_6dof_spring2(rbConstraint *con); + /* motors */ void RB_constraint_set_enable_motor(rbConstraint *con, int enable_lin, int enable_ang); void RB_constraint_set_max_impulse_motor(rbConstraint *con, float max_impulse_lin, float max_impulse_ang); diff --git a/intern/rigidbody/rb_bullet_api.cpp b/intern/rigidbody/rb_bullet_api.cpp index a9fbcb28529..6a50c5c93ee 100644 --- a/intern/rigidbody/rb_bullet_api.cpp +++ b/intern/rigidbody/rb_bullet_api.cpp @@ -954,11 +954,25 @@ rbConstraint *RB_constraint_new_6dof_spring(float pivot[3], float orn[4], rbRigi make_constraint_transforms(transform1, transform2, body1, body2, pivot, orn); - btTypedConstraint *con = new btGeneric6DofSpring2Constraint(*body1, *body2, transform1, transform2); + btTypedConstraint *con = new btGeneric6DofSpringConstraint(*body1, *body2, transform1, transform2, true); return (rbConstraint *)con; } +rbConstraint *RB_constraint_new_6dof_spring2(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2) +{ + btRigidBody *body1 = rb1->body; + btRigidBody *body2 = rb2->body; + btTransform transform1; + btTransform transform2; + + make_constraint_transforms(transform1, transform2, body1, body2, pivot, orn); + + btTypedConstraint *con = new btGeneric6DofSpring2Constraint(*body1, *body2, transform1, transform2); + + return (rbConstraint *)con; +} + rbConstraint *RB_constraint_new_motor(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2) { btRigidBody *body1 = rb1->body; @@ -1034,7 +1048,7 @@ void RB_constraint_set_limits_6dof(rbConstraint *con, int axis, float lower, flo constraint->setLimit(axis, lower, upper); } -void RB_constraint_set_limits_6dof_spring(rbConstraint *con, int axis, float lower, float upper) +void RB_constraint_set_limits_6dof_spring2(rbConstraint *con, int axis, float lower, float upper) { btGeneric6DofSpring2Constraint *constraint = reinterpret_cast(con); @@ -1043,26 +1057,57 @@ void RB_constraint_set_limits_6dof_spring(rbConstraint *con, int axis, float low void RB_constraint_set_stiffness_6dof_spring(rbConstraint *con, int axis, float stiffness) { - btGeneric6DofSpring2Constraint *constraint = reinterpret_cast(con); + btGeneric6DofSpringConstraint *constraint = reinterpret_cast(con); constraint->setStiffness(axis, stiffness); } void RB_constraint_set_damping_6dof_spring(rbConstraint *con, int axis, float damping) { - btGeneric6DofSpring2Constraint *constraint = reinterpret_cast(con); + btGeneric6DofSpringConstraint *constraint = reinterpret_cast(con); + + // invert damping range so that 0 = no damping + damping = (damping > 1.0f) ? 0.0f : 1.0f - damping; constraint->setDamping(axis, damping); } void RB_constraint_set_spring_6dof_spring(rbConstraint *con, int axis, int enable) { - btGeneric6DofSpring2Constraint *constraint = reinterpret_cast(con); + btGeneric6DofSpringConstraint *constraint = reinterpret_cast(con); constraint->enableSpring(axis, enable); } void RB_constraint_set_equilibrium_6dof_spring(rbConstraint *con) +{ + btGeneric6DofSpringConstraint *constraint = reinterpret_cast(con); + + constraint->setEquilibriumPoint(); +} + +void RB_constraint_set_stiffness_6dof_spring2(rbConstraint *con, int axis, float stiffness) +{ + btGeneric6DofSpring2Constraint *constraint = reinterpret_cast(con); + + constraint->setStiffness(axis, stiffness); +} + +void RB_constraint_set_damping_6dof_spring2(rbConstraint *con, int axis, float damping) +{ + btGeneric6DofSpring2Constraint *constraint = reinterpret_cast(con); + + constraint->setDamping(axis, damping); +} + +void RB_constraint_set_spring_6dof_spring2(rbConstraint *con, int axis, int enable) +{ + btGeneric6DofSpring2Constraint *constraint = reinterpret_cast(con); + + constraint->enableSpring(axis, enable); +} + +void RB_constraint_set_equilibrium_6dof_spring2(rbConstraint *con) { btGeneric6DofSpring2Constraint *constraint = reinterpret_cast(con); diff --git a/release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py b/release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py index 84a4cbb4b68..8f6b5b5d8b2 100644 --- a/release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py +++ b/release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py @@ -140,6 +140,11 @@ class PHYSICS_PT_rigid_body_constraint(PHYSICS_PT_rigidbody_constraint_panel, Pa sub.prop(rbc, "motor_ang_max_impulse", text="Max Impulse") elif rbc.type in {'GENERIC', 'GENERIC_SPRING'}: + if rbc.type == 'GENERIC_SPRING': + row = layout.row() + row.label("Spring Type:") + row.prop(rbc, "spring_type", text="") + col = layout.column(align=True) col.label("Limits:") diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 502b6a81c76..5d6695e6598 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -700,6 +700,35 @@ static void rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, bool /* --------------------- */ +static void rigidbody_constraint_init_spring( + RigidBodyCon *rbc, void (*set_spring)(rbConstraint*,int,int), + void (*set_stiffness)(rbConstraint*,int,float), void (*set_damping)(rbConstraint*,int,float) +) { + set_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->flag & RBC_FLAG_USE_SPRING_X); + set_stiffness(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->spring_stiffness_x); + set_damping(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->spring_damping_x); + + set_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->flag & RBC_FLAG_USE_SPRING_Y); + set_stiffness(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->spring_stiffness_y); + set_damping(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->spring_damping_y); + + set_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->flag & RBC_FLAG_USE_SPRING_Z); + set_stiffness(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_stiffness_z); + set_damping(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_damping_z); + + set_spring(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->flag & RBC_FLAG_USE_SPRING_ANG_X); + set_stiffness(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->spring_stiffness_ang_x); + set_damping(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->spring_damping_ang_x); + + set_spring(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->flag & RBC_FLAG_USE_SPRING_ANG_Y); + set_stiffness(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->spring_stiffness_ang_y); + set_damping(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->spring_damping_ang_y); + + set_spring(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->flag & RBC_FLAG_USE_SPRING_ANG_Z); + set_stiffness(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->spring_stiffness_ang_z); + set_damping(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->spring_damping_ang_z); +} + static void rigidbody_constraint_set_limits(RigidBodyCon *rbc, void (*set_limits)(rbConstraint*,int,float,float)) { if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X) @@ -824,35 +853,24 @@ static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, b RB_constraint_set_limits_piston(rbc->physics_constraint, lin_lower, lin_upper, ang_lower, ang_upper); break; case RBC_TYPE_6DOF_SPRING: - rbc->physics_constraint = RB_constraint_new_6dof_spring(loc, rot, rb1, rb2); - - RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->flag & RBC_FLAG_USE_SPRING_X); - RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->spring_stiffness_x); - RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->spring_damping_x); - - RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->flag & RBC_FLAG_USE_SPRING_Y); - RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->spring_stiffness_y); - RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->spring_damping_y); + if (rbc->spring_type == RBC_SPRING_TYPE2) { + rbc->physics_constraint = RB_constraint_new_6dof_spring2(loc, rot, rb1, rb2); - RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->flag & RBC_FLAG_USE_SPRING_Z); - RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_stiffness_z); - RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_damping_z); + rigidbody_constraint_init_spring(rbc, RB_constraint_set_spring_6dof_spring2, RB_constraint_set_stiffness_6dof_spring2, RB_constraint_set_damping_6dof_spring2); - RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->flag & RBC_FLAG_USE_SPRING_ANG_X); - RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->spring_stiffness_ang_x); - RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->spring_damping_ang_x); + RB_constraint_set_equilibrium_6dof_spring2(rbc->physics_constraint); - RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->flag & RBC_FLAG_USE_SPRING_ANG_Y); - RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->spring_stiffness_ang_y); - RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->spring_damping_ang_y); + rigidbody_constraint_set_limits(rbc, RB_constraint_set_limits_6dof_spring2); + } + else { + rbc->physics_constraint = RB_constraint_new_6dof_spring(loc, rot, rb1, rb2); - RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->flag & RBC_FLAG_USE_SPRING_ANG_Z); - RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->spring_stiffness_ang_z); - RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->spring_damping_ang_z); + rigidbody_constraint_init_spring(rbc, RB_constraint_set_spring_6dof_spring, RB_constraint_set_stiffness_6dof_spring, RB_constraint_set_damping_6dof_spring); - RB_constraint_set_equilibrium_6dof_spring(rbc->physics_constraint); + RB_constraint_set_equilibrium_6dof_spring(rbc->physics_constraint); - rigidbody_constraint_set_limits(rbc, RB_constraint_set_limits_6dof_spring); + rigidbody_constraint_set_limits(rbc, RB_constraint_set_limits_6dof); + } break; case RBC_TYPE_6DOF: rbc->physics_constraint = RB_constraint_new_6dof(loc, rot, rb1, rb2); @@ -1071,6 +1089,8 @@ RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, short ty rbc->flag |= RBC_FLAG_ENABLED; rbc->flag |= RBC_FLAG_DISABLE_COLLISIONS; + rbc->spring_type = RBC_SPRING_TYPE2; + rbc->breaking_threshold = 10.0f; /* no good default here, just use 10 for now */ rbc->num_solver_iterations = 10; /* 10 is Bullet default */ diff --git a/source/blender/makesdna/DNA_rigidbody_types.h b/source/blender/makesdna/DNA_rigidbody_types.h index 1cd3a22fbe0..19e49644816 100644 --- a/source/blender/makesdna/DNA_rigidbody_types.h +++ b/source/blender/makesdna/DNA_rigidbody_types.h @@ -203,7 +203,8 @@ typedef struct RigidBodyCon { int flag; /* (eRigidBodyCon_Flag) */ float breaking_threshold; /* breaking impulse threshold */ - float pad; + char spring_type; /* spring implementation to use */ + char pad[3]; /* limits */ /* translation limits */ @@ -273,9 +274,15 @@ typedef enum eRigidBodyCon_Type { /* Simplified spring constraint with only once axis that's automatically placed between the connected bodies */ RBC_TYPE_SPRING, /* dirves bodies by applying linear and angular forces */ - RBC_TYPE_MOTOR + RBC_TYPE_MOTOR, } eRigidBodyCon_Type; +/* Spring implementation type for RigidBodyOb */ +typedef enum eRigidBodyCon_SpringType { + RBC_SPRING_TYPE1 = 0, /* btGeneric6DofSpringConstraint */ + RBC_SPRING_TYPE2, /* btGeneric6DofSpring2Constraint */ +} eRigidBodyCon_SpringType; + /* Flags for RigidBodyCon */ typedef enum eRigidBodyCon_Flag { /* constraint influences rigid body motion */ diff --git a/source/blender/makesrna/intern/rna_rigidbody.c b/source/blender/makesrna/intern/rna_rigidbody.c index e1e9bb30335..853b1d9978c 100644 --- a/source/blender/makesrna/intern/rna_rigidbody.c +++ b/source/blender/makesrna/intern/rna_rigidbody.c @@ -76,6 +76,12 @@ const EnumPropertyItem rna_enum_rigidbody_constraint_type_items[] = { {RBC_TYPE_MOTOR, "MOTOR", ICON_NONE, "Motor", "Drive rigid body around or along an axis"}, {0, NULL, 0, NULL, NULL}}; +/* bullet spring type */ +const EnumPropertyItem rna_enum_rigidbody_constraint_spring_type_items[] = { + {RBC_SPRING_TYPE1, "SPRING1", ICON_NONE, "Blender 2.7", "Spring implementation used in blender 2.7. Damping is capped at 1.0"}, + {RBC_SPRING_TYPE2, "SPRING2", ICON_NONE, "Blender 2.8", "New implementation available since 2.8"}, + {0, NULL, 0, NULL, NULL}}; + #ifndef RNA_RUNTIME /* mesh source for collision shape creation */ static const EnumPropertyItem rigidbody_mesh_source_items[] = { @@ -376,6 +382,14 @@ static void rna_RigidBodyCon_type_set(PointerRNA *ptr, int value) rbc->flag |= RBC_FLAG_NEEDS_VALIDATE; } +static void rna_RigidBodyCon_spring_type_set(PointerRNA *ptr, int value) +{ + RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; + + rbc->spring_type = value; + rbc->flag |= RBC_FLAG_NEEDS_VALIDATE; +} + static void rna_RigidBodyCon_enabled_set(PointerRNA *ptr, bool value) { RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; @@ -468,6 +482,22 @@ static void rna_RigidBodyCon_num_solver_iterations_set(PointerRNA *ptr, int valu #endif } +#ifdef WITH_BULLET +static void rna_RigidBodyCon_do_set_spring_stiffness(RigidBodyCon *rbc, float value, int flag, int axis) +{ + if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & flag)) { + switch (rbc->spring_type) { + case RBC_SPRING_TYPE1: + RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, axis, value); + break; + case RBC_SPRING_TYPE2: + RB_constraint_set_stiffness_6dof_spring2(rbc->physics_constraint, axis, value); + break; + } + } +} +#endif + static void rna_RigidBodyCon_spring_stiffness_x_set(PointerRNA *ptr, float value) { RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; @@ -475,9 +505,7 @@ static void rna_RigidBodyCon_spring_stiffness_x_set(PointerRNA *ptr, float value rbc->spring_stiffness_x = value; #ifdef WITH_BULLET - if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_X)) { - RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, value); - } + rna_RigidBodyCon_do_set_spring_stiffness(rbc, value, RBC_FLAG_USE_SPRING_X, RB_LIMIT_LIN_X); #endif } @@ -488,9 +516,7 @@ static void rna_RigidBodyCon_spring_stiffness_y_set(PointerRNA *ptr, float value rbc->spring_stiffness_y = value; #ifdef WITH_BULLET - if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_Y)) { - RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, value); - } + rna_RigidBodyCon_do_set_spring_stiffness(rbc, value, RBC_FLAG_USE_SPRING_Y, RB_LIMIT_LIN_Y); #endif } @@ -501,9 +527,7 @@ static void rna_RigidBodyCon_spring_stiffness_z_set(PointerRNA *ptr, float value rbc->spring_stiffness_z = value; #ifdef WITH_BULLET - if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_Z)) { - RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, value); - } + rna_RigidBodyCon_do_set_spring_stiffness(rbc, value, RBC_FLAG_USE_SPRING_Z, RB_LIMIT_LIN_Z); #endif } @@ -514,9 +538,7 @@ static void rna_RigidBodyCon_spring_stiffness_ang_x_set(PointerRNA *ptr, float v rbc->spring_stiffness_ang_x = value; #ifdef WITH_BULLET - if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_ANG_X)) { - RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_X, value); - } + rna_RigidBodyCon_do_set_spring_stiffness(rbc, value, RBC_FLAG_USE_SPRING_ANG_X, RB_LIMIT_ANG_X); #endif } @@ -527,9 +549,7 @@ static void rna_RigidBodyCon_spring_stiffness_ang_y_set(PointerRNA *ptr, float v rbc->spring_stiffness_ang_y = value; #ifdef WITH_BULLET - if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_ANG_Y)) { - RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Y, value); - } + rna_RigidBodyCon_do_set_spring_stiffness(rbc, value, RBC_FLAG_USE_SPRING_ANG_Y, RB_LIMIT_ANG_Y); #endif } @@ -540,12 +560,26 @@ static void rna_RigidBodyCon_spring_stiffness_ang_z_set(PointerRNA *ptr, float v rbc->spring_stiffness_ang_z = value; #ifdef WITH_BULLET - if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_ANG_Z)) { - RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Z, value); - } + rna_RigidBodyCon_do_set_spring_stiffness(rbc, value, RBC_FLAG_USE_SPRING_ANG_Z, RB_LIMIT_ANG_Z); #endif } +#ifdef WITH_BULLET +static void rna_RigidBodyCon_do_set_spring_damping(RigidBodyCon *rbc, float value, int flag, int axis) +{ + if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & flag)) { + switch (rbc->spring_type) { + case RBC_SPRING_TYPE1: + RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, axis, value); + break; + case RBC_SPRING_TYPE2: + RB_constraint_set_damping_6dof_spring2(rbc->physics_constraint, axis, value); + break; + } + } +} +#endif + static void rna_RigidBodyCon_spring_damping_x_set(PointerRNA *ptr, float value) { RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; @@ -553,9 +587,7 @@ static void rna_RigidBodyCon_spring_damping_x_set(PointerRNA *ptr, float value) rbc->spring_damping_x = value; #ifdef WITH_BULLET - if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_X)) { - RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, value); - } + rna_RigidBodyCon_do_set_spring_damping(rbc, value, RBC_FLAG_USE_SPRING_X, RB_LIMIT_LIN_X); #endif } @@ -565,9 +597,7 @@ static void rna_RigidBodyCon_spring_damping_y_set(PointerRNA *ptr, float value) rbc->spring_damping_y = value; #ifdef WITH_BULLET - if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_Y)) { - RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, value); - } + rna_RigidBodyCon_do_set_spring_damping(rbc, value, RBC_FLAG_USE_SPRING_Y, RB_LIMIT_LIN_Y); #endif } @@ -577,9 +607,7 @@ static void rna_RigidBodyCon_spring_damping_z_set(PointerRNA *ptr, float value) rbc->spring_damping_z = value; #ifdef WITH_BULLET - if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_Z)) { - RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, value); - } + rna_RigidBodyCon_do_set_spring_damping(rbc, value, RBC_FLAG_USE_SPRING_Z, RB_LIMIT_LIN_Z); #endif } @@ -590,9 +618,7 @@ static void rna_RigidBodyCon_spring_damping_ang_x_set(PointerRNA *ptr, float val rbc->spring_damping_ang_x = value; #ifdef WITH_BULLET - if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_ANG_X)) { - RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_X, value); - } + rna_RigidBodyCon_do_set_spring_damping(rbc, value, RBC_FLAG_USE_SPRING_ANG_X, RB_LIMIT_ANG_X); #endif } @@ -602,9 +628,7 @@ static void rna_RigidBodyCon_spring_damping_ang_y_set(PointerRNA *ptr, float val rbc->spring_damping_ang_y = value; #ifdef WITH_BULLET - if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_ANG_Y)) { - RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Y, value); - } + rna_RigidBodyCon_do_set_spring_damping(rbc, value, RBC_FLAG_USE_SPRING_ANG_Y, RB_LIMIT_ANG_Y); #endif } @@ -614,9 +638,7 @@ static void rna_RigidBodyCon_spring_damping_ang_z_set(PointerRNA *ptr, float val rbc->spring_damping_ang_z = value; #ifdef WITH_BULLET - if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_ANG_Z)) { - RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Z, value); - } + rna_RigidBodyCon_do_set_spring_damping(rbc, value, RBC_FLAG_USE_SPRING_ANG_Z, RB_LIMIT_ANG_Z); #endif } @@ -1025,6 +1047,14 @@ static void rna_def_rigidbody_constraint(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); + prop = RNA_def_property(srna, "spring_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "spring_type"); + RNA_def_property_enum_items(prop, rna_enum_rigidbody_constraint_spring_type_items); + RNA_def_property_enum_funcs(prop, NULL, "rna_RigidBodyCon_spring_type_set", NULL); + RNA_def_property_ui_text(prop, "Spring Type", "Which implementation of spring to use"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); + prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_ENABLED); RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyCon_enabled_set"); -- cgit v1.2.3 From 5ba4d059c014a038202b6981a040ba247ff42758 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 25 Jul 2018 21:04:28 +0200 Subject: Fix (unreported) potential div-by-zero in ray/bbox intersection BLI code. Also added note that direction parameter should be normalized vector in case one intend to use returned distance values. --- source/blender/blenlib/intern/math_geom.c | 32 +++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index a48d985faed..61b8f6819cc 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -2475,9 +2475,11 @@ bool isect_ray_aabb_v3( return true; } -/* - * Test a bounding box (AABB) for ray intersection - * assumes the ray is already local to the boundbox space +/** + * Test a bounding box (AABB) for ray intersection. + * Assumes the ray is already local to the boundbox space. + * + * \note: \a direction should be normalized if you intend to use the \a tmin or \a tmax distance results! */ bool isect_ray_aabb_v3_simple( const float orig[3], const float dir[3], @@ -2486,19 +2488,25 @@ bool isect_ray_aabb_v3_simple( { double t[7]; float hit_dist[2]; - t[1] = (double)(bb_min[0] - orig[0]) / dir[0]; - t[2] = (double)(bb_max[0] - orig[0]) / dir[0]; - t[3] = (double)(bb_min[1] - orig[1]) / dir[1]; - t[4] = (double)(bb_max[1] - orig[1]) / dir[1]; - t[5] = (double)(bb_min[2] - orig[2]) / dir[2]; - t[6] = (double)(bb_max[2] - orig[2]) / dir[2]; + const double invdirx = (dir[0] > 1e-35f || dir[0] < -1e-35f) ? 1.0 / (double)dir[0] : DBL_MAX; + const double invdiry = (dir[1] > 1e-35f || dir[1] < -1e-35f) ? 1.0 / (double)dir[1] : DBL_MAX; + const double invdirz = (dir[2] > 1e-35f || dir[2] < -1e-35f) ? 1.0 / (double)dir[2] : DBL_MAX; + t[1] = (double)(bb_min[0] - orig[0]) * invdirx; + t[2] = (double)(bb_max[0] - orig[0]) * invdirx; + t[3] = (double)(bb_min[1] - orig[1]) * invdiry; + t[4] = (double)(bb_max[1] - orig[1]) * invdiry; + t[5] = (double)(bb_min[2] - orig[2]) * invdirz; + t[6] = (double)(bb_max[2] - orig[2]) * invdirz; hit_dist[0] = (float)fmax(fmax(fmin(t[1], t[2]), fmin(t[3], t[4])), fmin(t[5], t[6])); hit_dist[1] = (float)fmin(fmin(fmax(t[1], t[2]), fmax(t[3], t[4])), fmax(t[5], t[6])); - if ((hit_dist[1] < 0 || hit_dist[0] > hit_dist[1])) + if ((hit_dist[1] < 0.0f || hit_dist[0] > hit_dist[1])) { return false; + } else { - if (tmin) *tmin = hit_dist[0]; - if (tmax) *tmax = hit_dist[1]; + if (tmin) + *tmin = hit_dist[0]; + if (tmax) + *tmax = hit_dist[1]; return true; } } -- cgit v1.2.3 From 29d1db9ed6253f68c5452be1f0125ed364d4a954 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 25 Jul 2018 21:05:44 +0200 Subject: Fix T55964: Direction not normalized in isect_ray_aabb_v3_simple()? RNA API Object.ray_cast would not normalize direction vector before doing first quick bbox intersection test, while using its returned distance value. This could lead to wrong exclusion of object. Thanks to @codemanx for finding that issue. --- source/blender/makesrna/intern/rna_object_api.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index 2acda5985e1..376a89c65d1 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -332,8 +332,10 @@ static void rna_Object_ray_cast( /* Test BoundBox first (efficiency) */ BoundBox *bb = BKE_object_boundbox_get(ob); float distmin; - if (!bb || (isect_ray_aabb_v3_simple(origin, direction, bb->vec[0], bb->vec[6], &distmin, NULL) && distmin <= distance)) { - + normalize_v3(direction); /* Needed for valid distance check from isect_ray_aabb_v3_simple() call. */ + if (!bb || + (isect_ray_aabb_v3_simple(origin, direction, bb->vec[0], bb->vec[6], &distmin, NULL) && distmin <= distance)) + { BVHTreeFromMesh treeData = {NULL}; /* no need to managing allocation or freeing of the BVH data. this is generated and freed as needed */ @@ -346,9 +348,6 @@ static void rna_Object_ray_cast( hit.index = -1; hit.dist = distance; - normalize_v3(direction); - - if (BLI_bvhtree_ray_cast(treeData.tree, origin, direction, 0.0f, &hit, treeData.raycast_callback, &treeData) != -1) { -- cgit v1.2.3