[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [20248] trunk/blender: Bugfix for FBX export for animations

Campbell Barton ideasman42 at gmail.com
Mon May 18 06:11:55 CEST 2009


Revision: 20248
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=20248
Author:   campbellbarton
Date:     2009-05-18 06:11:54 +0200 (Mon, 18 May 2009)

Log Message:
-----------
Bugfix for FBX export for animations
in 2.48 constant interpolations meant that wasnt a problem but since it now uses linear interp. you can notice errors with animated characters because the 2 eulers are not compatible.

Added optional euler_compat argument to matrix.toEuler(eul) and quat.toEuler(eul) so when getting the euler rotations from a list of matrices the animation curve will be continues.
Also added euler.makeCompatible(euler).

- warning silenced for imagepaint.c

Modified Paths:
--------------
    trunk/blender/release/scripts/export_fbx.py
    trunk/blender/source/blender/python/api2_2x/doc/Mathutils.py
    trunk/blender/source/blender/python/api2_2x/euler.c
    trunk/blender/source/blender/python/api2_2x/euler.h
    trunk/blender/source/blender/python/api2_2x/matrix.c
    trunk/blender/source/blender/python/api2_2x/matrix.h
    trunk/blender/source/blender/python/api2_2x/quat.c
    trunk/blender/source/blender/python/api2_2x/quat.h
    trunk/blender/source/blender/src/imagepaint.c

Modified: trunk/blender/release/scripts/export_fbx.py
===================================================================
--- trunk/blender/release/scripts/export_fbx.py	2009-05-18 02:25:33 UTC (rev 20247)
+++ trunk/blender/release/scripts/export_fbx.py	2009-05-18 04:11:54 UTC (rev 20248)
@@ -2591,8 +2591,18 @@
 						for TX_LAYER, TX_CHAN in enumerate('TRS'): # transform, rotate, scale
 							
 							if		TX_CHAN=='T':	context_bone_anim_vecs = [mtx[0].translationPart()	for mtx in context_bone_anim_mats]
-							elif 	TX_CHAN=='R':	context_bone_anim_vecs = [mtx[1].toEuler()			for mtx in context_bone_anim_mats]
-							else:					context_bone_anim_vecs = [mtx[0].scalePart()		for mtx in context_bone_anim_mats]
+							elif	TX_CHAN=='S':	context_bone_anim_vecs = [mtx[0].scalePart()		for mtx in context_bone_anim_mats]
+							elif	TX_CHAN=='R':
+								# Was....
+								# elif 	TX_CHAN=='R':	context_bone_anim_vecs = [mtx[1].toEuler()			for mtx in context_bone_anim_mats]
+								# 
+								# ...but we need to use the previous euler for compatible conversion.
+								context_bone_anim_vecs = []
+								prev_eul = None
+								for mtx in context_bone_anim_mats:
+									if prev_eul:	prev_eul = mtx[1].toEuler(prev_eul)
+									else:			prev_eul = mtx[1].toEuler()
+									context_bone_anim_vecs.append(prev_eul)
 							
 							file.write('\n\t\t\t\tChannel: "%s" {' % TX_CHAN) # translation
 							

Modified: trunk/blender/source/blender/python/api2_2x/doc/Mathutils.py
===================================================================
--- trunk/blender/source/blender/python/api2_2x/doc/Mathutils.py	2009-05-18 02:25:33 UTC (rev 20247)
+++ trunk/blender/source/blender/python/api2_2x/doc/Mathutils.py	2009-05-18 04:11:54 UTC (rev 20248)
@@ -617,6 +617,12 @@
     @rtype: Quaternion object
     @return: Quaternion representation of the euler.
     """
+  def makeCompatible(eul_compat):
+    """
+    Make this euler compatible with another, so interpolating between them works as expected.
+    @rtype: Euler object
+    @return: an instance of itself
+    """
 
 class Quaternion:
   """
@@ -718,9 +724,11 @@
     @return: an instance of itself
     """
 
-  def toEuler():
+  def toEuler(eul_compat):
     """
     Return Euler representation of the quaternion.
+    @type eul_compat: L{Euler}
+    @param eul_compat: Optional euler argument the new euler will be made compatible with (no axis flipping between them). Useful for converting a series of matrices to animation curves.
     @rtype: Euler object
     @return: Euler representation of the quaternion.
     """
@@ -870,9 +878,11 @@
     @return: an instance of itself.
     """
   
-  def toEuler():
+  def toEuler(eul_compat):
     """
     Return an Euler representation of the rotation matrix (3x3 or 4x4 matrix only).
+    @type eul_compat: L{Euler}
+    @param eul_compat: Optional euler argument the new euler will be made compatible with (no axis flipping between them). Useful for converting a series of matrices to animation curves.
     @rtype: Euler object
     @return: Euler representation of the rotation matrix.
     """

Modified: trunk/blender/source/blender/python/api2_2x/euler.c
===================================================================
--- trunk/blender/source/blender/python/api2_2x/euler.c	2009-05-18 02:25:33 UTC (rev 20247)
+++ trunk/blender/source/blender/python/api2_2x/euler.c	2009-05-18 04:11:54 UTC (rev 20248)
@@ -40,6 +40,7 @@
 char Euler_ToQuat_doc[] = "() - returns a quaternion representing the euler rotation";
 char Euler_Rotate_doc[] = "() - rotate a euler by certain amount around an axis of rotation";
 char Euler_copy_doc[] = "() - returns a copy of the euler.";
+char Euler_MakeCompatible_doc[] = "(euler) - Make this user compatible with another (no axis flipping).";
 //-----------------------METHOD DEFINITIONS ----------------------
 struct PyMethodDef Euler_methods[] = {
 	{"zero", (PyCFunction) Euler_Zero, METH_NOARGS, Euler_Zero_doc},
@@ -47,6 +48,7 @@
 	{"toMatrix", (PyCFunction) Euler_ToMatrix, METH_NOARGS, Euler_ToMatrix_doc},
 	{"toQuat", (PyCFunction) Euler_ToQuat, METH_NOARGS, Euler_ToQuat_doc},
 	{"rotate", (PyCFunction) Euler_Rotate, METH_VARARGS, Euler_Rotate_doc},
+	{"makeCompatible", (PyCFunction) Euler_MakeCompatible, METH_O, Euler_MakeCompatible_doc},
 	{"__copy__", (PyCFunction) Euler_copy, METH_VARARGS, Euler_copy_doc},
 	{"copy", (PyCFunction) Euler_copy, METH_VARARGS, Euler_copy_doc},
 	{NULL, NULL, 0, NULL}
@@ -173,6 +175,32 @@
 	Py_INCREF(self);
 	return (PyObject *)self;
 }
+
+PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value)
+{
+	float eul_from_rad[3];
+	int x;
+	
+	if(!EulerObject_Check(value)) {
+		PyErr_SetString(PyExc_TypeError, "euler.makeCompatible(euler):expected a single euler argument.");
+		return NULL;
+	}
+	
+	//covert to radians
+	for(x = 0; x < 3; x++) {
+		self->eul[x] = self->eul[x] * ((float)Py_PI / 180);
+		eul_from_rad[x] = value->eul[x] * ((float)Py_PI / 180);
+	}
+	compatible_eul(self->eul, eul_from_rad);
+	//convert back from radians
+	for(x = 0; x < 3; x++) {
+		self->eul[x] *= (180 / (float)Py_PI);
+	}
+	
+	Py_INCREF(self);
+	return (PyObject *)self;
+}
+
 //----------------------------Euler.rotate()-----------------------
 // return a copy of the euler
 PyObject *Euler_copy(EulerObject * self, PyObject *args)
