From ac1b08a9281e7a93064455b89a36715f094da2b0 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Sun, 27 Feb 2011 09:21:13 +0000 Subject: [PATCH] =?UTF-8?q?BGE=20patch:=20[#26223]=20Some=20RigidBody=20jo?= =?UTF-8?q?ints=20fixes=20(ui=20angles,=20conetwist/hinge=20limits=20etc)?= =?UTF-8?q?=20by=20Juha=20M=C3=A4ki-Kanto=20+=20ui=20changes=20pour=20moi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From the tracker::: Issues fixed: - ConeTwist-constraint's params weren't making it to the CcdPhysicsEnvironment, also added Hinge's params. - UI wasn't using angles where applicable. - btHingeConstraint's constructor can create frame-matrices which don't align so the hinge doesn's start at 0 degree tilt. This is an issue when setting limits. Changes: - UI: Hinge limits can be set (and disabled). - UI: ConeTwist only has max-limits and only the twistX can be disabled - PyApi via rna_constraint.c: added the functions limit_xyz_min, limit_xyz_max (for 6dof), limit_angle_xyz_min, limit_angle_xyz_max (for 6dof), limit_angle_x_min, limit_angle_x_max (for hinge). - PyApi: dropped python-function limit_cone_min. .:. Extra: UI Changes: - renamed "RigidBody Joint" to "Rigid Boidy Joint" - reorganized UI to conform with other parameters (e.g. Limit Rot) - added dis/active all over the place :) --- .../ui/properties_object_constraint.py | 84 +++++++++-- source/blender/blenkernel/intern/constraint.c | 2 +- .../blender/makesrna/intern/rna_constraint.c | 133 ++++++++---------- .../Converter/BL_BlenderDataConversion.cpp | 35 +++++ .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 85 +++++++++-- 5 files changed, 243 insertions(+), 96 deletions(-) diff --git a/release/scripts/ui/properties_object_constraint.py b/release/scripts/ui/properties_object_constraint.py index ad6c0630289..6034fb9e51e 100644 --- a/release/scripts/ui/properties_object_constraint.py +++ b/release/scripts/ui/properties_object_constraint.py @@ -535,32 +535,86 @@ class ConstraintButtonsPanel(): layout.label(text="Limits:") split = layout.split() - col = split.column(align=True) - col.prop(con, "use_angular_limit_x", text="Angular X") - col.prop(con, "use_angular_limit_y", text="Angular Y") - col.prop(con, "use_angular_limit_z", text="Angular Z") + col = split.column() + col.prop(con, "use_angular_limit_x", text="Angle X") + subcol = col.column() + subcol.active =con.use_angular_limit_x + subcol.prop(con, "limit_angle_max_x", text="") col = split.column() - col.prop(con, "limit_cone_min", text="") + col.prop(con, "use_angular_limit_y", text="Angle Y") + subcol = col.column() + subcol.active =con.use_angular_limit_y + subcol.prop(con, "limit_angle_max_y", text="") + col = split.column() - col.prop(con, "limit_cone_max", text="") + col.prop(con, "use_angular_limit_z", text="Angle Z") + subcol = col.column() + subcol.active =con.use_angular_limit_z + subcol.prop(con, "limit_angle_max_z", text="") elif con.pivot_type == 'GENERIC_6_DOF': layout.label(text="Limits:") split = layout.split() - + col = split.column(align=True) col.prop(con, "use_limit_x", text="X") + sub = col.column() + sub.active = con.use_limit_x + sub.prop(con, "limit_min_x", text="Min") + sub.prop(con, "limit_max_x", text="Max") + + col = split.column(align=True) col.prop(con, "use_limit_y", text="Y") + sub = col.column() + sub.active = con.use_limit_y + sub.prop(con, "limit_min_y", text="Min") + sub.prop(con, "limit_max_y", text="Max") + + col = split.column(align=True) col.prop(con, "use_limit_z", text="Z") - col.prop(con, "use_angular_limit_x", text="Angular X") - col.prop(con, "use_angular_limit_y", text="Angular Y") - col.prop(con, "use_angular_limit_z", text="Angular Z") + sub = col.column() + sub.active = con.use_limit_z + sub.prop(con, "limit_min_z", text="Min") + sub.prop(con, "limit_max_z", text="Max") + + split = layout.split() + + col = split.column(align=True) + col.prop(con, "use_angular_limit_x", text="Angle X") + sub = col.column() + sub.active = con.use_angular_limit_x + sub.prop(con, "limit_angle_min_x", text="Min") + sub.prop(con, "limit_angle_max_x", text="Max") + + col = split.column(align=True) + col.prop(con, "use_angular_limit_y", text="Angle Y") + sub = col.column() + sub.active = con.use_angular_limit_y + sub.prop(con, "limit_angle_min_y", text="Min") + sub.prop(con, "limit_angle_max_y", text="Max") + + col = split.column(align=True) + col.prop(con, "use_angular_limit_z", text="Angle Z") + sub = col.column() + sub.active = con.use_angular_limit_z + sub.prop(con, "limit_angle_min_z", text="Min") + sub.prop(con, "limit_angle_max_z", text="Max") - col = split.column() - col.prop(con, "limit_generic_min", text="") - col = split.column() - col.prop(con, "limit_generic_max", text="") + elif con.pivot_type == 'HINGE': + layout.label(text="Limits:") + split = layout.split() + + row = split.row(align=True) + col = row.column() + col.prop(con, "use_angular_limit_x", text="Angle X") + + col = row.column() + col.active = con.use_angular_limit_x + col.prop(con, "limit_angle_min_x", text="Min") + col = row.column() + col.active = con.use_angular_limit_x + col.prop(con, "limit_angle_max_x", text="Max") def CLAMP_TO(self, context, layout, con): self.target_template(layout, con) @@ -736,4 +790,4 @@ def unregister(): bpy.utils.unregister_module(__name__) if __name__ == "__main__": - register() + register() \ No newline at end of file diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 827dddf34d3..2bbed3ba9f0 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -3069,7 +3069,7 @@ static void rbj_flush_tars (bConstraint *con, ListBase *list, short nocopy) static bConstraintTypeInfo CTI_RIGIDBODYJOINT = { CONSTRAINT_TYPE_RIGIDBODYJOINT, /* type */ sizeof(bRigidBodyJointConstraint), /* size */ - "RigidBody Joint", /* name */ + "Rigid Body Joint", /* name */ "bRigidBodyJointConstraint", /* struct name */ NULL, /* free data */ NULL, /* relink data */ diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 3d516440731..92637e1577c 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -322,47 +322,6 @@ static void rna_SplineIKConstraint_joint_bindings_set(PointerRNA *ptr, const flo memcpy(ikData->points, values, ikData->numpoints * sizeof(float)); } -/* Array Get/Set Functions for RigidBodyJointConstraint Min/Max Cone Limits */ -void rna_RigidBodyJointConstraint_limit_cone_min_get(PointerRNA *ptr, float values[3]) -{ - bRigidBodyJointConstraint *data= (bRigidBodyJointConstraint*)(((bConstraint*)ptr->data)->data); - float *limit = data->minLimit; - - values[0]= limit[3]; - values[1]= limit[4]; - values[2]= limit[5]; -} - -static void rna_RigidBodyJointConstraint_limit_cone_min_set(PointerRNA *ptr, const float values[3]) -{ - bRigidBodyJointConstraint *data= (bRigidBodyJointConstraint*)(((bConstraint*)ptr->data)->data); - float *limit = data->minLimit; - - limit[3]= values[0]; - limit[4]= values[1]; - limit[5]= values[2]; -} - -void rna_RigidBodyJointConstraint_limit_cone_max_get(PointerRNA *ptr, float values[3]) -{ - bRigidBodyJointConstraint *data= (bRigidBodyJointConstraint*)(((bConstraint*)ptr->data)->data); - float *limit = data->maxLimit; - - values[0]= limit[3]; - values[1]= limit[4]; - values[2]= limit[5]; -} - -static void rna_RigidBodyJointConstraint_limit_cone_max_set(PointerRNA *ptr, const float values[3]) -{ - bRigidBodyJointConstraint *data= (bRigidBodyJointConstraint*)(((bConstraint*)ptr->data)->data); - float *limit = data->maxLimit; - - limit[3]= values[0]; - limit[4]= values[1]; - limit[5]= values[2]; -} - #else EnumPropertyItem constraint_distance_items[] = { @@ -1293,62 +1252,92 @@ static void rna_def_constraint_rigid_body_joint(BlenderRNA *brna) RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); - /* Limit */ - - /* Limit Min/Max for genereic 6 DoF */ - prop= RNA_def_property(srna, "limit_generic_min", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "minLimit"); - RNA_def_property_array(prop, 6); - RNA_def_property_ui_text(prop, "Minimum Limit", ""); + /* Limits */ + /* Limit Min/Max */ + prop= RNA_def_property(srna, "limit_min_x", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "minLimit[0]"); + RNA_def_property_ui_text(prop, "Minimum Limit X", ""); - prop= RNA_def_property(srna, "limit_generic_max", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "maxLimit"); - RNA_def_property_array(prop, 6); - RNA_def_property_ui_text(prop, "Maximum Limit", ""); - - /* Limit Min/Max for Cone Twist */ - prop= RNA_def_property(srna, "limit_cone_min", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "minLimit"); - RNA_def_property_float_funcs(prop, "rna_RigidBodyJointConstraint_limit_cone_min_get", "rna_RigidBodyJointConstraint_limit_cone_min_set", NULL); - RNA_def_property_array(prop, 3); - RNA_def_property_ui_text(prop, "Minimum Limit", ""); + prop= RNA_def_property(srna, "limit_min_y", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "minLimit[1]"); + RNA_def_property_ui_text(prop, "Minimum Limit Y", ""); - prop= RNA_def_property(srna, "limit_cone_max", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "maxLimit"); - RNA_def_property_float_funcs(prop, "rna_RigidBodyJointConstraint_limit_cone_max_get", "rna_RigidBodyJointConstraint_limit_cone_max_set", NULL); - RNA_def_property_array(prop, 3); - RNA_def_property_ui_text(prop, "Maximum Limit", ""); + prop= RNA_def_property(srna, "limit_min_z", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "minLimit[2]"); + RNA_def_property_ui_text(prop, "Minimum Limit Z", ""); - - /* Limit Booleans */ + prop= RNA_def_property(srna, "limit_max_x", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "maxLimit[0]"); + RNA_def_property_ui_text(prop, "Maximum Limit X", ""); + + prop= RNA_def_property(srna, "limit_max_y", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "maxLimit[1]"); + RNA_def_property_ui_text(prop, "Maximum Limit Y", ""); + + prop= RNA_def_property(srna, "limit_max_z", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "maxLimit[2]"); + RNA_def_property_ui_text(prop, "Maximum Limit Z", ""); + + /* Limit Min/Max for angle */ + prop= RNA_def_property(srna, "limit_angle_min_x", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "minLimit[3]"); + RNA_def_property_range(prop, -M_PI*2, M_PI*2); + RNA_def_property_ui_text(prop, "Minimum Angular Limit X", ""); + + prop= RNA_def_property(srna, "limit_angle_min_y", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "minLimit[4]"); + RNA_def_property_range(prop, -M_PI*2, M_PI*2); + RNA_def_property_ui_text(prop, "Minimum Angular Limit Y", ""); + + prop= RNA_def_property(srna, "limit_angle_min_z", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "minLimit[5]"); + RNA_def_property_range(prop, -M_PI*2, M_PI*2); + RNA_def_property_ui_text(prop, "Minimum Angular Limit Z", ""); + + prop= RNA_def_property(srna, "limit_angle_max_x", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "maxLimit[3]"); + RNA_def_property_range(prop, -M_PI*2, M_PI*2); + RNA_def_property_ui_text(prop, "Maximum Angular Limit X", ""); + + prop= RNA_def_property(srna, "limit_angle_max_y", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "maxLimit[4]"); + RNA_def_property_range(prop, -M_PI*2, M_PI*2); + RNA_def_property_ui_text(prop, "Maximum Angular Limit Y", ""); + + prop= RNA_def_property(srna, "limit_angle_max_z", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "maxLimit[5]"); + RNA_def_property_range(prop, -M_PI*2, M_PI*2); + RNA_def_property_ui_text(prop, "Maximum Angular Limit Z", ""); + + /* Limit Booleans */ prop= RNA_def_property(srna, "use_limit_x", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", 1); - RNA_def_property_ui_text(prop, "Use X Limit", "Use minimum/maximum x limit"); + RNA_def_property_ui_text(prop, "Limit X", "Use minimum/maximum x limit"); RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); prop= RNA_def_property(srna, "use_limit_y", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", 2); - RNA_def_property_ui_text(prop, "Use Y Limit", "Use minimum/maximum y limit"); + RNA_def_property_ui_text(prop, "Limit Y", "Use minimum/maximum y limit"); RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); prop= RNA_def_property(srna, "use_limit_z", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", 4); - RNA_def_property_ui_text(prop, "Use Z Limit", "Use minimum/maximum z limit"); + RNA_def_property_ui_text(prop, "Limit Z", "Use minimum/maximum z limit"); RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); prop= RNA_def_property(srna, "use_angular_limit_x", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", 8); - RNA_def_property_ui_text(prop, "Use Angular X Limit", "Use minimum/maximum x angular limit"); + RNA_def_property_ui_text(prop, "Angular X Limit", "Use minimum/maximum x angular limit"); RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); prop= RNA_def_property(srna, "use_angular_limit_y", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", 16); - RNA_def_property_ui_text(prop, "Use Angular Y Limit", "Use minimum/maximum y angular limit"); + RNA_def_property_ui_text(prop, "Angular Y Limit", "Use minimum/maximum y angular limit"); RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); prop= RNA_def_property(srna, "use_angular_limit_z", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", 32); - RNA_def_property_ui_text(prop, "Use Angular Z Limit", "Use minimum/maximum z angular limit"); + RNA_def_property_ui_text(prop, "Angular Z Limit", "Use minimum/maximum z angular limit"); RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); } diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index d69ae6b1821..35cd4edf945 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -2651,6 +2651,41 @@ void BL_ConvertBlenderObjects(struct Main* maggie, dofbit<<=1; } } + else if(dat->type == PHY_CONE_TWIST_CONSTRAINT) + { + int dof; + int dofbit = 1<<3; // bitflag use_angular_limit_x + + for (dof=3;dof<6;dof++) + { + // flag only applies to angular limit x + if(dof != 3 || dat->flag & dofbit) + { + kxscene->GetPhysicsEnvironment()->setConstraintParam(constraintId,dof,dat->minLimit[dof],dat->maxLimit[dof]); + } + else + { + //maxLimit < 0 means free(disabled limit) for this degree of freedom + kxscene->GetPhysicsEnvironment()->setConstraintParam(constraintId,dof,1,-1); + } + dofbit<<=1; + } + } + else if (dat->type == PHY_LINEHINGE_CONSTRAINT) + { + int dof = 3; // dof for angular x + int dofbit = 1<<3; // bitflag use_angular_limit_x + + if (dat->flag & dofbit) + { + kxscene->GetPhysicsEnvironment()->setConstraintParam(constraintId,dof, + dat->minLimit[dof],dat->maxLimit[dof]); + } else + { + //minLimit > maxLimit means free(disabled limit) for this degree of freedom + kxscene->GetPhysicsEnvironment()->setConstraintParam(constraintId,dof,1,-1); + } + } } } } diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 93f1d0962d7..937c70ede5e 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -1987,6 +1987,41 @@ void CcdPhysicsEnvironment::setConstraintParam(int constraintId,int param,float break; } + default: + { + } + }; + break; + }; + case PHY_CONE_TWIST_CONSTRAINT: + { + switch (param) + { + case 3: case 4: case 5: + { + //param = 3,4,5 are constraint limits, high limit values + btConeTwistConstraint* coneTwist = (btConeTwistConstraint*)typedConstraint; + coneTwist->setLimit(param,value1); + break; + } + default: + { + } + }; + break; + }; + case PHY_ANGULAR_CONSTRAINT: + case PHY_LINEHINGE_CONSTRAINT: + { + switch (param) + { + case 3: + { + //param = 3 is a constraint limit, with low/high limit value + btHingeConstraint* hingeCons = (btHingeConstraint*)typedConstraint; + hingeCons->setLimit(value0,value1); + break; + } default: { } @@ -2623,20 +2658,54 @@ int CcdPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl if (rb1) { - btVector3 axisInB = rb1 ? - (rb1->getCenterOfMassTransform().getBasis().inverse()*(rb0->getCenterOfMassTransform().getBasis() * axisInA)) : - rb0->getCenterOfMassTransform().getBasis() * axisInA; + // We know the orientations so we should use them instead of + // having btHingeConstraint fill in the blanks any way it wants to. + btTransform frameInA; + btTransform frameInB; + + btVector3 axis1(axis1X,axis1Y,axis1Z), axis2(axis2X,axis2Y,axis2Z); + if (axis1.length() == 0.0) + { + btPlaneSpace1( axisInA, axis1, axis2 ); + } + + // Internally btHingeConstraint's hinge-axis is z + frameInA.getBasis().setValue( axis1.x(), axis2.x(), axisInA.x(), + axis1.y(), axis2.y(), axisInA.y(), + axis1.z(), axis2.z(), axisInA.z() ); + + frameInA.setOrigin( pivotInA ); - hinge = new btHingeConstraint( - *rb0, - *rb1,pivotInA,pivotInB,axisInA,axisInB); + btTransform inv = rb1->getCenterOfMassTransform().inverse(); + + btTransform globalFrameA = rb0->getCenterOfMassTransform() * frameInA; + + frameInB = inv * globalFrameA; + + hinge = new btHingeConstraint(*rb0,*rb1,frameInA,frameInB); } else { - hinge = new btHingeConstraint(*rb0, - pivotInA,axisInA); + static btRigidBody s_fixedObject2( 0,0,0); + btTransform frameInA; + btTransform frameInB; + + btVector3 axis1(axis1X,axis1Y,axis1Z), axis2(axis2X,axis2Y,axis2Z); + if (axis1.length() == 0.0) + { + btPlaneSpace1( axisInA, axis1, axis2 ); + } + + // Internally btHingeConstraint's hinge-axis is z + frameInA.getBasis().setValue( axis1.x(), axis2.x(), axisInA.x(), + axis1.y(), axis2.y(), axisInA.y(), + axis1.z(), axis2.z(), axisInA.z() ); + frameInA.setOrigin( pivotInA ); + frameInB = rb0->getCenterOfMassTransform() * frameInA; + + hinge = new btHingeConstraint(*rb0, s_fixedObject2, frameInA, frameInB); } hinge->setAngularOnly(angularOnly);