BGE patch: local/global flag to distance contraint actuator.
authorBenoit Bolsee <benoit.bolsee@online.be>
Fri, 26 Sep 2008 18:03:14 +0000 (18:03 +0000)
committerBenoit Bolsee <benoit.bolsee@online.be>
Fri, 26 Sep 2008 18:03:14 +0000 (18:03 +0000)
Previously the distance constraint actuator was always working
in local axis. The local flag allows to cast the ray along a
world axis (when the flag is not selected).
The N flag works differently in this case: only the object
orientation is changed to be parallel to the normal at the hit
point.

The linear velocity is now changed so that the speed along the
ray axis is null. This eliminates the need to compensate the
gravity when casting along the Z axis.

source/blender/blenkernel/BKE_blender.h
source/blender/blenloader/intern/readfile.c
source/blender/makesdna/DNA_actuator_types.h
source/blender/src/buttons_logic.c
source/gameengine/Ketsji/KX_ConstraintActuator.cpp
source/gameengine/Ketsji/KX_ConstraintActuator.h
source/gameengine/Physics/Bullet/CcdPhysicsController.cpp

index f123c14fddf10ceb4c9281edad4dabdeaef27e5a..14270d3a7c93906e932f01fbd6528c0f7896a2fe 100644 (file)
@@ -41,7 +41,7 @@ struct ListBase;
 struct MemFile;
 
 #define BLENDER_VERSION                        247
-#define BLENDER_SUBVERSION             6
+#define BLENDER_SUBVERSION             7
 
 #define BLENDER_MINVERSION             245
 #define BLENDER_MINSUBVERSION  15
index 66905c6f24025081030a7ec6c392f25f26bab399..85e45e87994daa790ec5b30cedd7da882b9ad523 100644 (file)
@@ -7883,6 +7883,23 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                        }
                }
        }
+       /* direction constraint actuators were always local in previous version */
+       if (main->versionfile < 247 || (main->versionfile == 247 && main->subversionfile < 7)) {
+               bActuator *act;
+               Object *ob;
+               
+               for(ob = main->object.first; ob; ob= ob->id.next) {
+                       for(act= ob->actuators.first; act; act= act->next) {
+                               if (act->type == ACT_CONSTRAINT) {
+                                       bConstraintActuator *coa = act->data;
+                                       if (coa->type == ACT_CONST_TYPE_DIST) {
+                                               coa->flag |= ACT_CONST_LOCAL;
+                                       }
+                               }
+                       }
+               }
+       }
+
        /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
        /* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */
 
index 750bdf2cfff1b5558b27405261d4db0d35eba001..2487216f764a45c6bbdb755e2e9fa1dee8cd62b7 100644 (file)
@@ -368,6 +368,8 @@ typedef struct FreeCamera {
 #define ACT_CONST_MATERIAL     128
 #define ACT_CONST_PERMANENT 256
 #define ACT_CONST_DISTANCE     512
+#define ACT_CONST_LOCAL     1024
+
 /* constraint mode */
 #define ACT_CONST_DIRPX                1
 #define ACT_CONST_DIRPY                2
index a6f4acb8c6866cdde6d4a842e5aa6e385b3c0e2b..e36e51d9686014e5e704ef7554a40e2dd131060b 100644 (file)
@@ -2162,6 +2162,8 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh
                        uiDefButS(block, NUM,           0, "damp",      xco+10, yco-45, 70, 19, &coa->damp, 0.0, 100.0, 0, 0, "Damping factor: time constant (in frame) of low pass filter");
                        uiDefBut(block, LABEL,                  0, "Range",     xco+80, yco-45, (width-115)/2, 19, NULL, 0.0, 0.0, 0, 0, "Set the maximum length of ray");
                        uiDefButBitS(block, TOG, ACT_CONST_DISTANCE, B_REDR, "Dist",    xco+80+(width-115)/2, yco-45, (width-115)/2, 19, &coa->flag, 0.0, 0.0, 0, 0, "Force distance of object to point of impact of ray");
+                       uiDefButBitS(block, TOG, ACT_CONST_LOCAL, 0, "L", xco+80+(width-115), yco-45, 25, 19,
+                                        &coa->flag, 0.0, 0.0, 0, 0, "Set ray along object's axis or global axis");
 
                        if(coa->mode & (ACT_CONST_DIRPX|ACT_CONST_DIRNX)) fp= coa->minloc;
                        else if(coa->mode & (ACT_CONST_DIRPY|ACT_CONST_DIRNY)) fp= coa->minloc+1;
@@ -2171,7 +2173,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh
                        if (coa->flag & ACT_CONST_DISTANCE)
                                uiDefButF(block, NUM, 0, "",            xco+80+(width-115)/2, yco-65, (width-115)/2, 19, fp, -2000.0, 2000.0, 10, 0, "Keep this distance to target");
                        uiDefButBitS(block, TOG, ACT_CONST_NORMAL, 0, "N", xco+80+(width-115), yco-65, 25, 19,
-                                        &coa->flag, 0.0, 0.0, 0, 0, "Set object axis along the normal at hit position");
+                                        &coa->flag, 0.0, 0.0, 0, 0, "Set object axis along (local axis) or parallel (global axis) to the normal at hit position");
                        uiDefButBitS(block, TOG, ACT_CONST_MATERIAL, B_REDR, "M/P", xco+10, yco-84, 40, 19,
                                         &coa->flag, 0.0, 0.0, 0, 0, "Detect material instead of property");
                        if (coa->flag & ACT_CONST_MATERIAL)
