Esempio n. 1
0
/** 
 * @ingroup quaternion
 * @brief Linear interpolates between two quaternions.  It will cause the resulting quaternion to move in a straight line "through the 3-sphere"
 *
 * @param percent This refers to how far along we want to go toward end.  1.0 means go to the end. 0.0 means start.  1.1 is nonsense. Negative is nonsense.
 * @param start The quaternion representing the starting orientation
 * @param end The quaternion representing the final or ending orientation
 * @param qR The resulting new orientation.
 *
 */
HYPAPI quaternion * quaternion_lerp(const quaternion *start, const quaternion *end, float percent, quaternion *qR)
{
	float f1, f2;
	
	/* if percent is 0, return start */
	if(percent == 0.0f)
	{
		quaternion_set(qR, start);
		return qR;
	}
	
	/* if percent is 1 return end */
	if(percent == 1.0f)
	{
		quaternion_set(qR, end);
		return qR;
	}
	
	f1 = 1.0f - percent;
	f2 = percent;
	
	/* this expanded form avoids calling quaternion_multiply and quaternion_add */
	qR->w = f1 * start->w + f2 * end->w;
	qR->x = f1 * start->x + f2 * end->x;
	qR->y = f1 * start->y + f2 * end->y;
	qR->z = f1 * start->z + f2 * end->z;
	
	return qR;
}
Esempio n. 2
0
/** 
 * @ingroup experimental
 * @brief This code is suspect. Treats two quaternions sort of like 2 vector4's and then computes the cross-product between them. 
 *
 */
HYPAPI void quaternion_axis_between_EXP(const quaternion *self, const quaternion *qT, quaternion *qR)
{
	quaternion axis;
	axis = quaternion_cross_product_EXP(self, qT);
	quaternion_set(qR, &axis);
	quaternion_normalize(qR);
}
Esempio n. 3
0
/**
 * @ingroup experimental
 * @brief this is an opinionated method (opinionated about what axis is yaw, pitch, roll and what is left/right/up/down
 *
 * @param self the quaternion
 * @param ax the x axis
 * @param ay the y axis
 * @param az the z axis
 *
 */
HYPAPI quaternion * quaternion_set_from_euler_anglesf3_EXP(quaternion *self, float ax, float ay, float az)
{
	vector3 vx;
	vector3 vy;
	vector3 vz;
	quaternion qx;
	quaternion qy;
	quaternion qz;
	
	vector3_setf3(&vx, 1, 0, 0);
	vector3_setf3(&vy, 0, 1, 0);
	vector3_setf3(&vz, 0, 0, 1);
	
	quaternion_set_from_axis_anglev3(&qx, &vx, ax);
	quaternion_set_from_axis_anglev3(&qy, &vy, ay);
	quaternion_set_from_axis_anglev3(&qz, &vz, az);
	
	/* self = qx * qy * qz */
	quaternion_multiply(&qx, &qy);
	quaternion_multiply(&qx, &qz);	
	quaternion_set(self, &qx);
	
	quaternion_normalize(self);
	
	return self;
}
Esempio n. 4
0
/**
 * @ingroup vector3
 * @brief Rotate a point by the quaternion.  Returns the rotated point.
 *
 * \f$self= qT * self * conjugate(qT)\f$
 *
 * @param self the starting point
 * @param qT the quaternion
 *
 */
HYPAPI vector3 * vector3_rotate_by_quaternion(vector3 *self, const quaternion *qT)
{
	quaternion qinverse;
	quaternion q;
	
	/* make the conjugate */
	quaternion_set(&qinverse, qT);
	quaternion_conjugate(&qinverse);
	
	quaternion_set(&q, qT);
	quaternion_multiplyv3(&q, self);
	quaternion_multiply(&q, &qinverse);
	
	self->x = q.x;
	self->y = q.y;
	self->z = q.z;
	
	return self;
}
Esempio n. 5
0
void
quaternion_inverse(Quaternion *ret, const Quaternion *quat)
{
/* 	double n = norm(quat); */

	quaternion_set(ret, quat);
	quaternion_conjugate(ret);

	/* unit quaternion, so take conjugate */
	quaternion_normalize(ret);
 	/* printf("Quaternion inverse: ret = {%f, %f, %f, %f}, quat = {%f, %f, %f, %f}\n",
 	 	   ret->w, ret->x, ret->y, ret->z, quat->w, quat->x, quat->y, quat->z); */
}
Esempio n. 6
0
/** 
 * @ingroup quaternion
 * @brief in place multiplies the quaternion by the vector.  The w element is handled a little differenly in this case.  See source code.
 */
HYPAPI quaternion * quaternion_multiplyv3(quaternion *self, const vector3 *vT)
{
	/* vT is the multiplicand */
	
	quaternion r;
	
	r.x = self->w*vT->x + self->y*vT->z - self->z*vT->y;
	r.y = self->w*vT->y - self->x*vT->z + self->z*vT->x;
	r.z = self->w*vT->z + self->x*vT->y - self->y*vT->x;
	r.w = 0 - self->x*vT->x - self->y*vT->y - self->z*vT->z;
	
	quaternion_set(self, &r); /* overwrite/save it */
	
	return self;
}
Esempio n. 7
0
/** 
 * @ingroup quaternion
 * @brief in place multiplies the quaternion by a quaternion
 */
