[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [16706] trunk/blender/source/gameengine/ Ketsji: BGE bug #17657 fixed: dRotY doesn' t work properly after 90 degrees rotation.
Benoit Bolsee
benoit.bolsee at online.be
Tue Sep 23 22:07:16 CEST 2008
Revision: 16706
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=16706
Author: ben2610
Date: 2008-09-23 22:07:15 +0200 (Tue, 23 Sep 2008)
Log Message:
-----------
BGE bug #17657 fixed: dRotY doesn't work properly after 90 degrees rotation.
This problem is caused by discontinuities in the conversion
orientation matrix -> euler angles: the angle sign can
switch and thus the direction of the rotation produced
by the dRot Ipo.
To avoid this bug, the matrix->euler conversion must be
avoided during the game. I took the following approach that
is compatible with Blender (identical effect in the game and
in the 3D view):
- no change in Add mode: Rot and dRot are treated as additional
rotation to the orientation at the start of the Ipo. There is
no matrix->euler conversion and thus no discontinuities.
- Rot Ipo are treated as absolute rotation. All 3 axis should
be specified but if they are not, the startup object orientation
will be used to set the unspecified axis. By doing a matrix->
euler conversion once at the start, the discontinuities are
avoided. If there are also dRot curves, they are treated as
delta of the corresponding Rot curve or startup angle.
- dRot Ipo are treated as Add mode in Local axis.
Note about Add mode: Rot and dRot curves are treated identically
during the game. However, only dRot curves make sense because
they don't interfere with the object orientation in the 3D view.
Modified Paths:
--------------
trunk/blender/source/gameengine/Ketsji/KX_IPO_SGController.cpp
trunk/blender/source/gameengine/Ketsji/KX_IPO_SGController.h
Modified: trunk/blender/source/gameengine/Ketsji/KX_IPO_SGController.cpp
===================================================================
--- trunk/blender/source/gameengine/Ketsji/KX_IPO_SGController.cpp 2008-09-23 15:57:05 UTC (rev 16705)
+++ trunk/blender/source/gameengine/Ketsji/KX_IPO_SGController.cpp 2008-09-23 20:07:15 UTC (rev 16706)
@@ -59,7 +59,9 @@
m_ipo_local(false),
m_modified(true),
m_ipo_start_initialized(false),
- m_ipotime(1.0)
+ m_ipotime(1.0),
+ m_ipo_start_euler(0.0,0.0,0.0),
+ m_ipo_euler_initialized(false)
{
m_game_object = NULL;
for (int i=0; i < KX_MAX_IPO_CHANNELS; i++)
@@ -136,6 +138,11 @@
m_ipo_start_orient = ob->GetLocalOrientation();
m_ipo_start_scale = ob->GetLocalScale();
m_ipo_start_initialized = true;
+ if (!m_ipo_euler_initialized) {
+ // do it only once to avoid angle discontinuities
+ m_ipo_start_orient.getEuler(m_ipo_start_euler[0], m_ipo_start_euler[1], m_ipo_start_euler[2]);
+ m_ipo_euler_initialized = true;
+ }
}
//modifies position?
@@ -199,51 +206,87 @@
ob->GetWorldOrientation() * m_ipo_xform.GetEulerAngles() :
m_ipo_xform.GetEulerAngles(), false);
}
- } else {
- double yaw=0, pitch=0, roll=0; //final Euler angles
- double tempYaw=0, tempPitch=0, tempRoll=0; //temp holders
- if (!m_ipo_add)
- ob->GetLocalOrientation().getEuler(yaw, pitch, roll);
+ } else if (m_ipo_add) {
+ if (m_ipo_start_initialized) {
+ double yaw=0, pitch=0, roll=0; //delta Euler angles
- //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) {
- if (!m_ipo_add)
- m_ipo_start_orient.getEuler(tempYaw, tempPitch, tempRoll);
- yaw = tempYaw + m_ipo_xform.GetDeltaEulerAngles()[0];
- }
+ //RotX and dRotX
+ if (m_ipo_channels_active[OB_ROT_X])
+ yaw += m_ipo_xform.GetEulerAngles()[0];
+ if (m_ipo_channels_active[OB_DROT_X])
+ yaw += 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) {
- if (!m_ipo_add)
- 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) {
- if (!m_ipo_add)
- m_ipo_start_orient.getEuler(tempYaw, tempPitch, tempRoll);
- roll = tempRoll + m_ipo_xform.GetDeltaEulerAngles()[2];
- }
- if (m_ipo_add) {
+ //RotY dRotY
+ if (m_ipo_channels_active[OB_ROT_Y])
+ pitch += m_ipo_xform.GetEulerAngles()[1];
+ if (m_ipo_channels_active[OB_DROT_Y])
+ pitch += m_ipo_xform.GetDeltaEulerAngles()[1];
+
+ //RotZ and dRotZ
+ if (m_ipo_channels_active[OB_ROT_Z])
+ roll += m_ipo_xform.GetEulerAngles()[2];
+ if (m_ipo_channels_active[OB_DROT_Z])
+ roll += m_ipo_xform.GetDeltaEulerAngles()[2];
+
MT_Matrix3x3 rotation(MT_Vector3(yaw, pitch, roll));
if (m_ipo_local)
rotation = m_ipo_start_orient * rotation;
else
rotation = rotation * m_ipo_start_orient;
ob->SetLocalOrientation(rotation);
- } else {
+ }
+ } else if (m_ipo_channels_active[OB_ROT_X] || m_ipo_channels_active[OB_ROT_Y] || m_ipo_channels_active[OB_ROT_Z]) {
+ if (m_ipo_euler_initialized) {
+ // assume all channel absolute
+ // All 3 channels should be specified but if they are not, we will take
+ // the value at the start of the game to avoid angle sign reversal
+ double yaw=m_ipo_start_euler[0], pitch=m_ipo_start_euler[1], roll=m_ipo_start_euler[2];
+
+ //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]) {
+ yaw += 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]) {
+ pitch += 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]) {
+ roll += m_ipo_xform.GetDeltaEulerAngles()[2];
+ }
ob->SetLocalOrientation(MT_Vector3(yaw, pitch, roll));
}
+ } else if (m_ipo_start_initialized) {
+ // only DROT, treat as Add
+ double yaw=0, pitch=0, roll=0; //delta Euler angles
+
+ //dRotX
+ if (m_ipo_channels_active[OB_DROT_X])
+ yaw = m_ipo_xform.GetDeltaEulerAngles()[0];
+
+ //dRotY
+ if (m_ipo_channels_active[OB_DROT_Y])
+ pitch = m_ipo_xform.GetDeltaEulerAngles()[1];
+
+ //dRotZ
+ if (m_ipo_channels_active[OB_DROT_Z])
+ roll = m_ipo_xform.GetDeltaEulerAngles()[2];
+
+ // dRot are always local
+ MT_Matrix3x3 rotation(MT_Vector3(yaw, pitch, roll));
+ rotation = m_ipo_start_orient * rotation;
+ ob->SetLocalOrientation(rotation);
}
}
//modifies scale?
Modified: trunk/blender/source/gameengine/Ketsji/KX_IPO_SGController.h
===================================================================
--- trunk/blender/source/gameengine/Ketsji/KX_IPO_SGController.h 2008-09-23 15:57:05 UTC (rev 16705)
+++ trunk/blender/source/gameengine/Ketsji/KX_IPO_SGController.h 2008-09-23 20:07:15 UTC (rev 16706)
@@ -72,6 +72,12 @@
/** if IPO initial position has been set for local normal IPO */
bool m_ipo_start_initialized;
+ /** Euler angles at the start of the game, needed for incomplete ROT Ipo curves */
+ class MT_Vector3 m_ipo_start_euler;
+
+ /** true is m_ipo_start_euler has been initialized */
+ bool m_ipo_euler_initialized;
+
/** A reference to the original game object. */
class KX_GameObject* m_game_object;
More information about the Bf-blender-cvs
mailing list