@@ -528,4 +556,3 @@
 	}
 	return (PyObject *)self;
 }
-

Modified: trunk/blender/source/blender/python/api2_2x/euler.h
===================================================================
--- trunk/blender/source/blender/python/api2_2x/euler.h	2009-05-18 02:25:33 UTC (rev 20247)
+++ trunk/blender/source/blender/python/api2_2x/euler.h	2009-05-18 04:11:54 UTC (rev 20248)
@@ -58,6 +58,7 @@
 PyObject *Euler_ToMatrix( EulerObject * self );
 PyObject *Euler_ToQuat( EulerObject * self );
 PyObject *Euler_Rotate( EulerObject * self, PyObject *args );
+PyObject *Euler_MakeCompatible( EulerObject * self, EulerObject *value );
 PyObject *Euler_copy( EulerObject * self, PyObject *args );
 PyObject *newEulerObject( float *eul, int type );
 

Modified: trunk/blender/source/blender/python/api2_2x/matrix.c
===================================================================
--- trunk/blender/source/blender/python/api2_2x/matrix.c	2009-05-18 02:25:33 UTC (rev 20247)
+++ trunk/blender/source/blender/python/api2_2x/matrix.c	2009-05-18 04:11:54 UTC (rev 20248)
@@ -41,7 +41,7 @@
 char Matrix_RotationPart_doc[] = "() - return a vector encompassing the rotation of the matrix";
 char Matrix_scalePart_doc[] = "() - convert matrix to a 3D vector";
 char Matrix_Resize4x4_doc[] = "() - resize the matrix to a 4x4 square matrix";