HYPAPI quaternion * quaternion_multiply(quaternion *self, const quaternion *qT)
{
	/* qT is the multiplicand */
	
	quaternion r;
	
	r.x = self->w * qT->x + self->x * qT->w + self->y * qT->z - self->z * qT->y;
	r.y = self->w * qT->y - self->x * qT->z + self->y * qT->w + self->z * qT->x;
	r.z = self->w * qT->z + self->x * qT->y - self->y * qT->x + self->z * qT->w;
	r.w = self->w * qT->w - self->x * qT->x - self->y * qT->y - self->z * qT->z;
	
	quaternion_set(self, &r); /* overwrite/save it */
	
	return self;
}
Esempio n. 8
0
/** [quaternion inverse example] */
static char * test_quaternion_inverse()
{
	quaternion qA;
	quaternion qInverse;
	quaternion qIdentity;
	
	quaternion_set_from_axis_anglef3(&qA, 1.0f, 1.0f, 1.0f, HYP_TAU / 4.0f);
	quaternion_set(&qInverse, &qA);
	quaternion_inverse(&qInverse);
	quaternion_multiply(&qA, &qInverse);
	quaternion_normalize(&qA);
	quaternion_identity(&qIdentity);
	test_assert(quaternion_equals(&qA, &qIdentity));
		
	return 0;
}
Esempio n. 9
0
/**
 * @ingroup vector3
 * @brief Reflect a point by the quaternion.  Returns the reflected point. (through origin)
 *
 * \f$self= qT * self * qT\f$
 *
 * @param qT the quaternion
 * @param self the starting point that is rotated by qT
 *
 */
HYPAPI vector3 * vector3_reflect_by_quaternion(vector3 *self, const quaternion *qT)
{
	quaternion q;
	
	quaternion_set(&q, qT);
	quaternion_multiplyv3(&q, self);
	quaternion_multiply(&q, qT);
	
	/* this seems to be necessary */
	quaternion_normalize(&q);
	
	self->x = q.x;
	self->y = q.y;
	self->z = q.z;
	
	return self;
}
Esempio n. 10
0
static char * test_quaternion_multiply_identity()
{
	quaternion qA, qB, q;

	qA.x = 1;
	qA.y = 2;
	qA.z = 3;
	qA.w = 4;

	quaternion_identity(&qB);

	quaternion_set(&q, &qA);
	quaternion_multiply(&q, &qB);

	test_assert(quaternion_equals(&q, &qA));

	return 0;
}
Esempio n. 11
0
/** 
 * @ingroup quaternion
 * @brief This computes the SLERP between two quaternions.  It computes that absolute final position interopolated between start and end. 
 * This function computes shortest arc.
 * If the start and end result in a negative dot product (reversed direction) then the SLERP will reverse direction.
 *
 * @param percent This refers to how far along we want to go toward end.  1.0 means go to the end. 0.0 means start.  1.1 is nonsense. Negative is nonsense.
 * @param start The quaternion representing the starting orientation
 * @param end The quaternion representing the final or ending orientation
 * @param qR The resulting new orientation.
 *
 */
HYPAPI quaternion * quaternion_slerp(const quaternion *start, const quaternion *end, float percent, quaternion *qR)
{
	float dot;
	float f1, f2;
	float theta;
	float s;
	quaternion qneg;
	
	/* if percent is 0, return start */
	if(percent == 0.0f)
	{
		quaternion_set(qR, start);
		return qR;
	}
	
	/* if percent is 1 return end */
	if(percent == 1.0f)
	{
		quaternion_set(qR, end);
		return qR;
	}
	
	/* how parallel are the quaternions (also the dot is the cosine) */
	dot = quaternion_dot_product(start, end);
	
	/* if they are close to parallel, use LERP
	 *	- This avoids div/0
	 *	- At small angles, the slerp and lerp are the same
	 */
	if((1.0f - HYP_ABS(dot)) < HYP_EPSILON)
	{
		quaternion_lerp(start, end, percent, qR);
		return qR;
	}
	
	/* if dot is negative, they are "pointing" away from one another, 
	 * use the shortest arc instead (reverse end and start)
	 * This has the effect of changing the direction of travel around the sphere 
	 * beginning with "end" and going the other way around the sphere
	 */
	if(dot < 0.0f)
	{
		quaternion_set(&qneg, end);
		/*quaternion_conjugate(&qneg);*/
		quaternion_negate(&qneg);
		quaternion_slerp(start, &qneg, percent, qR);
		quaternion_negate(qR);
		/*quaternion_conjugate(qR);*/
		return qR;
	}
	
	/* keep the dot product in the range that acos can handle (shouldn't get here) */
	HYP_CLAMP(dot, -1.0f, 1.0f);
	
	theta = HYP_ACOS(dot);							/* what is the angle between start and end in radians */
	s = HYP_SIN(theta); 							/* cache */
	f1 = HYP_SIN((1.0 - percent) * theta) / s;		/* compute negative */
	f2 = HYP_SIN(percent * theta) / s;				/* compute positive */
	
	/* this expanded form avoids calling quaternion_multiply and quaternion_add */
	qR->w = f1 * start->w + f2 * end->w;
	qR->x = f1 * start->x + f2 * end->x;
	qR->y = f1 * start->y + f2 * end->y;
	qR->z = f1 * start->z + f2 * end->z;
	
	return qR;
}