diff options
-rw-r--r-- | intern/moto/include/MT_Matrix3x3.h | 20 | ||||
-rw-r--r-- | source/gameengine/Converter/KX_IpoConvert.cpp | 42 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_IPO_SGController.cpp | 134 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_IPO_SGController.h | 36 |
4 files changed, 180 insertions, 52 deletions
diff --git a/intern/moto/include/MT_Matrix3x3.h b/intern/moto/include/MT_Matrix3x3.h index fb899a7da96..98851e73040 100644 --- a/intern/moto/include/MT_Matrix3x3.h +++ b/intern/moto/include/MT_Matrix3x3.h @@ -147,6 +147,26 @@ public: -sj, cj * si, cj * ci); } + void getEuler(MT_Scalar& yaw, MT_Scalar& pitch, MT_Scalar& roll) const + { + if (m_el[2][0] != -1.0 && m_el[2][0] != 1.0) { + pitch = MT_Scalar(-asin(m_el[2][0])); + yaw = MT_Scalar(atan2(m_el[2][1] / cos(pitch), m_el[2][2] / cos(pitch))); + roll = MT_Scalar(atan2(m_el[1][0] / cos(pitch), m_el[0][0] / cos(pitch))); + } + else { + roll = MT_Scalar(0); + if (m_el[2][0] == -1.0) { + pitch = MT_PI / 2.0; + yaw = MT_Scalar(atan2(m_el[0][1], m_el[0][2])); + } + else { + pitch = - MT_PI / 2.0; + yaw = MT_Scalar(atan2(m_el[0][1], m_el[0][2])); + } + } + } + void scale(MT_Scalar x, MT_Scalar y, MT_Scalar z) { m_el[0][0] *= x; m_el[0][1] *= y; m_el[0][2] *= z; m_el[1][0] *= x; m_el[1][1] *= y; m_el[1][2] *= z; diff --git a/source/gameengine/Converter/KX_IpoConvert.cpp b/source/gameengine/Converter/KX_IpoConvert.cpp index defcdffb6fc..2cf29e9dd62 100644 --- a/source/gameengine/Converter/KX_IpoConvert.cpp +++ b/source/gameengine/Converter/KX_IpoConvert.cpp @@ -100,9 +100,9 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend ipocontr->GetIPOTransform().SetPosition( MT_Point3( - blenderobject->loc[0]+blenderobject->dloc[0], - blenderobject->loc[1]+blenderobject->dloc[1], - blenderobject->loc[2]+blenderobject->dloc[2] + blenderobject->loc[0]/*+blenderobject->dloc[0]*/, + blenderobject->loc[1]/*+blenderobject->dloc[1]*/, + blenderobject->loc[2]/*+blenderobject->dloc[2]*/ ) ); ipocontr->GetIPOTransform().SetEulerAngles( @@ -134,7 +134,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend &(ipocontr->GetIPOTransform().GetPosition()[0]), ipo); ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyPosition(true); + ipocontr->SetIPOChannelActive(OB_LOC_X, true); } @@ -145,7 +145,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend &(ipocontr->GetIPOTransform().GetPosition()[1]), ipo); ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyPosition(true); + ipocontr->SetIPOChannelActive(OB_LOC_Y, true); } ipo = ipoList->GetScalarInterpolator(OB_LOC_Z); @@ -155,7 +155,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend &(ipocontr->GetIPOTransform().GetPosition()[2]), ipo); ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyPosition(true); + ipocontr->SetIPOChannelActive(OB_LOC_Z, true); } // Master the art of cut & paste programming... @@ -167,7 +167,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend &(ipocontr->GetIPOTransform().GetDeltaPosition()[0]), ipo); ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyPosition(true); + ipocontr->SetIPOChannelActive(OB_DLOC_X, true); } ipo = ipoList->GetScalarInterpolator(OB_DLOC_Y); @@ -177,7 +177,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend &(ipocontr->GetIPOTransform().GetDeltaPosition()[1]), ipo); ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyPosition(true); + ipocontr->SetIPOChannelActive(OB_DLOC_Y, true); } ipo = ipoList->GetScalarInterpolator(OB_DLOC_Z); @@ -187,7 +187,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend &(ipocontr->GetIPOTransform().GetDeltaPosition()[2]), ipo); ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyPosition(true); + ipocontr->SetIPOChannelActive(OB_DLOC_Z, true); } // Explore the finesse of reuse and slight modification @@ -199,7 +199,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend &(ipocontr->GetIPOTransform().GetEulerAngles()[0]), ipo); ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyOrientation(true); + ipocontr->SetIPOChannelActive(OB_ROT_X, true); } ipo = ipoList->GetScalarInterpolator(OB_ROT_Y); if (ipo) { @@ -208,7 +208,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend &(ipocontr->GetIPOTransform().GetEulerAngles()[1]), ipo); ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyOrientation(true); + ipocontr->SetIPOChannelActive(OB_ROT_Y, true); } ipo = ipoList->GetScalarInterpolator(OB_ROT_Z); if (ipo) { @@ -217,7 +217,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend &(ipocontr->GetIPOTransform().GetEulerAngles()[2]), ipo); ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyOrientation(true); + ipocontr->SetIPOChannelActive(OB_ROT_Z, true); } // Hmmm, the need for a macro comes to mind... @@ -229,7 +229,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend &(ipocontr->GetIPOTransform().GetDeltaEulerAngles()[0]), ipo); ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyOrientation(true); + ipocontr->SetIPOChannelActive(OB_DROT_X, true); } ipo = ipoList->GetScalarInterpolator(OB_DROT_Y); if (ipo) { @@ -238,7 +238,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend &(ipocontr->GetIPOTransform().GetDeltaEulerAngles()[1]), ipo); ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyOrientation(true); + ipocontr->SetIPOChannelActive(OB_DROT_Y, true); } ipo = ipoList->GetScalarInterpolator(OB_DROT_Z); if (ipo) { @@ -247,7 +247,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend &(ipocontr->GetIPOTransform().GetDeltaEulerAngles()[2]), ipo); ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyOrientation(true); + ipocontr->SetIPOChannelActive(OB_DROT_Z, true); } // Hang on, almost there... @@ -259,7 +259,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend &(ipocontr->GetIPOTransform().GetScaling()[0]), ipo); ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyScaling(true); + ipocontr->SetIPOChannelActive(OB_SIZE_X, true); } ipo = ipoList->GetScalarInterpolator(OB_SIZE_Y); if (ipo) { @@ -268,7 +268,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend &(ipocontr->GetIPOTransform().GetScaling()[1]), ipo); ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyScaling(true); + ipocontr->SetIPOChannelActive(OB_SIZE_Y, true); } ipo = ipoList->GetScalarInterpolator(OB_SIZE_Z); if (ipo) { @@ -277,7 +277,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend &(ipocontr->GetIPOTransform().GetScaling()[2]), ipo); ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyScaling(true); + ipocontr->SetIPOChannelActive(OB_SIZE_Z, true); } // The last few... @@ -289,7 +289,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend &(ipocontr->GetIPOTransform().GetDeltaScaling()[0]), ipo); ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyScaling(true); + ipocontr->SetIPOChannelActive(OB_DSIZE_X, true); } ipo = ipoList->GetScalarInterpolator(OB_DSIZE_Y); if (ipo) { @@ -298,7 +298,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend &(ipocontr->GetIPOTransform().GetDeltaScaling()[1]), ipo); ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyScaling(true); + ipocontr->SetIPOChannelActive(OB_DSIZE_Y, true); } ipo = ipoList->GetScalarInterpolator(OB_DSIZE_Z); if (ipo) { @@ -307,7 +307,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend &(ipocontr->GetIPOTransform().GetDeltaScaling()[2]), ipo); ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyScaling(true); + ipocontr->SetIPOChannelActive(OB_DSIZE_Z, true); } { diff --git a/source/gameengine/Ketsji/KX_IPO_SGController.cpp b/source/gameengine/Ketsji/KX_IPO_SGController.cpp index 920a65be0fb..a4cb9970492 100644 --- a/source/gameengine/Ketsji/KX_IPO_SGController.cpp +++ b/source/gameengine/Ketsji/KX_IPO_SGController.cpp @@ -51,20 +51,21 @@ typedef unsigned long uint_ptr; #include "KX_ScalarInterpolator.h" #include "KX_GameObject.h" #include "KX_IPhysicsController.h" +#include "DNA_ipo_types.h" +#include "BLI_arithb.h" // All objects should start on frame 1! Will we ever need an object to // start on another frame, the 1.0 should change. KX_IpoSGController::KX_IpoSGController() -: m_modify_position(false), - m_modify_orientation(false), - m_modify_scaling(false), - m_ipo_as_force(false), +: m_ipo_as_force(false), m_force_ipo_acts_local(false), m_modified(true), + m_ipo_start_initialized(false), m_ipotime(1.0) { m_game_object = NULL; - + for (int i=0; i < KX_MAX_IPO_CHANNELS; i++) + m_ipo_channels_active[i] = false; } @@ -115,21 +116,60 @@ bool KX_IpoSGController::Update(double currentTime) } SG_Spatial* ob = (SG_Spatial*)m_pObject; - - if (m_modify_position) { - if (m_ipo_as_force) { - - if (m_game_object && ob) { + + //initialization on the first frame of the IPO + if (! m_ipo_start_initialized && currentTime > 0.0) { + m_ipo_start_point = ob->GetLocalPosition(); + m_ipo_start_orient = ob->GetLocalOrientation(); + m_ipo_start_scale = ob->GetLocalScale(); + m_ipo_start_initialized = true; + } + + //modifies position? + if (m_ipo_channels_active[OB_LOC_X] || m_ipo_channels_active[OB_LOC_Y] || m_ipo_channels_active[OB_LOC_Z] || m_ipo_channels_active[OB_DLOC_X] || m_ipo_channels_active[OB_DLOC_Y] || m_ipo_channels_active[OB_DLOC_Z]) + { + if (m_ipo_as_force == true) + { + if (m_game_object && ob) + { m_game_object->GetPhysicsController()->ApplyForce(m_force_ipo_acts_local ? ob->GetWorldOrientation() * m_ipo_xform.GetPosition() : m_ipo_xform.GetPosition(), false); } - - } else { - ob->SetLocalPosition(m_ipo_xform.GetPosition()); + } + else + { + //by default, leave object as it stands + MT_Point3 newPosition = ob->GetLocalPosition(); + //apply separate IPO channels if there is any data in them + //Loc and dLoc act by themselves or are additive + //LocX and dLocX + if (m_ipo_channels_active[OB_LOC_X]) { + newPosition[0] = (m_ipo_channels_active[OB_DLOC_X] ? m_ipo_xform.GetPosition()[0] + m_ipo_xform.GetDeltaPosition()[0] : m_ipo_xform.GetPosition()[0]); + } + else if (m_ipo_channels_active[OB_DLOC_X] && m_ipo_start_initialized) { + newPosition[0] = (m_ipo_start_point[0] + m_ipo_xform.GetDeltaPosition()[0]); + } + //LocY and dLocY + if (m_ipo_channels_active[OB_LOC_Y]) { + newPosition[1] = (m_ipo_channels_active[OB_DLOC_Y] ? m_ipo_xform.GetPosition()[1] + m_ipo_xform.GetDeltaPosition()[1] : m_ipo_xform.GetPosition()[1]); + } + else if (m_ipo_channels_active[OB_DLOC_Y] && m_ipo_start_initialized) { + newPosition[1] = (m_ipo_start_point[1] + m_ipo_xform.GetDeltaPosition()[1]); + } + //LocZ and dLocZ + if (m_ipo_channels_active[OB_LOC_Z]) { + newPosition[2] = (m_ipo_channels_active[OB_DLOC_Z] ? m_ipo_xform.GetPosition()[2] + m_ipo_xform.GetDeltaPosition()[2] : m_ipo_xform.GetPosition()[2]); + } + else if (m_ipo_channels_active[OB_DLOC_Z] && m_ipo_start_initialized) { + newPosition[2] = (m_ipo_start_point[2] + m_ipo_xform.GetDeltaPosition()[2]); + } + + ob->SetLocalPosition(newPosition); } } - if (m_modify_orientation) { + //modifies orientation? + if (m_ipo_channels_active[OB_ROT_X] || m_ipo_channels_active[OB_ROT_Y] || m_ipo_channels_active[OB_ROT_Z] || m_ipo_channels_active[OB_DROT_X] || m_ipo_channels_active[OB_DROT_Y] || m_ipo_channels_active[OB_DROT_Z]) { if (m_ipo_as_force) { if (m_game_object && ob) { @@ -137,13 +177,71 @@ bool KX_IpoSGController::Update(double currentTime) ob->GetWorldOrientation() * m_ipo_xform.GetEulerAngles() : m_ipo_xform.GetEulerAngles(), false); } - } else { - ob->SetLocalOrientation(MT_Matrix3x3(m_ipo_xform.GetEulerAngles())); + double yaw, pitch, roll; //final Euler angles + double tempYaw=0, tempPitch=0, tempRoll=0; //temp holders + ob->GetLocalOrientation().getEuler(yaw, pitch, roll); + + //RotX and dRotX + if (m_ipo_channels_active[OB_ROT_X]) { + yaw = (m_ipo_channels_active[OB_DROT_X] ? (m_ipo_xform.GetEulerAngles()[0] + m_ipo_xform.GetDeltaEulerAngles()[0]) : m_ipo_xform.GetEulerAngles()[0] ); + } + else if (m_ipo_channels_active[OB_DROT_X] && m_ipo_start_initialized) { + m_ipo_start_orient.getEuler(tempYaw, tempPitch, tempRoll); + yaw = tempYaw + m_ipo_xform.GetDeltaEulerAngles()[0]; + } + + //RotY dRotY + if (m_ipo_channels_active[OB_ROT_Y]) { + pitch = (m_ipo_channels_active[OB_DROT_Y] ? (m_ipo_xform.GetEulerAngles()[1] + m_ipo_xform.GetDeltaEulerAngles()[1]) : m_ipo_xform.GetEulerAngles()[1] ); + } + else if (m_ipo_channels_active[OB_DROT_Y] && m_ipo_start_initialized) { + m_ipo_start_orient.getEuler(tempYaw, tempPitch, tempRoll); + pitch = tempPitch + m_ipo_xform.GetDeltaEulerAngles()[1]; + } + + //RotZ and dRotZ + if (m_ipo_channels_active[OB_ROT_Z]) { + roll = (m_ipo_channels_active[OB_DROT_Z] ? (m_ipo_xform.GetEulerAngles()[2] + m_ipo_xform.GetDeltaEulerAngles()[2]) : m_ipo_xform.GetEulerAngles()[2] ); + } + else if (m_ipo_channels_active[OB_DROT_Z] && m_ipo_start_initialized) { + m_ipo_start_orient.getEuler(tempYaw, tempPitch, tempRoll); + roll = tempRoll + m_ipo_xform.GetDeltaEulerAngles()[2]; + } + + ob->SetLocalOrientation(MT_Vector3(yaw, pitch, roll)); } } - if (m_modify_scaling) - ob->SetLocalScale(m_ipo_xform.GetScaling()); + //modifies scale? + if (m_ipo_channels_active[OB_SIZE_X] || m_ipo_channels_active[OB_SIZE_Y] || m_ipo_channels_active[OB_SIZE_Z] || m_ipo_channels_active[OB_DSIZE_X] || m_ipo_channels_active[OB_DSIZE_Y] || m_ipo_channels_active[OB_DSIZE_Z]) { + //default is no scale change + MT_Vector3 newScale = ob->GetLocalScale(); + + if (m_ipo_channels_active[OB_SIZE_X]) { + newScale[0] = (m_ipo_channels_active[OB_DSIZE_X] ? (m_ipo_xform.GetScaling()[0] + m_ipo_xform.GetDeltaScaling()[0]) : m_ipo_xform.GetScaling()[0]); + } + else if (m_ipo_channels_active[OB_DSIZE_X] && m_ipo_start_initialized) { + newScale[0] = (m_ipo_xform.GetDeltaScaling()[0] + m_ipo_start_scale[0]); + } + + //RotY dRotY + if (m_ipo_channels_active[OB_SIZE_Y]) { + newScale[1] = (m_ipo_channels_active[OB_DSIZE_Y] ? (m_ipo_xform.GetScaling()[1] + m_ipo_xform.GetDeltaScaling()[1]): m_ipo_xform.GetScaling()[1]); + } + else if (m_ipo_channels_active[OB_DSIZE_Y] && m_ipo_start_initialized) { + newScale[1] = (m_ipo_xform.GetDeltaScaling()[1] + m_ipo_start_scale[1]); + } + + //RotZ and dRotZ + if (m_ipo_channels_active[OB_SIZE_Z]) { + newScale[2] = (m_ipo_channels_active[OB_DSIZE_Z] ? (m_ipo_xform.GetScaling()[2] + m_ipo_xform.GetDeltaScaling()[2]) : m_ipo_xform.GetScaling()[2]); + } + else if (m_ipo_channels_active[OB_DSIZE_Z] && m_ipo_start_initialized) { + newScale[2] = (m_ipo_xform.GetDeltaScaling()[2] + m_ipo_start_scale[2]); + } + + ob->SetLocalScale(newScale); + } m_modified=false; } diff --git a/source/gameengine/Ketsji/KX_IPO_SGController.h b/source/gameengine/Ketsji/KX_IPO_SGController.h index 3b20f47f5fc..1ebd6900741 100644 --- a/source/gameengine/Ketsji/KX_IPO_SGController.h +++ b/source/gameengine/Ketsji/KX_IPO_SGController.h @@ -38,27 +38,40 @@ #include "KX_IPOTransform.h" #include "KX_IInterpolator.h" +#define KX_MAX_IPO_CHANNELS 19 //note- [0] is not used + class KX_IpoSGController : public SG_Controller { KX_IPOTransform m_ipo_xform; T_InterpolatorList m_interpolators; - /* Why not bools? */ - short m_modify_position : 1; - short m_modify_orientation : 1; - short m_modify_scaling : 1; + + /** Flag for each IPO channel that can be applied to a game object */ + bool m_ipo_channels_active[KX_MAX_IPO_CHANNELS]; /** Interpret the ipo as a force rather than a displacement? */ bool m_ipo_as_force; /** Ipo-as-force acts in local rather than in global coordinates? */ bool m_force_ipo_acts_local; - + /** Were settings altered since the last update? */ bool m_modified; /** Local time of this ipo.*/ double m_ipotime; + /** Location of the object when the IPO is first fired (for local transformations) */ + class MT_Point3 m_ipo_start_point; + + /** Orientation of the object when the IPO is first fired (for local transformations) */ + class MT_Matrix3x3 m_ipo_start_orient; + + /** Scale of the object when the IPO is first fired (for local transformations) */ + class MT_Vector3 m_ipo_start_scale; + + /** if IPO initial position has been set for local normal IPO */ + bool m_ipo_start_initialized; + /** A reference to the original game object. */ class KX_GameObject* m_game_object; @@ -80,16 +93,12 @@ public: /** Set reference to the corresponding game object. */ void SetGameObject(class KX_GameObject*); - void SetModifyPosition(bool modifypos) { - m_modify_position=modifypos; - } - void SetModifyOrientation(bool modifyorient) { - m_modify_orientation=modifyorient; - } - void SetModifyScaling(bool modifyscale) { - m_modify_scaling=modifyscale; + void SetIPOChannelActive(int index, bool value) { + //indexes found in makesdna\DNA_ipo_types.h + m_ipo_channels_active[index] = value; } + KX_IPOTransform& GetIPOTransform() { return m_ipo_xform; @@ -105,3 +114,4 @@ public: #endif //__IPO_SGCONTROLLER_H + |