diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index f123c14fddf..14270d3a7c9 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -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 diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 66905c6f240..85e45e87994 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -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! */ diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h index 750bdf2cfff..2487216f764 100644 --- a/source/blender/makesdna/DNA_actuator_types.h +++ b/source/blender/makesdna/DNA_actuator_types.h @@ -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 diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index a6f4acb8c68..e36e51d9686 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -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) diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp index 11af4b9324b..49534ccbd4a 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp @@ -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 = 0; + break; + case KX_ACT_CONSTRAINT_DIRNX: + normal[0] = -rotation[0][0]; + normal[1] = -rotation[1][0]; + normal[2] = -rotation[2][0]; + axis = 0; + sign = 1; + break; + case KX_ACT_CONSTRAINT_DIRNY: + normal[0] = -rotation[0][1]; + normal[1] = -rotation[1][1]; + normal[2] = -rotation[2][1]; + axis = 1; + sign = 1; + break; + case KX_ACT_CONSTRAINT_DIRNZ: + normal[0] = -rotation[0][2]; + normal[1] = -rotation[1][2]; + normal[2] = -rotation[2][2]; axis = 2; sign = 1; break; - case KX_ACT_CONSTRAINT_DIRNX: - direction[0] = -rotation[0][0]; - direction[1] = -rotation[1][0]; - direction[2] = -rotation[2][0]; - axis = 0; - sign = 0; - break; - case KX_ACT_CONSTRAINT_DIRNY: - direction[0] = -rotation[0][1]; - direction[1] = -rotation[1][1]; - direction[2] = -rotation[2][1]; - axis = 1; - sign = 0; - break; - case KX_ACT_CONSTRAINT_DIRNZ: - direction[0] = -rotation[0][2]; - direction[1] = -rotation[1][2]; - direction[2] = -rotation[2][2]; - axis = 2; - sign = 0; - 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(); } diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.h b/source/gameengine/Ketsji/KX_ConstraintActuator.h index 99c09c1e5cc..b2ef0dae553 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.h +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.h @@ -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); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index f1e30b4a1e3..f17cfb79e92 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -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())