BGE: TrackTo actuator: increasing up & track axis options
authorJorge Bernal <jbernalmartinez@gmail.com>
Tue, 15 Jul 2014 00:36:56 +0000 (17:36 -0700)
committerMitchell Stokes <mogurijin@gmail.com>
Tue, 15 Jul 2014 01:30:27 +0000 (18:30 -0700)
This is related to Task T34861 to increase up & track axis options for TrackTo actuator. I've just added it to differential to facilitate an easier review.

With the patch applied you can select X, Y and Z axis for the Up axis, and X, Y, Z, -X, -Y and -Z for the track axis.

Related to the implementation I have used the algorithm from Trackto constrain placed in constrain.c but adapted to be used with MOTO library.

The wiki docs are here (http://wiki.blender.org/index.php/User:Lordloki/Doc:2.6/Manual/Game_Engine/Logic/Actuators/Edit_Object#Trackto_Actuator).

Test file is here: {F97623}

I have also uploaded 2 screenshots showing the UI modifications to the TrackTo actuator:

{F91992} {F91990}

Reviewers: moguri, dfelinto

Reviewed By: moguri

CC: Genome36
Differential Revision: https://developer.blender.org/D565

16 files changed:
doc/python_api/rst/bge.logic.rst
doc/python_api/rst/bge_types/bge.types.KX_TrackToActuator.rst
intern/moto/include/MT_Matrix3x3.h
intern/moto/include/MT_Vector3.h
intern/moto/include/MT_Vector3.inl
release/scripts/startup/bl_ui/properties_object.py
source/blender/blenkernel/BKE_blender.h
source/blender/blenkernel/intern/sca.c
source/blender/blenloader/intern/versioning_270.c
source/blender/editors/space_logic/logic_window.c
source/blender/makesdna/DNA_actuator_types.h
source/blender/makesrna/intern/rna_actuator.c
source/gameengine/Converter/KX_ConvertActuators.cpp
source/gameengine/Ketsji/KX_PythonInit.cpp
source/gameengine/Ketsji/KX_TrackToActuator.cpp
source/gameengine/Ketsji/KX_TrackToActuator.h

index 4e0d317e4bf4a808fffc31250e9353fe8fd8fa8c..d901a4e420713b66dae484e8b520dc1515297c58 100644 (file)
@@ -868,6 +868,23 @@ See :class:`bge.types.KX_SteeringActuator.behavior`
 
    :value: 3
 
+.. _logic-trackto-actuator:
+
+-----------------
+TrackTo Actuator
+-----------------
+
+See :class:`bge.types.KX_TrackToActuator`
+
+.. data:: KX_TRACK_UPAXIS_POS_X
+.. data:: KX_TRACK_UPAXIS_POS_Y
+.. data:: KX_TRACK_UPAXIS_POS_Z
+.. data:: KX_TRACK_TRAXIS_POS_X
+.. data:: KX_TRACK_TRAXIS_POS_Y
+.. data:: KX_TRACK_TRAXIS_POS_Z
+.. data:: KX_TRACK_TRAXIS_NEG_X
+.. data:: KX_TRACK_TRAXIS_NEG_Y
+.. data:: KX_TRACK_TRAXIS_NEG_Z
 
 =======
 Various
index 070243c6a052e250355ee7f936ac8ea18c44bf1a..5b5c5d0c0db65d80e3930b5d768c01aee5536472 100644 (file)
@@ -37,3 +37,25 @@ base class --- :class:`SCA_IActuator`
 
       :type: boolean
 
+   .. attribute:: upAxis
+
+      The axis that points upward.
+
+      :type: integer from 0 to 2
+
+      * KX_TRACK_UPAXIS_POS_X
+      * KX_TRACK_UPAXIS_POS_Y
+      * KX_TRACK_UPAXIS_POS_Z
+
+   .. attribute:: trackAxis
+
+      The axis that points to the target object.
+
+      :type: integer from 0 to 5
+
+      * KX_TRACK_TRAXIS_POS_X
+      * KX_TRACK_TRAXIS_POS_Y
+      * KX_TRACK_TRAXIS_POS_Z
+      * KX_TRACK_TRAXIS_NEG_X
+      * KX_TRACK_TRAXIS_NEG_Y
+      * KX_TRACK_TRAXIS_NEG_Z
index 6d709fae662d6234de51359aac23f02d092d9892..17dd53352177ea46b638f2a669a6a4f553443201 100644 (file)
@@ -84,11 +84,18 @@ public:
        MT_Vector3 getColumn(int i) const {
                return MT_Vector3(m_el[0][i], m_el[1][i], m_el[2][i]);
        }
+
        void setColumn(int i, const MT_Vector3& v) {
                m_el[0][i] = v[0];
                m_el[1][i] = v[1];
                m_el[2][i] = v[2];
        }
+
+       void setRow(int i, const MT_Vector3& v) {
+               m_el[i][0] = v[0];
+               m_el[i][1] = v[1];
+               m_el[i][2] = v[2];
+       }
     
     void setValue(const float *m) {
         m_el[0][0] = *m++; m_el[1][0] = *m++; m_el[2][0] = *m++; m++;
index 83c53a19d6610c6a67faee3d0dfb9bad9b641758..b06f345bdaf6aef1addca80d9831d5ebb588e750 100644 (file)
@@ -75,7 +75,7 @@ public:
     void        normalize();
     MT_Vector3  normalized() const;
        MT_Vector3  safe_normalized() const;
-       
+       MT_Vector3  safe_normalized_vec(MT_Vector3 vecnormalized) const;
 
     void        scale(MT_Scalar x, MT_Scalar y, MT_Scalar z); 
     MT_Vector3  scaled(MT_Scalar x, MT_Scalar y, MT_Scalar z) const; 
index b17ef47c709d395bdf92437d4a0992ede7b5fc52..09c92c6ab54fb2b1a9ddf8382ead15bf788e0ca7 100644 (file)
@@ -77,6 +77,13 @@ GEN_INLINE MT_Vector3 MT_Vector3::safe_normalized() const {
         *this / len; 
 }
 
+GEN_INLINE MT_Vector3 MT_Vector3::safe_normalized_vec(MT_Vector3 vecnormalized) const {
+       MT_Scalar len = length();
+       return MT_fuzzyZero(len) ?
+        vecnormalized :
+        *this / len;
+}
+
 GEN_INLINE void MT_Vector3::scale(MT_Scalar xx, MT_Scalar yy, MT_Scalar zz) {
     m_co[0] *= xx; m_co[1] *= yy; m_co[2] *= zz;
 }
index 6b7e7b47281e56e5a9471cae94b9853acdad3915..9d958892c73e388efc4a9328e7acf5321f85d7b9 100644 (file)
@@ -301,10 +301,11 @@ class OBJECT_PT_relations_extras(ObjectButtonsPanel, Panel):
 
         split = layout.split()
 
-        col = split.column()
-        col.label(text="Tracking Axes:")
-        col.prop(ob, "track_axis", text="Axis")
-        col.prop(ob, "up_axis", text="Up Axis")
+        if context.scene.render.engine != 'BLENDER_GAME':
+            col = split.column()
+            col.label(text="Tracking Axes:")
+            col.prop(ob, "track_axis", text="Axis")
+            col.prop(ob, "up_axis", text="Up Axis")
 
         col = split.column()
         col.prop(ob, "use_slow_parent")
index 0af45a147a42bc32315a3e7578d9109345d6ac97..19fa60f5827c7db6a390c70783a3a5664e31d589 100644 (file)
@@ -42,7 +42,7 @@ extern "C" {
  * and keep comment above the defines.
  * Use STRINGIFY() rather than defining with quotes */
 #define BLENDER_VERSION         271
-#define BLENDER_SUBVERSION      1
+#define BLENDER_SUBVERSION      2
 /* 262 was the last editmesh release but it has compatibility code for bmesh data */
 #define BLENDER_MINVERSION      270
 #define BLENDER_MINSUBVERSION   5
index 1310162483e3191e1cffa5466e01f969b8ca02bd..4be7534413362842957979fb96096223fe6911f6 100644 (file)
@@ -392,6 +392,7 @@ void init_actuator(bActuator *act)
        bSteeringActuator *sta;
        bArmatureActuator *arma;
        bMouseActuator *ma;
+       bEditObjectActuator *eoa;
        
        if (act->data) MEM_freeN(act->data);
        act->data= NULL;
@@ -430,6 +431,9 @@ void init_actuator(bActuator *act)
                break;
        case ACT_EDIT_OBJECT:
                act->data= MEM_callocN(sizeof(bEditObjectActuator), "editobact");
+               eoa = act->data;
+               eoa->upflag= ACT_TRACK_UP_Z;
+               eoa->trackflag= ACT_TRACK_TRAXIS_Y;
                break;
        case ACT_CONSTRAINT:
                act->data= MEM_callocN(sizeof(bConstraintActuator), "cons act");
index 103f9b76ba7cb19de9d4f5f3335242d5d7a87bde..dde16c8d44f711e866e849f4a2f20445b67d446c 100644 (file)
@@ -42,6 +42,7 @@
 #include "DNA_mesh_types.h"
 #include "DNA_modifier_types.h"
 #include "DNA_linestyle_types.h"
+#include "DNA_actuator_types.h"
 
 #include "DNA_genfile.h"
 
@@ -310,6 +311,29 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
                }
        }
 
+       if (!MAIN_VERSION_ATLEAST(main, 271, 2)) {
+               /* init up & track axis property of trackto actuators */
+               Object *ob;
+
+               for (ob = main->object.first; ob; ob = ob->id.next) {
+                       bActuator *act;
+                       for (act = ob->actuators.first; act; act = act->next) {
+                               if (act->type == ACT_EDIT_OBJECT) {
+                                       bEditObjectActuator *eoact = act->data;
+                                       eoact->trackflag = ob->trackflag;
+                                       /* if trackflag is pointing +-Z axis then upflag should point Y axis.
+                                        * Rest of trackflag cases, upflag should be point z axis */
+                                       if ((ob->trackflag == OB_POSZ) || (ob->trackflag == OB_NEGZ)) {
+                                               eoact->upflag = 1;
+                                       }
+                                       else {
+                                               eoact->upflag = 2;
+                                       }
+                               }
+                       }
+               }
+       }
+
        if (!DNA_struct_elem_find(fd->filesdna, "RenderData", "int", "preview_start_resolution")) {
                Scene *scene;
                for (scene = main->scene.first; scene; scene = scene->id.next) {
index b52d626580099c28d27802a9ef384c1301d38d44..c3a3dda2c477d0c71217473c70aa50d5f4c8a750 100644 (file)
@@ -1720,6 +1720,12 @@ static void draw_actuator_edit_object(uiLayout *layout, PointerRNA *ptr)
                        sub = uiLayoutSplit(split, 0.7f, false);
                        uiItemR(sub, ptr, "time", 0, NULL, ICON_NONE);
                        uiItemR(sub, ptr, "use_3d_tracking", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
+
+                       row = uiLayoutRow(layout, false);
+                       uiItemR(row, ptr, "up_axis", 0, NULL, ICON_NONE);
+
+                       row = uiLayoutRow(layout, false);
+                       uiItemR(row, ptr, "track_axis", 0, NULL, ICON_NONE);
                        break;
                case ACT_EDOB_DYNAMICS:
                        if (ob->type != OB_MESH) {
index 5ab799a75e5f918b2b85bb772968e51fdce0d79f..7698d671117d54bdb37768595b587ae77dbf8251 100644 (file)
@@ -97,6 +97,8 @@ typedef struct bEditObjectActuator {
        float mass;
        short localflag; /* flag for the lin & ang. vel: apply locally   */
        short dyn_operation;
+       short upflag, trackflag; /* flag for up axis and track axis */
+       int pad;
 } bEditObjectActuator;
 
 typedef struct bSceneActuator {
@@ -439,6 +441,19 @@ typedef struct bActuator {
 /* editObjectActuator->flag */
 #define ACT_TRACK_3D                   1
 
+/* editObjectActuator->upflag */
+#define ACT_TRACK_UP_X                 0
+#define ACT_TRACK_UP_Y                 1
+#define ACT_TRACK_UP_Z                 2
+
+/* editObjectActuator->trackflag */
+#define ACT_TRACK_TRAXIS_X                     0
+#define ACT_TRACK_TRAXIS_Y                     1
+#define ACT_TRACK_TRAXIS_Z                     2
+#define ACT_TRACK_TRAXIS_NEGX          3
+#define ACT_TRACK_TRAXIS_NEGY          4
+#define ACT_TRACK_TRAXIS_NEGZ          5
+
 /* editObjectActuator->flag for replace mesh actuator */
 #define ACT_EDOB_REPLACE_MESH_NOGFX            2 /* use for replace mesh actuator */
 #define ACT_EDOB_REPLACE_MESH_PHYS             4
index 62e681d13746abdd68ba381282a70df1d983e193..9d26978d098e606ea6fb3d57f40960e3970e4753 100644 (file)
@@ -1369,6 +1369,23 @@ static void rna_def_edit_object_actuator(BlenderRNA *brna)
                {0, NULL, 0, NULL, NULL}
        };
 
+       static EnumPropertyItem prop_track_axis_items[] = {
+               {ACT_TRACK_TRAXIS_X, "TRACKAXISX", 0, "X axis", ""},
+               {ACT_TRACK_TRAXIS_Y, "TRACKAXISY", 0, "Y axis", ""},
+               {ACT_TRACK_TRAXIS_Z, "TRACKAXISZ", 0, "Z axis", ""},
+               {ACT_TRACK_TRAXIS_NEGX, "TRACKAXISNEGX", 0, "-X axis", ""},
+               {ACT_TRACK_TRAXIS_NEGY, "TRACKAXISNEGY", 0, "-Y axis", ""},
+               {ACT_TRACK_TRAXIS_NEGZ, "TRACKAXISNEGZ", 0, "-Z axis", ""},
+               {0, NULL, 0, NULL, NULL}
+       };
+
+       static EnumPropertyItem prop_up_axis_items[] = {
+               {ACT_TRACK_UP_X, "UPAXISX", 0, "X axis", ""},
+               {ACT_TRACK_UP_Y, "UPAXISY", 0, "Y axis", ""},
+               {ACT_TRACK_UP_Z, "UPAXISZ", 0, "Z axis", ""},
+               {0, NULL, 0, NULL, NULL}
+       };
+
        srna = RNA_def_struct(brna, "EditObjectActuator", "Actuator");
        RNA_def_struct_ui_text(srna, "Edit Object Actuator", "Actuator used to edit objects");
        RNA_def_struct_sdna_from(srna, "bEditObjectActuator", "data");
@@ -1385,6 +1402,18 @@ static void rna_def_edit_object_actuator(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Dynamic Operation", "");
        RNA_def_property_update(prop, NC_LOGIC, NULL);
 
+       prop = RNA_def_property(srna, "up_axis", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "upflag");
+       RNA_def_property_enum_items(prop, prop_up_axis_items);
+       RNA_def_property_ui_text(prop, "Up Axis", "The axis that points upward");
+       RNA_def_property_update(prop, NC_LOGIC, NULL);
+
+       prop = RNA_def_property(srna, "track_axis", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "trackflag");
+       RNA_def_property_enum_items(prop, prop_track_axis_items);
+       RNA_def_property_ui_text(prop, "Track Axis", "The axis that points to the target object");
+       RNA_def_property_update(prop, NC_LOGIC, NULL);
+
        prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
        RNA_def_property_struct_type(prop, "Object");
        RNA_def_property_pointer_sdna(prop, NULL, "ob");
index 45fc11b97d2f5769073922d1a851f3672250f1c5..f6ed3366625fbb24264e3e7d6e49a76cafdf7a1c 100644 (file)
@@ -538,8 +538,8 @@ void BL_ConvertActuators(const char* maggiename,
                                                            originalval,
                                                            editobact->time,
                                                            editobact->flag,
-                                                           blenderobject->trackflag,
-                                                           blenderobject->upflag);
+                                                           editobact->trackflag,
+                                                           editobact->upflag);
                                                baseact = tmptrackact;
                                                break;
                                        }
index fa52fab06fc8aa924ff1f61d2a13a2c8c21e53fe..bbf9f427a6c29e3ab830d050cfc53ceed8bd6d40 100644 (file)
@@ -88,6 +88,7 @@ extern "C" {
 #include "KX_SteeringActuator.h"
 #include "KX_NavMeshObject.h"
 #include "KX_MouseActuator.h"
+#include "KX_TrackToActuator.h"
 
 #include "SCA_IInputDevice.h"
 #include "SCA_PropertySensor.h"
@@ -1754,6 +1755,17 @@ PyObject *initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack
        KX_MACRO_addTypesToDict(d, KX_RAY_AXIS_NEG_Y, KX_RaySensor::KX_RAY_AXIS_NEG_Y);
        KX_MACRO_addTypesToDict(d, KX_RAY_AXIS_NEG_Z, KX_RaySensor::KX_RAY_AXIS_NEG_Z);
 
+       /* TrackTo Actuator */
+       KX_MACRO_addTypesToDict(d, KX_TRACK_UPAXIS_POS_X, KX_TrackToActuator::KX_TRACK_UPAXIS_POS_X);
+       KX_MACRO_addTypesToDict(d, KX_TRACK_UPAXIS_POS_Y, KX_TrackToActuator::KX_TRACK_UPAXIS_POS_Y);
+       KX_MACRO_addTypesToDict(d, KX_TRACK_UPAXIS_POS_Z, KX_TrackToActuator::KX_TRACK_UPAXIS_POS_Z);
+       KX_MACRO_addTypesToDict(d, KX_TRACK_TRAXIS_POS_X, KX_TrackToActuator::KX_TRACK_TRAXIS_POS_X);
+       KX_MACRO_addTypesToDict(d, KX_TRACK_TRAXIS_POS_Y, KX_TrackToActuator::KX_TRACK_TRAXIS_POS_Y);
+       KX_MACRO_addTypesToDict(d, KX_TRACK_TRAXIS_POS_Z, KX_TrackToActuator::KX_TRACK_TRAXIS_POS_Z);
+       KX_MACRO_addTypesToDict(d, KX_TRACK_TRAXIS_NEG_X, KX_TrackToActuator::KX_TRACK_TRAXIS_NEG_X);
+       KX_MACRO_addTypesToDict(d, KX_TRACK_TRAXIS_NEG_Y, KX_TrackToActuator::KX_TRACK_TRAXIS_NEG_Y);
+       KX_MACRO_addTypesToDict(d, KX_TRACK_TRAXIS_NEG_Z, KX_TrackToActuator::KX_TRACK_TRAXIS_NEG_Z);
+
        /* Dynamic actuator */
        KX_MACRO_addTypesToDict(d, KX_DYN_RESTORE_DYNAMICS, KX_SCA_DynamicActuator::KX_DYN_RESTORE_DYNAMICS);
        KX_MACRO_addTypesToDict(d, KX_DYN_DISABLE_DYNAMICS, KX_SCA_DynamicActuator::KX_DYN_DISABLE_DYNAMICS);
index 90b7850946b96afee7fb2d5dad4324ea767bea60..75baf5fac1d6957f0ab630fee810dc93172180ef 100644 (file)
@@ -31,8 +31,7 @@
  * Replace the mesh for this actuator's parent
  */
 
-/* todo: not all trackflags / upflags are implemented/tested !
- * m_trackflag is used to determine the forward tracking direction
+/* m_trackflag is used to determine the forward tracking direction
  * m_upflag for the up direction
  * normal situation is +y for forward, +z for up */
 
@@ -177,7 +176,77 @@ static MT_Matrix3x3 matrix3x3_interpol(MT_Matrix3x3 oldmat, MT_Matrix3x3 mat, in
        return EulToMat3(eul);
 }
 
+static float basis_cross(int n, int m)
+{
+       switch (n - m) {
+               case 1:
+               case -2:
+                       return 1.0f;
+
+               case -1:
+               case 2:
+                       return -1.0f;
+
+               default:
+                       return 0.0f;
+       }
+}
 
+/* vectomat function obtained from constrain.c and modified to work with MOTO library */
+static MT_Matrix3x3 vectomat(MT_Vector3 vec, short axis, short upflag, short threedimup)
+{
+       MT_Matrix3x3 mat;
+       MT_Vector3 y(MT_Scalar(0.0), MT_Scalar(1.0), MT_Scalar(0.0));
+       MT_Vector3 z(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(1.0)); /* world Z axis is the global up axis */
+       MT_Vector3 proj;
+       MT_Vector3 right;
+       MT_Scalar mul;
+       int right_index;
+
+       /* Normalized Vec vector*/
+       vec = vec.safe_normalized_vec(z);
+
+       /* if 2D doesn't move the up vector */
+       if (!threedimup){
+               vec.setValue(MT_Scalar(vec[0]), MT_Scalar(vec[1]), MT_Scalar(0.0));
+               vec = (vec - z.dot(vec)*z).safe_normalized_vec(z);
+       }
+
+       if (axis > 2)
+               axis -= 3;
+       else
+               vec = -vec;
+
+       /* project the up vector onto the plane specified by vec */
+       /* first z onto vec... */
+       mul = z.dot(vec) / vec.dot(vec);
+       proj = vec * mul;
+       /* then onto the plane */
+       proj = z - proj;
+       /* proj specifies the transformation of the up axis */
+       proj = proj.safe_normalized_vec(y);
+
+       /* Normalized cross product of vec and proj specifies transformation of the right axis */
+       right = proj.cross(vec);
+       right.normalize();
+
+       if (axis != upflag) {
+               right_index = 3 - axis - upflag;
+
+               /* account for up direction, track direction */
+               right = right * basis_cross(axis, upflag);
+               mat.setRow(right_index, right);
+               mat.setRow(upflag, proj);
+               mat.setRow(axis, vec);
+               mat = mat.inverse();
+       }
+       /* identity matrix - don't do anything if the two axes are the same */
+       else {
+               mat.setIdentity();
+       }
+
+       return mat;
+}
 
 KX_TrackToActuator::~KX_TrackToActuator()
 {
@@ -247,153 +316,24 @@ bool KX_TrackToActuator::Update(double curtime, bool frame)
        else if (m_object)
        {
                KX_GameObject* curobj = (KX_GameObject*) GetParent();
-               MT_Vector3 dir = ((KX_GameObject*)m_object)->NodeGetWorldPosition() - curobj->NodeGetWorldPosition();
-               if (dir.length2())
-                       dir.normalize();
-               MT_Vector3 up(0,0,1);
-               
-               
-#ifdef DSADSA
-               switch (m_upflag)
-               {
-               case 0:
-                       {
-                               up.setValue(1.0,0,0);
-                               break;
-                       } 
-               case 1:
-                       {
-                               up.setValue(0,1.0,0);
-                               break;
-                       }
-               case 2:
-               default:
-                       {
-                               up.setValue(0,0,1.0);
-                       }
-               }
-#endif 
-               if (m_allow3D)
-               {
-                       up = (up - up.dot(dir) * dir).safe_normalized();
-                       
-               }
-               else
-               {
-                       dir = (dir - up.dot(dir)*up).safe_normalized();
-               }
-               
-               MT_Vector3 left;
+               MT_Vector3 dir = curobj->NodeGetWorldPosition() - ((KX_GameObject*)m_object)->NodeGetWorldPosition();
                MT_Matrix3x3 mat;
-               
-               switch (m_trackflag)
-               {
-               case 0: // TRACK X
-                       {
-                               // (1.0 , 0.0 , 0.0 ) x direction is forward, z (0.0 , 0.0 , 1.0 ) up
-                               left  = dir.safe_normalized();
-                               dir = up.cross(left).safe_normalized();
-                               mat.setValue (
-                                       left[0], dir[0],up[0], 
-                                       left[1], dir[1],up[1],
-                                       left[2], dir[2],up[2]
-                                       );
-                               
-                               break;
-                       };
-               case 1: // TRACK Y
-                       {
-                               // (0.0 , 1.0 , 0.0 ) y direction is forward, z (0.0 , 0.0 , 1.0 ) up
-                               left  = (dir.cross(up)).safe_normalized();
-                               mat.setValue (
-                                       left[0], dir[0],up[0], 
-                                       left[1], dir[1],up[1],
-                                       left[2], dir[2],up[2]
-                                       );
-                               
-                               break;
-                       }
-                       
-               case 2: // track Z
-                       {
-                               left = up.safe_normalized();
-                               up = dir.safe_normalized();
-                               dir = left;
-                               left  = (dir.cross(up)).safe_normalized();
-                               mat.setValue (
-                                       left[0], dir[0],up[0], 
-                                       left[1], dir[1],up[1],
-                                       left[2], dir[2],up[2]
-                                       );
-                               break;
-                       }
-                       
-               case 3: // TRACK -X
-                       {
-                               // (1.0 , 0.0 , 0.0 ) x direction is forward, z (0.0 , 0.0 , 1.0 ) up
-                               left  = -dir.safe_normalized();
-                               dir = up.cross(left).safe_normalized();
-                               mat.setValue (
-                                       left[0], dir[0],up[0], 
-                                       left[1], dir[1],up[1],
-                                       left[2], dir[2],up[2]
-                                       );
-                               
-                               break;
-                       };
-               case 4: // TRACK -Y
-                       {
-                               // (0.0 , -1.0 , 0.0 ) -y direction is forward, z (0.0 , 0.0 , 1.0 ) up
-                               left  = (-dir.cross(up)).safe_normalized();
-                               mat.setValue (
-                                       left[0], -dir[0],up[0], 
-                                       left[1], -dir[1],up[1],
-                                       left[2], -dir[2],up[2]
-                                       );
-                               break;
-                       }
-               case 5: // track -Z
-                       {
-                               left = up.safe_normalized();
-                               up = -dir.safe_normalized();
-                               dir = left;
-                               left  = (dir.cross(up)).safe_normalized();
-                               mat.setValue (
-                                       left[0], dir[0],up[0], 
-                                       left[1], dir[1],up[1],
-                                       left[2], dir[2],up[2]
-                                       );
-                               
-                               break;
-                       }
-                       
-               default:
-                       {
-                               // (1.0 , 0.0 , 0.0 ) -x direction is forward, z (0.0 , 0.0 , 1.0 ) up
-                               left  = -dir.safe_normalized();
-                               dir = up.cross(left).safe_normalized();
-                               mat.setValue (
-                                       left[0], dir[0],up[0], 
-                                       left[1], dir[1],up[1],
-                                       left[2], dir[2],up[2]
-                                       );
-                       }
-               }
-               
                MT_Matrix3x3 oldmat;
-               oldmat= curobj->NodeGetWorldOrientation();
+
+               mat = vectomat(dir, m_trackflag, m_upflag, m_allow3D);
+               oldmat = curobj->NodeGetWorldOrientation();
                
                /* erwin should rewrite this! */
-               mat= matrix3x3_interpol(oldmat, mat, m_time);
+               mat = matrix3x3_interpol(oldmat, mat, m_time);
                
-
-               if (m_parentobj) { // check if the model is parented and calculate the child transform
+               /* check if the model is parented and calculate the child transform */
+               if (m_parentobj) {
                                
                        MT_Point3 localpos;
                        localpos = curobj->GetSGNode()->GetLocalPosition();
                        // Get the inverse of the parent matrix
                        MT_Matrix3x3 parentmatinv;
-                       parentmatinv = m_parentobj->NodeGetWorldOrientation ().inverse ();
+                       parentmatinv = m_parentobj->NodeGetWorldOrientation().inverse();
                        // transform the local coordinate system into the parents system
                        mat = parentmatinv * mat;
                        // append the initial parent local rotation matrix
@@ -404,8 +344,7 @@ bool KX_TrackToActuator::Update(double curtime, bool frame)
                        curobj->NodeSetLocalPosition(localpos);
                        //curobj->UpdateTransform();
                }
-               else
-               {
+               else {
                        curobj->NodeSetLocalOrientation(mat);
                }
 
@@ -451,6 +390,8 @@ PyMethodDef KX_TrackToActuator::Methods[] = {
 PyAttributeDef KX_TrackToActuator::Attributes[] = {
        KX_PYATTRIBUTE_INT_RW("time",0,1000,true,KX_TrackToActuator,m_time),
        KX_PYATTRIBUTE_BOOL_RW("use3D",KX_TrackToActuator,m_allow3D),
+       KX_PYATTRIBUTE_INT_RW("upAxis", 0, 2, true, KX_TrackToActuator,m_upflag),
+       KX_PYATTRIBUTE_INT_RW("trackAxis", 0, 5, true, KX_TrackToActuator,m_trackflag),
        KX_PYATTRIBUTE_RW_FUNCTION("object", KX_TrackToActuator, pyattr_get_object, pyattr_set_object),
 
        { NULL }        //Sentinel
index 4df240a00631c399496c5aeb7535fb33ffc47efd..124014eede22a08f2a316d239b1c266f19221ed9 100644 (file)
@@ -68,6 +68,21 @@ class KX_TrackToActuator : public SCA_IActuator
        virtual void Relink(CTR_Map<CTR_HashedPtr, void*> *obj_map);
        virtual bool Update(double curtime, bool frame);
 
+       //Python Interface
+       enum UpAxis {
+               KX_TRACK_UPAXIS_POS_X = 0,
+               KX_TRACK_UPAXIS_POS_Y,
+               KX_TRACK_UPAXIS_POS_Z
+       };
+       enum TrackAxis {
+               KX_TRACK_TRAXIS_POS_X = 0,
+               KX_TRACK_TRAXIS_POS_Y,
+               KX_TRACK_TRAXIS_POS_Z,
+               KX_TRACK_TRAXIS_NEG_X,
+               KX_TRACK_TRAXIS_NEG_Y,
+               KX_TRACK_TRAXIS_NEG_Z
+       };
+
 #ifdef WITH_PYTHON
 
        /* Python part */