forked from bartvdbraak/blender
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
This commit is contained in:
parent
9a40f4d2a6
commit
5a16f0b60c
@ -2591,8 +2591,18 @@ Takes: {''')
|
||||
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
|
||||
|
||||
|
@ -617,6 +617,12 @@ class Euler:
|
||||
@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 @@ class Quaternion:
|
||||
@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 @@ class Matrix:
|
||||
@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.
|
||||
"""
|
||||
|
@ -40,6 +40,7 @@ char Euler_ToMatrix_doc[] = "() - returns a rotation matrix representing the eul
|
||||
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 @@ struct PyMethodDef Euler_methods[] = {
|
||||
{"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 @@ PyObject *Euler_Rotate(EulerObject * self, PyObject *args)
|
||||
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 @@ PyObject *newEulerObject(float *eul, int type)
|
||||
}
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
|
@ -58,6 +58,7 @@ PyObject *Euler_Unique( EulerObject * self );
|
||||
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 );
|
||||
|
||||
|
@ -41,7 +41,7 @@ char Matrix_TranslationPart_doc[] = "() - return a vector encompassing the trans
|
||||
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 @@ struct PyMethodDef Matrix_methods[] = {
|
||||
{"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 @@ PyObject *Matrix_toQuat(MatrixObject * self)
|
||||
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;
|
||||
|
||||
|
||||
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;
|
||||
|
@ -69,7 +69,7 @@ PyObject *Matrix_TranslationPart( MatrixObject * self );
|
||||
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);
|
||||
|
@ -39,7 +39,7 @@ char Quaternion_Negate_doc[] = "() - set all values in the quaternion to their n
|
||||
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";
|
||||
char Quaternion_ToEuler_doc[] = "() - return a euler rotation representing the quaternion";
|
||||
char Quaternion_ToEuler_doc[] = "(eul_compat) - return a euler rotation representing the quaternion, optional euler argument that the new euler will be made compatible with.";
|
||||
char Quaternion_ToMatrix_doc[] = "() - return a rotation matrix representing the quaternion";
|
||||
char Quaternion_copy_doc[] = "() - return a copy of the quat";
|
||||
//-----------------------METHOD DEFINITIONS ----------------------
|
||||
@ -49,7 +49,7 @@ struct PyMethodDef Quaternion_methods[] = {
|
||||
{"conjugate", (PyCFunction) Quaternion_Conjugate, METH_NOARGS, Quaternion_Conjugate_doc},
|
||||
{"inverse", (PyCFunction) Quaternion_Inverse, METH_NOARGS, Quaternion_Inverse_doc},
|
||||
{"normalize", (PyCFunction) Quaternion_Normalize, METH_NOARGS, Quaternion_Normalize_doc},
|
||||
{"toEuler", (PyCFunction) Quaternion_ToEuler, METH_NOARGS, Quaternion_ToEuler_doc},
|
||||
{"toEuler", (PyCFunction) Quaternion_ToEuler, METH_VARARGS, Quaternion_ToEuler_doc},
|
||||
{"toMatrix", (PyCFunction) Quaternion_ToMatrix, METH_NOARGS, Quaternion_ToMatrix_doc},
|
||||
{"__copy__", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc},
|
||||
{"copy", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc},
|
||||
@ -58,12 +58,30 @@ struct PyMethodDef Quaternion_methods[] = {
|
||||
//-----------------------------METHODS------------------------------
|
||||
//----------------------------Quaternion.toEuler()------------------
|
||||
//return the quat as a euler
|
||||
PyObject *Quaternion_ToEuler(QuaternionObject * self)
|
||||
PyObject *Quaternion_ToEuler(QuaternionObject * self, PyObject *args)
|
||||
{
|
||||
float eul[3];
|
||||
EulerObject *eul_compat = NULL;
|
||||
int x;
|
||||
|
||||
QuatToEul(self->quat, eul);
|
||||
|
||||
if(!PyArg_ParseTuple(args, "|O!:toEuler", &euler_Type, &eul_compat))
|
||||
return NULL;
|
||||
|
||||
if(eul_compat) {
|
||||
float mat[3][3], eul_compatf[3];
|
||||
|
||||
for(x = 0; x < 3; x++) {
|
||||
eul_compatf[x] = eul_compat->eul[x] * ((float)Py_PI / 180);
|
||||
}
|
||||
|
||||
QuatToMat3(self->quat, mat);
|
||||
Mat3ToCompatibleEul(mat, eul, eul_compatf);
|
||||
}
|
||||
else {
|
||||
QuatToEul(self->quat, eul);
|
||||
}
|
||||
|
||||
|
||||
for(x = 0; x < 3; x++) {
|
||||
eul[x] *= (180 / (float)Py_PI);
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ PyObject *Quaternion_Negate( QuaternionObject * self );
|
||||
PyObject *Quaternion_Conjugate( QuaternionObject * self );
|
||||
PyObject *Quaternion_Inverse( QuaternionObject * self );
|
||||
PyObject *Quaternion_Normalize( QuaternionObject * self );
|
||||
PyObject *Quaternion_ToEuler( QuaternionObject * self );
|
||||
PyObject *Quaternion_ToEuler( QuaternionObject * self, PyObject *args );
|
||||
PyObject *Quaternion_ToMatrix( QuaternionObject * self );
|
||||
PyObject *Quaternion_copy( QuaternionObject * self );
|
||||
PyObject *newQuaternionObject( float *quat, int type );
|
||||
|
@ -2603,7 +2603,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
|
||||
|
||||
if (!is_ortho) {
|
||||
pixelScreenCo[3] = 1.0f;
|
||||
Mat4MulVec4fl(ps->projectMat, pixelScreenCo);
|
||||
Mat4MulVec4fl((float (*)[4])*ps->projectMat, pixelScreenCo);
|
||||
pixelScreenCo[0] = (float)(curarea->winx/2.0f)+(curarea->winx/2.0f)*pixelScreenCo[0]/pixelScreenCo[3];
|
||||
pixelScreenCo[1] = (float)(curarea->winy/2.0f)+(curarea->winy/2.0f)*pixelScreenCo[1]/pixelScreenCo[3];
|
||||
pixelScreenCo[2] = pixelScreenCo[2]/pixelScreenCo[3]; /* Use the depth for bucket point occlusion */
|
||||
@ -4664,3 +4664,4 @@ void imagepaint_pick(short mousebutton)
|
||||
sample_vpaint();
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user