static int Quaternion_angle_set(QuaternionObject *self, PyObject *value, void *UNUSED(closure)) { float tquat[4]; float len; float axis[3], angle_dummy; float angle; if (BaseMath_ReadCallback(self) == -1) return -1; len = normalize_qt_qt(tquat, self->quat); quat_to_axis_angle(axis, &angle_dummy, tquat); angle = PyFloat_AsDouble(value); if (angle == -1.0f && PyErr_Occurred()) { /* parsed item not a number */ PyErr_SetString(PyExc_TypeError, "Quaternion.angle = value: float expected"); return -1; } angle = angle_wrap_rad(angle); quat__axis_angle_sanitize(axis, &angle); axis_angle_to_quat(self->quat, axis, angle); mul_qt_fl(self->quat, len); if (BaseMath_WriteCallback(self) == -1) return -1; return 0; }
static PyObject *quat_mul_float(QuaternionObject *quat, const float scalar) { float tquat[4]; copy_qt_qt(tquat, quat->quat); mul_qt_fl(tquat, scalar); return Quaternion_CreatePyObject(tquat, Py_NEW, Py_TYPE(quat)); }
static int Quaternion_axis_vector_set(QuaternionObject *self, PyObject *value, void *UNUSED(closure)) { float tquat[4]; float len; float axis[3]; float angle; if (BaseMath_ReadCallback(self) == -1) return -1; len = normalize_qt_qt(tquat, self->quat); quat_to_axis_angle(axis, &angle, tquat); /* axis value is unused */ if (mathutils_array_parse(axis, 3, 3, value, "quat.axis = other") == -1) return -1; quat__axis_angle_sanitize(axis, &angle); axis_angle_to_quat(self->quat, axis, angle); mul_qt_fl(self->quat, len); if (BaseMath_WriteCallback(self) == -1) return -1; return 0; }
static PyObject *Quaternion_negate(QuaternionObject *self) { if (BaseMath_ReadCallback(self) == -1) return NULL; mul_qt_fl(self->quat, -1.0f); (void)BaseMath_WriteCallback(self); Py_RETURN_NONE; }
static PyObject *Quaternion_rotate(QuaternionObject *self, PyObject *value) { float self_rmat[3][3], other_rmat[3][3], rmat[3][3]; float tquat[4], length; if (BaseMath_ReadCallback(self) == -1) return NULL; if (mathutils_any_to_rotmat(other_rmat, value, "Quaternion.rotate(value)") == -1) return NULL; length = normalize_qt_qt(tquat, self->quat); quat_to_mat3(self_rmat, tquat); mul_m3_m3m3(rmat, other_rmat, self_rmat); mat3_to_quat(self->quat, rmat); mul_qt_fl(self->quat, length); /* maintain length after rotating */ (void)BaseMath_WriteCallback(self); Py_RETURN_NONE; }
/* clear rotation of object */ static void object_clear_rot(Object *ob) { /* clear rotations that aren't locked */ if (ob->protectflag & (OB_LOCK_ROTX|OB_LOCK_ROTY|OB_LOCK_ROTZ|OB_LOCK_ROTW)) { if (ob->protectflag & OB_LOCK_ROT4D) { /* perform clamping on a component by component basis */ if (ob->rotmode == ROT_MODE_AXISANGLE) { if ((ob->protectflag & OB_LOCK_ROTW) == 0) ob->rotAngle= ob->drotAngle= 0.0f; if ((ob->protectflag & OB_LOCK_ROTX) == 0) ob->rotAxis[0]= ob->drotAxis[0]= 0.0f; if ((ob->protectflag & OB_LOCK_ROTY) == 0) ob->rotAxis[1]= ob->drotAxis[1]= 0.0f; if ((ob->protectflag & OB_LOCK_ROTZ) == 0) ob->rotAxis[2]= ob->drotAxis[2]= 0.0f; /* check validity of axis - axis should never be 0,0,0 (if so, then we make it rotate about y) */ if (IS_EQF(ob->rotAxis[0], ob->rotAxis[1]) && IS_EQF(ob->rotAxis[1], ob->rotAxis[2])) ob->rotAxis[1] = 1.0f; if (IS_EQF(ob->drotAxis[0], ob->drotAxis[1]) && IS_EQF(ob->drotAxis[1], ob->drotAxis[2])) ob->drotAxis[1]= 1.0f; } else if (ob->rotmode == ROT_MODE_QUAT) { if ((ob->protectflag & OB_LOCK_ROTW) == 0) ob->quat[0]= ob->dquat[0]= 1.0f; if ((ob->protectflag & OB_LOCK_ROTX) == 0) ob->quat[1]= ob->dquat[1]= 0.0f; if ((ob->protectflag & OB_LOCK_ROTY) == 0) ob->quat[2]= ob->dquat[2]= 0.0f; if ((ob->protectflag & OB_LOCK_ROTZ) == 0) ob->quat[3]= ob->dquat[3]= 0.0f; // TODO: does this quat need normalising now? } else { /* the flag may have been set for the other modes, so just ignore the extra flag... */ if ((ob->protectflag & OB_LOCK_ROTX) == 0) ob->rot[0]= ob->drot[0]= 0.0f; if ((ob->protectflag & OB_LOCK_ROTY) == 0) ob->rot[1]= ob->drot[1]= 0.0f; if ((ob->protectflag & OB_LOCK_ROTZ) == 0) ob->rot[2]= ob->drot[2]= 0.0f; } } else { /* perform clamping using euler form (3-components) */ // FIXME: deltas are not handled for these cases yet... float eul[3], oldeul[3], quat1[4] = {0}; if (ob->rotmode == ROT_MODE_QUAT) { copy_qt_qt(quat1, ob->quat); quat_to_eul(oldeul, ob->quat); } else if (ob->rotmode == ROT_MODE_AXISANGLE) { axis_angle_to_eulO(oldeul, EULER_ORDER_DEFAULT, ob->rotAxis, ob->rotAngle); } else { copy_v3_v3(oldeul, ob->rot); } eul[0]= eul[1]= eul[2]= 0.0f; if (ob->protectflag & OB_LOCK_ROTX) eul[0]= oldeul[0]; if (ob->protectflag & OB_LOCK_ROTY) eul[1]= oldeul[1]; if (ob->protectflag & OB_LOCK_ROTZ) eul[2]= oldeul[2]; if (ob->rotmode == ROT_MODE_QUAT) { eul_to_quat(ob->quat, eul); /* quaternions flip w sign to accumulate rotations correctly */ if ((quat1[0]<0.0f && ob->quat[0]>0.0f) || (quat1[0]>0.0f && ob->quat[0]<0.0f)) { mul_qt_fl(ob->quat, -1.0f); } } else if (ob->rotmode == ROT_MODE_AXISANGLE) { eulO_to_axis_angle(ob->rotAxis, &ob->rotAngle,eul, EULER_ORDER_DEFAULT); } else { copy_v3_v3(ob->rot, eul); } } } // Duplicated in source/blender/editors/armature/editarmature.c else { if (ob->rotmode == ROT_MODE_QUAT) { unit_qt(ob->quat); unit_qt(ob->dquat); } else if (ob->rotmode == ROT_MODE_AXISANGLE) { unit_axis_angle(ob->rotAxis, &ob->rotAngle); unit_axis_angle(ob->drotAxis, &ob->drotAngle); } else { zero_v3(ob->rot); zero_v3(ob->drot); } } }