index 11af4b9324ba98553c85172f934d6f5b719736b7..49534ccbd4a4a37e9fef236889d4c5c20f5c4cf3 100644 (file)
@@ -172,13 +172,15 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame)
                KX_GameObject  *obj = (KX_GameObject*) GetParent();
                MT_Point3    position = obj->NodeGetWorldPosition();
                MT_Point3    newposition;
-               MT_Vector3   direction, refDirection;
+               MT_Vector3   normal, direction, refDirection;
                MT_Matrix3x3 rotation = obj->NodeGetWorldOrientation();
                MT_Scalar    filter, newdistance, cosangle;
                int axis, sign;
 
                if (m_posDampTime) {
                        filter = m_posDampTime/(1.0+m_posDampTime);
+               } else {
+                       filter = 0.0;
                }
                switch (m_locrot) {
                case KX_ACT_CONSTRAINT_ORIX:
@@ -238,12 +240,8 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame)
                        } else {
                                refDirection = m_refDirection;
                        }
-                       if (m_posDampTime) {
-                               // apply damping on the direction
-                               direction = filter*direction + (1.0-filter)*refDirection;
-                       } else {
-                               direction = refDirection;
-                       }
+                       // apply damping on the direction
+                       direction = filter*direction + (1.0-filter)*refDirection;
                        obj->AlignAxisToVect(direction, axis);
                        result = true;
                        goto CHECK_TIME;
@@ -255,49 +253,74 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame)
                case KX_ACT_CONSTRAINT_DIRNZ:
                        switch (m_locrot) {
                        case KX_ACT_CONSTRAINT_DIRPX:
-                               direction[0] = rotation[0][0];
-                               direction[1] = rotation[1][0];
-                               direction[2] = rotation[2][0];
+                               normal[0] = rotation[0][0];
+                               normal[1] = rotation[1][0];
+                               normal[2] = rotation[2][0];
                                axis = 0;               // axis according to KX_GameObject::AlignAxisToVect()
-                               sign = 1;               // X axis will be anti parrallel to normal
+                               sign = 0;               // X axis will be parrallel to direction of ray
                                break;
                        case KX_ACT_CONSTRAINT_DIRPY:
-                               direction[0] = rotation[0][1];
-                               direction[1] = rotation[1][1];
-                               direction[2] = rotation[2][1];
+                               normal[0] = rotation[0][1];
+                               normal[1] = rotation[1][1];
+                               normal[2] = rotation[2][1];
                                axis = 1;
-                               sign = 1;
+                               sign = 0;
                                break;
                        case KX_ACT_CONSTRAINT_DIRPZ:
-                               direction[0] = rotation[0][2];
-                               direction[1] = rotation[1][2];
-                               direction[2] = rotation[2][2];
+                               normal[0] = rotation[0][2];
+                               normal[1] = rotation[1][2];
+                               normal[2] = rotation[2][2];
                                axis = 2;
-                               sign = 1;
+                               sign = 0;
                                break;
                        case KX_ACT_CONSTRAINT_DIRNX:
-                               direction[0] = -rotation[0][0];
-                               direction[1] = -rotation[1][0];
-                               direction[2] = -rotation[2][0];
+                               normal[0] = -rotation[0][0];
+                               normal[1] = -rotation[1][0];
+                               normal[2] = -rotation[2][0];
                                axis = 0;
-                               sign = 0;
+                               sign = 1;
                                break;
                        case KX_ACT_CONSTRAINT_DIRNY:
-                               direction[0] = -rotation[0][1];
-                               direction[1] = -rotation[1][1];
-                               direction[2] = -rotation[2][1];
+                               normal[0] = -rotation[0][1];
+                               normal[1] = -rotation[1][1];
+                               normal[2] = -rotation[2][1];
                                axis = 1;
-                               sign = 0;
+                               sign = 1;
                                break;
                        case KX_ACT_CONSTRAINT_DIRNZ:
-                               direction[0] = -rotation[0][2];
-                               direction[1] = -rotation[1][2];
-                               direction[2] = -rotation[2][2];
+                               normal[0] = -rotation[0][2];
+                               normal[1] = -rotation[1][2];
+                               normal[2] = -rotation[2][2];
                                axis = 2;
-                               sign = 0;
+                               sign = 1;
                                break;
                        }