-char Matrix_toEuler_doc[] = "() - convert matrix to a euler angle rotation";
+char Matrix_toEuler_doc[] = "(eul_compat) - convert matrix to a euler angle rotation, optional euler argument that the new euler will be made compatible with.";
 char Matrix_toQuat_doc[] = "() - convert matrix to a quaternion rotation";
 char Matrix_copy_doc[] = "() - return a copy of the matrix";
 /*-----------------------METHOD DEFINITIONS ----------------------*/
@@ -55,7 +55,7 @@
 	{"rotationPart", (PyCFunction) Matrix_RotationPart, METH_NOARGS, Matrix_RotationPart_doc},
 	{"scalePart", (PyCFunction) Matrix_scalePart, METH_NOARGS, Matrix_scalePart_doc},
 	{"resize4x4", (PyCFunction) Matrix_Resize4x4, METH_NOARGS, Matrix_Resize4x4_doc},
-	{"toEuler", (PyCFunction) Matrix_toEuler, METH_NOARGS, Matrix_toEuler_doc},
+	{"toEuler", (PyCFunction) Matrix_toEuler, METH_VARARGS, Matrix_toEuler_doc},
 	{"toQuat", (PyCFunction) Matrix_toQuat, METH_NOARGS, Matrix_toQuat_doc},
 	{"copy", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc},
 	{"__copy__", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc},
@@ -81,19 +81,32 @@
 	return newQuaternionObject(quat, Py_NEW);
 }
 /*---------------------------Matrix.toEuler() --------------------*/
-PyObject *Matrix_toEuler(MatrixObject * self)
+PyObject *Matrix_toEuler(MatrixObject * self, PyObject *args)
 {
-	float eul[3];
+	float eul[3], eul_compatf[3];
+	EulerObject *eul_compat = NULL;
+	int x;
 	
-	int x;
-
+	if(!PyArg_ParseTuple(args, "|O!:toEuler", &euler_Type, &eul_compat))
+		return NULL;
+	
+	if(eul_compat) {
+		for(x = 0; x < 3; x++) {
+			eul_compatf[x] = eul_compat->eul[x] *= ((float)Py_PI / 180);
+		}
+	}
+	
 	/*must be 3-4 cols, 3-4 rows, square matrix*/
 	if(self->colSize ==3 && self->rowSize ==3) {
-		Mat3ToEul((float (*)[3])*self->matrix, eul);
+		if(eul_compat)	Mat3ToCompatibleEul((float (*)[3])*self->matrix, eul, eul_compatf);
+		else			Mat3ToEul((float (*)[3])*self->matrix, eul);
 	}else if (self->colSize ==4 && self->rowSize ==4) {
 		float tempmat3[3][3];
 		Mat3CpyMat4(tempmat3, (float (*)[4])*self->matrix);
 		Mat3ToEul(tempmat3, eul);
+		if(eul_compat)	Mat3ToCompatibleEul(tempmat3, eul, eul_compatf);
+		else			Mat3ToEul(tempmat3, eul);
+		
 	}else {
 		PyErr_SetString(PyExc_AttributeError, "Matrix.toEuler(): inappropriate matrix size - expects 3x3 or 4x4 matrix\n");
 		return NULL;

Modified: trunk/blender/source/blender/python/api2_2x/matrix.h
===================================================================
--- trunk/blender/source/blender/python/api2_2x/matrix.h	2009-05-18 02:25:33 UTC (rev 20247)
+++ trunk/blender/source/blender/python/api2_2x/matrix.h	2009-05-18 04:11:54 UTC (rev 20248)
@@ -69,7 +69,7 @@
 PyObject *Matrix_RotationPart( MatrixObject * self );
 PyObject *Matrix_scalePart( MatrixObject * self );
 PyObject *Matrix_Resize4x4( MatrixObject * self );
-PyObject *Matrix_toEuler( MatrixObject * self );
+PyObject *Matrix_toEuler( MatrixObject * self, PyObject *args );
 PyObject *Matrix_toQuat( MatrixObject * self );
 PyObject *Matrix_copy( MatrixObject * self );
 PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type);

Modified: trunk/blender/source/blender/python/api2_2x/quat.c
===================================================================
--- trunk/blender/source/blender/python/api2_2x/quat.c	2009-05-18 02:25:33 UTC (rev 20247)
+++ trunk/blender/source/blender/python/api2_2x/quat.c	2009-05-18 04:11:54 UTC (rev 20248)
@@ -39,7 +39,7 @@
 char Quaternion_Conjugate_doc[] = "() - set the quaternion to it's conjugate";
 char Quaternion_Inverse_doc[] = "() - set the quaternion to it's inverse";
 char Quaternion_Normalize_doc[] = "() - normalize the vector portion of the quaternion";

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list