예제 #1
0
//------------------------NUMERIC PROTOCOLS----------------------
//------------------------obj + obj------------------------------
//addition
static PyObject *Quaternion_add(PyObject *q1, PyObject *q2)
{
	float quat[QUAT_SIZE];
	QuaternionObject *quat1 = NULL, *quat2 = NULL;

	if (!QuaternionObject_Check(q1) || !QuaternionObject_Check(q2)) {
		PyErr_Format(PyExc_TypeError,
		             "Quaternion addition: (%s + %s) "
		             "invalid type for this operation",
		             Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name);
		return NULL;
	}
	quat1 = (QuaternionObject *)q1;
	quat2 = (QuaternionObject *)q2;

	if (BaseMath_ReadCallback(quat1) == -1 || BaseMath_ReadCallback(quat2) == -1)
		return NULL;

	add_qt_qtqt(quat, quat1->quat, quat2->quat, 1.0f);
	return Quaternion_CreatePyObject(quat, Py_NEW, Py_TYPE(q1));
}
예제 #2
0
/* helper for apply() - perform sliding for quaternion rotations (using quat blending) */
static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
{
	FCurve *fcu_w = NULL, *fcu_x = NULL, *fcu_y = NULL, *fcu_z = NULL;
	bPoseChannel *pchan = pfl->pchan;
	LinkData *ld = NULL;
	char *path = NULL;
	float cframe;
	
	/* get the path to use - this should be quaternion rotations only (needs care) */
	path = BLI_sprintfN("%s.%s", pfl->pchan_path, "rotation_quaternion");
	
	/* get the current frame number */
	cframe = (float)pso->cframe;
	
	/* using this path, find each matching F-Curve for the variables we're interested in */
	while ( (ld = poseAnim_mapping_getNextFCurve(&pfl->fcurves, ld, path)) ) {
		FCurve *fcu = (FCurve *)ld->data;
		
		/* assign this F-Curve to one of the relevant pointers... */
		switch (fcu->array_index) {
			case 3: /* z */
				fcu_z = fcu;
				break;
			case 2: /* y */
				fcu_y = fcu;
				break;
			case 1: /* x */
				fcu_x = fcu;
				break;
			case 0: /* w */
				fcu_w = fcu;
				break;
		}
	}
	
	/* only if all channels exist, proceed */
	if (fcu_w && fcu_x && fcu_y && fcu_z) {
		float quat_prev[4], quat_next[4];
		
		/* get 2 quats */
		quat_prev[0] = evaluate_fcurve(fcu_w, pso->prevFrame);
		quat_prev[1] = evaluate_fcurve(fcu_x, pso->prevFrame);
		quat_prev[2] = evaluate_fcurve(fcu_y, pso->prevFrame);
		quat_prev[3] = evaluate_fcurve(fcu_z, pso->prevFrame);
		
		quat_next[0] = evaluate_fcurve(fcu_w, pso->nextFrame);
		quat_next[1] = evaluate_fcurve(fcu_x, pso->nextFrame);
		quat_next[2] = evaluate_fcurve(fcu_y, pso->nextFrame);
		quat_next[3] = evaluate_fcurve(fcu_z, pso->nextFrame);
		
		/* perform blending */
		if (pso->mode == POSESLIDE_BREAKDOWN) {
			/* just perform the interpol between quat_prev and quat_next using pso->percentage as a guide */
			interp_qt_qtqt(pchan->quat, quat_prev, quat_next, pso->percentage);
		}
		else if (pso->mode == POSESLIDE_PUSH) {
			float quat_diff[4], quat_orig[4];

			/* calculate the delta transform from the previous to the current */
			/* TODO: investigate ways to favour one transform more? */
			sub_qt_qtqt(quat_diff, pchan->quat, quat_prev);

			/* make a copy of the original rotation */
			copy_qt_qt(quat_orig, pchan->quat);
			
			/* increase the original by the delta transform, by an amount determined by percentage */
			add_qt_qtqt(pchan->quat, quat_orig, quat_diff, pso->percentage);
		}
		else {
			float quat_interp[4], quat_orig[4];
			int iters = (int)ceil(10.0f * pso->percentage); /* TODO: maybe a sensitivity ctrl on top of this is needed */

			/* perform this blending several times until a satisfactory result is reached */
			while (iters-- > 0) {
				/* calculate the interpolation between the endpoints */
				interp_qt_qtqt(quat_interp, quat_prev, quat_next, (cframe - pso->prevFrame) / (pso->nextFrame - pso->prevFrame));
				
				/* make a copy of the original rotation */
				copy_qt_qt(quat_orig, pchan->quat);
				
				/* tricky interpolations - blending between original and new */
				interp_qt_qtqt(pchan->quat, quat_orig, quat_interp, 1.0f / 6.0f);
			}
		}
	}
	
	/* free the path now */
	MEM_freeN(path);
}