-                       direction.normalize();
+                       normal.normalize();
+                       if (m_option & KX_ACT_CONSTRAINT_LOCAL) {
+                               // direction of the ray is along the local axis
+                               direction = normal;
+                       } else {
+                               switch (m_locrot) {
+                               case KX_ACT_CONSTRAINT_DIRPX:
+                                       direction = MT_Vector3(1.0,0.0,0.0);
+                                       break;
+                               case KX_ACT_CONSTRAINT_DIRPY:
+                                       direction = MT_Vector3(0.0,1.0,0.0);
+                                       break;
+                               case KX_ACT_CONSTRAINT_DIRPZ:
+                                       direction = MT_Vector3(0.0,0.0,1.0);
+                                       break;
+                               case KX_ACT_CONSTRAINT_DIRNX:
+                                       direction = MT_Vector3(-1.0,0.0,0.0);
+                                       break;
+                               case KX_ACT_CONSTRAINT_DIRNY:
+                                       direction = MT_Vector3(0.0,-1.0,0.0);
+                                       break;
+                               case KX_ACT_CONSTRAINT_DIRNZ:
+                                       direction = MT_Vector3(0.0,0.0,-1.0);
+                                       break;
+                               }
+                       }
                        {
                                MT_Point3 topoint = position + (m_maximumBound) * direction;
                                PHY_IPhysicsEnvironment* pe = obj->GetPhysicsEnvironment();
@@ -326,18 +349,19 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame)
                                                goto CHECK_TIME;
                                        }
                                        if (m_option & KX_ACT_CONSTRAINT_NORMAL) {
-                                               // the new orientation must be so that the axis is parallel to normal
-                                               if (sign)
-                                                       newnormal = -newnormal;
+                                               MT_Scalar rotFilter;
                                                // apply damping on the direction
                                                if (m_rotDampTime) {
-                                                       MT_Scalar rotFilter = 1.0/(1.0+m_rotDampTime);
-                                                       newnormal = (-m_rotDampTime*rotFilter)*direction + rotFilter*newnormal;
-                                               } else if (m_posDampTime) {
-                                                       newnormal = -filter*direction + (1.0-filter)*newnormal;
+                                                       rotFilter = m_rotDampTime/(1.0+m_rotDampTime);
+                                               } else {
+                                                       rotFilter = filter;
+                                               }
+                                               newnormal = rotFilter*normal - (1.0-rotFilter)*newnormal;
+                                               obj->AlignAxisToVect((sign)?-newnormal:newnormal, axis);
+                                               if (m_option & KX_ACT_CONSTRAINT_LOCAL) {
+                                                       direction = newnormal;
+                                                       direction.normalize();
                                                }
-                                               obj->AlignAxisToVect(newnormal, axis);
-                                               direction = -newnormal;
                                        }
                                        if (m_option & KX_ACT_CONSTRAINT_DISTANCE) {
                                                if (m_posDampTime) {
@@ -345,6 +369,16 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame)
                                                } else {
                                                        newdistance = m_minimumBound;
                                                }
+                                               // logically we should cancel the speed along the ray direction as we set the
+                                               // position along that axis
+                                               spc = obj->GetPhysicsController();
+                                               if (spc) {
+                                                       MT_Vector3 linV = spc->GetLinearVelocity();
+                                                       // cancel the projection along the ray direction
+                                                       MT_Scalar fallspeed = linV.dot(direction);
+                                                       if (!MT_fuzzyZero(fallspeed))
+                                                               spc->SetLinearVelocity(linV-fallspeed*direction,false);
+                                               }
                                        } else {
                                                newdistance = (position-callback.m_hitPoint).length();
                                        }
index 99c09c1e5ccc8da9e9b41694bcd667f98a81c5ac..b2ef0dae55354b3403ce870c290f189626a63511 100644 (file)
@@ -99,7 +99,8 @@ protected:
                KX_ACT_CONSTRAINT_NORMAL = 64,
                KX_ACT_CONSTRAINT_MATERIAL = 128,
                KX_ACT_CONSTRAINT_PERMANENT = 256,
-               KX_ACT_CONSTRAINT_DISTANCE = 512
+               KX_ACT_CONSTRAINT_DISTANCE = 512,
+               KX_ACT_CONSTRAINT_LOCAL = 1024
        };
        bool IsValidMode(KX_CONSTRAINTTYPE m); 
        bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data);
index f1e30b4a1e3093ea1aafdb334e39399d714458dc..f17cfb79e92afbd4ea4da12f8bdeca4610745cdf 100644 (file)
@@ -963,7 +963,7 @@ void                CcdPhysicsController::SetLinearVelocity(float lin_velX,float lin_velY,floa
 {
 
        btVector3 linVel(lin_velX,lin_velY,lin_velZ);
-       if (m_object && linVel.length2() > (SIMD_EPSILON*SIMD_EPSILON))
+       if (m_object/* && linVel.length2() > (SIMD_EPSILON*SIMD_EPSILON)*/)
        {
                m_object->activate(true);
                if (m_object->isStaticObject())