diff options
-rw-r--r-- | intern/rigidbody/RBI_api.h | 6 | ||||
-rw-r--r-- | intern/rigidbody/rb_bullet_api.cpp | 45 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py | 35 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/rigidbody.c | 12 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_rigidbody_types.h | 15 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_rigidbody.c | 128 |
6 files changed, 234 insertions, 7 deletions
diff --git a/intern/rigidbody/RBI_api.h b/intern/rigidbody/RBI_api.h index 9dde2cc3049..e7c88d96873 100644 --- a/intern/rigidbody/RBI_api.h +++ b/intern/rigidbody/RBI_api.h @@ -257,6 +257,7 @@ extern rbConstraint *RB_constraint_new_slider(float pivot[3], float orn[4], rbRi extern rbConstraint *RB_constraint_new_piston(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2); extern rbConstraint *RB_constraint_new_6dof(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2); extern rbConstraint *RB_constraint_new_6dof_spring(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2); +extern rbConstraint *RB_constraint_new_motor(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2); /* ............ */ @@ -292,6 +293,11 @@ extern void RB_constraint_set_damping_6dof_spring(rbConstraint *con, int axis, f extern void RB_constraint_set_spring_6dof_spring(rbConstraint *con, int axis, int enable); extern void RB_constraint_set_equilibrium_6dof_spring(rbConstraint *con); +/* motors */ +extern void RB_constraint_set_enable_motor(rbConstraint *con, int enable_lin, int enable_ang); +extern void RB_constraint_set_max_impulse_motor(rbConstraint *con, float max_impulse_lin, float max_impulse_ang); +extern void RB_constraint_set_target_velocity_motor(rbConstraint *con, float velocity_lin, float velocity_ang); + /* Set number of constraint solver iterations made per step, this overrided world setting * To use default set it to -1 */ extern void RB_constraint_set_solver_iterations(rbConstraint *con, int num_solver_iterations); diff --git a/intern/rigidbody/rb_bullet_api.cpp b/intern/rigidbody/rb_bullet_api.cpp index 58345d4e08c..a628c35218c 100644 --- a/intern/rigidbody/rb_bullet_api.cpp +++ b/intern/rigidbody/rb_bullet_api.cpp @@ -850,6 +850,27 @@ rbConstraint *RB_constraint_new_6dof_spring(float pivot[3], float orn[4], rbRigi return (rbConstraint *)con; } +rbConstraint *RB_constraint_new_motor(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); + + btGeneric6DofConstraint *con = new btGeneric6DofConstraint(*body1, *body2, transform1, transform2, true); + + /* unlock constraint axes */ + for (int i = 0; i < 6; i++) { + con->setLimit(i, 0.0f, -1.0f); + } + /* unlock motor axes */ + con->getTranslationalLimitMotor()->m_upperLimit.setValue(-1.0f, -1.0f, -1.0f); + + return (rbConstraint*)con; +} + /* Cleanup ----------------------------- */ void RB_constraint_delete(rbConstraint *con) @@ -947,4 +968,28 @@ void RB_constraint_set_breaking_threshold(rbConstraint *con, float threshold) constraint->setBreakingImpulseThreshold(threshold); } +void RB_constraint_set_enable_motor(rbConstraint *con, int enable_lin, int enable_ang) +{ + btGeneric6DofConstraint *constraint = reinterpret_cast<btGeneric6DofConstraint*>(con); + + constraint->getTranslationalLimitMotor()->m_enableMotor[0] = enable_lin; + constraint->getRotationalLimitMotor(0)->m_enableMotor = enable_ang; +} + +void RB_constraint_set_max_impulse_motor(rbConstraint *con, float max_impulse_lin, float max_impulse_ang) +{ + btGeneric6DofConstraint *constraint = reinterpret_cast<btGeneric6DofConstraint*>(con); + + constraint->getTranslationalLimitMotor()->m_maxMotorForce.setX(max_impulse_lin); + constraint->getRotationalLimitMotor(0)->m_maxMotorForce = max_impulse_ang; +} + +void RB_constraint_set_target_velocity_motor(rbConstraint *con, float velocity_lin, float velocity_ang) +{ + btGeneric6DofConstraint *constraint = reinterpret_cast<btGeneric6DofConstraint*>(con); + + constraint->getTranslationalLimitMotor()->m_targetVelocity.setX(velocity_lin); + constraint->getRotationalLimitMotor(0)->m_targetVelocity = velocity_ang; +} + /* ********************************** */ 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 e4e5b94407d..a49c6d623ca 100644 --- a/release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py +++ b/release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py @@ -51,11 +51,12 @@ class PHYSICS_PT_rigid_body_constraint(PHYSICS_PT_rigidbody_constraint_panel, Pa layout.prop(rbc, "object1") layout.prop(rbc, "object2") - row = layout.row() - row.prop(rbc, "use_breaking") - sub = row.row() - sub.active = rbc.use_breaking - sub.prop(rbc, "breaking_threshold", text="Threshold") + if rbc.type != 'MOTOR': + row = layout.row() + row.prop(rbc, "use_breaking") + sub = row.row() + sub.active = rbc.use_breaking + sub.prop(rbc, "breaking_threshold", text="Threshold") row = layout.row() row.prop(rbc, "override_solver_iterations", text="Override Iterations") @@ -113,6 +114,30 @@ class PHYSICS_PT_rigid_body_constraint(PHYSICS_PT_rigidbody_constraint_panel, Pa sub.prop(rbc, "limit_ang_x_lower", text="Lower") sub.prop(rbc, "limit_ang_x_upper", text="Upper") + elif rbc.type == 'MOTOR': + col = layout.column(align=True) + col.label("Linear motor:") + + row = col.row() + sub = row.row() + sub.scale_x = 0.5 + sub.prop(rbc, "use_motor_lin", toggle=True, text="Enable") + sub = row.row() + sub.active = rbc.use_motor_lin + sub.prop(rbc, "motor_lin_target_velocity", text="Target Velocity") + sub.prop(rbc, "motor_lin_max_impulse", text="Max Impulse") + + col.label("Angular motor:") + + row = col.row() + sub = row.row() + sub.scale_x = 0.5 + sub.prop(rbc, "use_motor_ang", toggle=True, text="Enable") + sub = row.row() + sub.active = rbc.use_motor_ang + sub.prop(rbc, "motor_ang_target_velocity", text="Target Velocity") + sub.prop(rbc, "motor_ang_max_impulse", text="Max Impulse") + elif rbc.type in {'GENERIC', 'GENERIC_SPRING'}: 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 c2fd6a9f54a..4c6bae122cd 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -633,6 +633,13 @@ void BKE_rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, shor else RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Z, 0.0f, -1.0f); break; + case RBC_TYPE_MOTOR: + rbc->physics_constraint = RB_constraint_new_motor(loc, rot, rb1, rb2); + + RB_constraint_set_enable_motor(rbc->physics_constraint, rbc->flag & RBC_FLAG_USE_MOTOR_LIN, rbc->flag & RBC_FLAG_USE_MOTOR_ANG); + RB_constraint_set_max_impulse_motor(rbc->physics_constraint, rbc->motor_lin_max_impulse, rbc->motor_ang_max_impulse); + RB_constraint_set_target_velocity_motor(rbc->physics_constraint, rbc->motor_lin_target_velocity, rbc->motor_ang_target_velocity); + break; } } else { /* can't create constraint without both rigid bodies */ @@ -816,6 +823,11 @@ RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, short ty rbc->spring_stiffness_y = 10.0f; rbc->spring_stiffness_z = 10.0f; + rbc->motor_lin_max_impulse = 1.0f; + rbc->motor_lin_target_velocity = 1.0f; + rbc->motor_ang_max_impulse = 1.0f; + rbc->motor_ang_target_velocity = 1.0f; + /* flag cache as outdated */ BKE_rigidbody_cache_reset(rbw); diff --git a/source/blender/makesdna/DNA_rigidbody_types.h b/source/blender/makesdna/DNA_rigidbody_types.h index 01a680e558a..c144bc4e588 100644 --- a/source/blender/makesdna/DNA_rigidbody_types.h +++ b/source/blender/makesdna/DNA_rigidbody_types.h @@ -221,6 +221,12 @@ typedef struct RigidBodyCon { float spring_damping_y; float spring_damping_z; + /* motor settings */ + float motor_lin_target_velocity; /* linear velocity the motor tries to hold */ + float motor_ang_target_velocity; /* angular velocity the motor tries to hold */ + float motor_lin_max_impulse; /* maximum force used to reach linear target velocity */ + float motor_ang_max_impulse; /* maximum force used to reach angular target velocity */ + /* References to Physics Sim object. Exist at runtime only */ void *physics_constraint; /* Physics object representation (i.e. btTypedConstraint) */ } RigidBodyCon; @@ -249,7 +255,9 @@ typedef enum eRigidBodyCon_Type { /* similar to slider but also allows rotation around slider axis */ RBC_TYPE_PISTON, /* Simplified spring constraint with only once axis that's automatically placed between the connected bodies */ - RBC_TYPE_SPRING + RBC_TYPE_SPRING, + /* dirves bodies by applying linear and angular forces */ + RBC_TYPE_MOTOR } eRigidBodyCon_Type; /* Flags for RigidBodyCon */ @@ -274,7 +282,10 @@ typedef enum eRigidBodyCon_Flag { /* springs */ RBC_FLAG_USE_SPRING_X = (1 << 11), RBC_FLAG_USE_SPRING_Y = (1 << 12), - RBC_FLAG_USE_SPRING_Z = (1 << 13) + RBC_FLAG_USE_SPRING_Z = (1 << 13), + /* motors */ + RBC_FLAG_USE_MOTOR_LIN = (1 << 14), + RBC_FLAG_USE_MOTOR_ANG = (1 << 15) } eRigidBodyCon_Flag; /* ******************************** */ diff --git a/source/blender/makesrna/intern/rna_rigidbody.c b/source/blender/makesrna/intern/rna_rigidbody.c index 7270ccadb81..f5cf247b5a1 100644 --- a/source/blender/makesrna/intern/rna_rigidbody.c +++ b/source/blender/makesrna/intern/rna_rigidbody.c @@ -72,6 +72,7 @@ EnumPropertyItem rigidbody_con_type_items[] = { {RBC_TYPE_6DOF, "GENERIC", ICON_NONE, "Generic", "Restrict translation and rotation to specified axes"}, {RBC_TYPE_6DOF_SPRING, "GENERIC_SPRING", ICON_NONE, "Generic Spring", "Restrict translation and rotation to specified axes with springs"}, + {RBC_TYPE_MOTOR, "MOTOR", ICON_NONE, "Motor", "Drive rigid body around or along an axis"}, {0, NULL, 0, NULL, NULL}}; @@ -501,6 +502,85 @@ static void rna_RigidBodyCon_spring_damping_z_set(PointerRNA *ptr, float value) #endif } +static void rna_RigidBodyCon_motor_lin_max_impulse_set(PointerRNA *ptr, float value) +{ + RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; + + rbc->motor_lin_max_impulse = value; + +#ifdef WITH_BULLET + if (rbc->physics_constraint && rbc->type == RBC_TYPE_MOTOR) { + RB_constraint_set_max_impulse_motor(rbc->physics_constraint, value, rbc->motor_ang_max_impulse); + } +#endif +} + +static void rna_RigidBodyCon_use_motor_lin_set(PointerRNA *ptr, int value) +{ + RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; + + RB_FLAG_SET(rbc->flag, value, RBC_FLAG_USE_MOTOR_LIN); + +#ifdef WITH_BULLET + if (rbc->physics_constraint) { + RB_constraint_set_enable_motor(rbc->physics_constraint, rbc->flag & RBC_FLAG_USE_MOTOR_LIN, rbc->flag & RBC_FLAG_USE_MOTOR_ANG); + } +#endif +} + +static void rna_RigidBodyCon_use_motor_ang_set(PointerRNA *ptr, int value) +{ + RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; + + RB_FLAG_SET(rbc->flag, value, RBC_FLAG_USE_MOTOR_ANG); + +#ifdef WITH_BULLET + if (rbc->physics_constraint) { + RB_constraint_set_enable_motor(rbc->physics_constraint, rbc->flag & RBC_FLAG_USE_MOTOR_LIN, rbc->flag & RBC_FLAG_USE_MOTOR_ANG); + } +#endif +} + +static void rna_RigidBodyCon_motor_lin_target_velocity_set(PointerRNA *ptr, float value) +{ + RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; + + rbc->motor_lin_target_velocity = value; + +#ifdef WITH_BULLET + if (rbc->physics_constraint && rbc->type == RBC_TYPE_MOTOR) { + RB_constraint_set_target_velocity_motor(rbc->physics_constraint, value, rbc->motor_ang_target_velocity); + } +#endif +} + +static void rna_RigidBodyCon_motor_ang_max_impulse_set(PointerRNA *ptr, float value) +{ + RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; + + rbc->motor_ang_max_impulse = value; + +#ifdef WITH_BULLET + if (rbc->physics_constraint && rbc->type == RBC_TYPE_MOTOR) { + RB_constraint_set_max_impulse_motor(rbc->physics_constraint, rbc->motor_lin_max_impulse, value); + } +#endif +} + +static void rna_RigidBodyCon_motor_ang_target_velocity_set(PointerRNA *ptr, float value) +{ + RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; + + rbc->motor_ang_target_velocity = value; + +#ifdef WITH_BULLET + if (rbc->physics_constraint && rbc->type == RBC_TYPE_MOTOR) { + RB_constraint_set_target_velocity_motor(rbc->physics_constraint, rbc->motor_lin_target_velocity, value); + } +#endif +} + + #else static void rna_def_rigidbody_world(BlenderRNA *brna) @@ -866,6 +946,18 @@ static void rna_def_rigidbody_constraint(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Z Spring", "Enable spring on Z axis"); RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset"); + prop = RNA_def_property(srna, "use_motor_lin", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_MOTOR_LIN); + RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyCon_use_motor_lin_set"); + RNA_def_property_ui_text(prop, "Linear Motor", "Enables linear motor"); + RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "use_motor_ang", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_MOTOR_ANG); + RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyCon_use_motor_ang_set"); + RNA_def_property_ui_text(prop, "Angular Motor", "Enables angular motor"); + RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset"); + prop = RNA_def_property(srna, "limit_lin_x_lower", PROP_FLOAT, PROP_UNIT_LENGTH); RNA_def_property_float_sdna(prop, NULL, "limit_lin_x_lower"); RNA_def_property_float_default(prop, -1.0f); @@ -994,6 +1086,42 @@ static void rna_def_rigidbody_constraint(BlenderRNA *brna) RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_spring_damping_z_set", NULL); RNA_def_property_ui_text(prop, "Damping Z", "Damping on the Z axis"); RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "motor_lin_target_velocity", PROP_FLOAT, PROP_UNIT_VELOCITY); + RNA_def_property_float_sdna(prop, NULL, "motor_lin_target_velocity"); + RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); + RNA_def_property_ui_range(prop, -100.0f, 100.0f, 1, 3); + RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_motor_lin_target_velocity_set", NULL); + RNA_def_property_ui_text(prop, "Target Velocity", "Target linear motor velocity"); + RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "motor_lin_max_impulse", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "motor_lin_max_impulse"); + RNA_def_property_range(prop, 0.0f, FLT_MAX); + RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3); + RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_motor_lin_max_impulse_set", NULL); + RNA_def_property_ui_text(prop, "Max Impulse", "Maximum linear motor impulse"); + RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "motor_ang_target_velocity", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "motor_ang_target_velocity"); + RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); + RNA_def_property_ui_range(prop, -100.0f, 100.0f, 1, 3); + RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_motor_ang_target_velocity_set", NULL); + RNA_def_property_ui_text(prop, "Target Velocity", "Target angular motor velocity"); + RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "motor_ang_max_impulse", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "motor_ang_max_impulse"); + RNA_def_property_range(prop, 0.0f, FLT_MAX); + RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3); + RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_motor_ang_max_impulse_set", NULL); + RNA_def_property_ui_text(prop, "Max Impulse", "Maximum angular motor impulse"); + RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset"); } void RNA_def_rigidbody(BlenderRNA *brna) |