/* \brief calcualate view matrix */ static void _glhckCameraViewMatrix(glhckCamera *object) { kmMat4 rotation, tmp; kmVec3 upvector; CALL(2, "%p", object); assert(object); /* build rotation for upvector */ kmMat4RotationAxisAngle(&rotation, &(kmVec3){0,0,1}, kmDegreesToRadians(object->object->view.rotation.z)); kmMat4RotationAxisAngle(&tmp, &(kmVec3){0,1,0}, kmDegreesToRadians(object->object->view.rotation.y)); kmMat4Multiply(&rotation, &rotation, &tmp); kmMat4RotationAxisAngle(&tmp, &(kmVec3){1,0,0}, kmDegreesToRadians(object->object->view.rotation.x)); kmMat4Multiply(&rotation, &rotation, &tmp); /* assuming upvector is normalized */ kmVec3Transform(&upvector, &object->view.upVector, &rotation); /* build view matrix */ kmMat4LookAt(&object->view.view, &object->object->view.translation, &object->object->view.target, &upvector); kmMat4Multiply(&object->view.viewProj, &object->view.projection, &object->view.view); glhckFrustumBuild(&object->frustum, &object->view.viewProj); }
///< Create a quaternion from yaw, pitch and roll kmQuaternion* kmQuaternionRotationYawPitchRoll(kmQuaternion* pOut, kmScalar yaw, kmScalar pitch, kmScalar roll) { kmScalar ex, ey, ez; // temp half euler angles kmScalar cr, cp, cy, sr, sp, sy, cpcy, spsy; // temp vars in roll,pitch yaw ex = kmDegreesToRadians(pitch) / 2.0f; // convert to rads and half them ey = kmDegreesToRadians(yaw) / 2.0f; ez = kmDegreesToRadians(roll) / 2.0f; cr = cosf(ex); cp = cosf(ey); cy = cosf(ez); sr = sinf(ex); sp = sinf(ey); sy = sinf(ez); cpcy = cp * cy; spsy = sp * sy; pOut->w = cr * cpcy + sr * spsy; pOut->x = sr * cpcy - cr * spsy; pOut->y = cr * sp * cy + sr * cp * sy; pOut->z = cr * cp * sy - sr * sp * cy; kmQuaternionNormalize(pOut, pOut); return pOut; }
static void dlUpdateMatrix( dlObject *object ) { kmMat4 translation, rotation, scale, temp; CALL("%p", object); /* translation */ kmMat4Translation( &translation, object->translation.x, object->translation.y, object->translation.z ); /* rotation */ kmMat4RotationX( &rotation, kmDegreesToRadians(object->rotation.x) ); kmMat4Multiply( &rotation, &rotation, kmMat4RotationY( &temp, kmDegreesToRadians(object->rotation.y) ) ); kmMat4Multiply( &rotation, &rotation, kmMat4RotationZ( &temp, kmDegreesToRadians(object->rotation.z) ) ); /* scale */ kmMat4Scaling( &scale, object->scale.x, object->scale.y, object->scale.z ); /* build matrix */ kmMat4Multiply( &translation, &translation, &rotation ); kmMat4Multiply( &object->matrix, &translation, &scale ); object->transform_changed = 0; }
/** * Builds a direction vector from input vector. * Input vector is assumed to be rotation vector composed from 3 Euler angle rotations, in degrees. * The forwards vector will be rotated by the input vector * * Code ported from Irrlicht: http://irrlicht.sourceforge.net/ */ kmVec3* kmVec3RotationToDirection(kmVec3* pOut, const kmVec3* pIn, const kmVec3* forwards) { const kmScalar xr = kmDegreesToRadians(pIn->x); const kmScalar yr = kmDegreesToRadians(pIn->y); const kmScalar zr = kmDegreesToRadians(pIn->z); const kmScalar cr = cos(xr), sr = sin(xr); const kmScalar cp = cos(yr), sp = sin(yr); const kmScalar cy = cos(zr), sy = sin(zr); const kmScalar srsp = sr*sp; const kmScalar crsp = cr*sp; const kmScalar pseudoMatrix[] = { (cp*cy), (cp*sy), (-sp), (srsp*cy-cr*sy), (srsp*sy+cr*cy), (sr*cp), (crsp*cy+sr*sy), (crsp*sy-sr*cy), (cr*cp) }; pOut->x = forwards->x * pseudoMatrix[0] + forwards->y * pseudoMatrix[3] + forwards->z * pseudoMatrix[6]; pOut->y = forwards->x * pseudoMatrix[1] + forwards->y * pseudoMatrix[4] + forwards->z * pseudoMatrix[7]; pOut->z = forwards->x * pseudoMatrix[2] + forwards->y * pseudoMatrix[5] + forwards->z * pseudoMatrix[8]; return pOut; }
/** * Creates a perspective projection matrix in the * same way as gluPerspective */ kmMat4* const kmMat4PerspectiveProjection(kmMat4* pOut, kmScalar fovY, kmScalar aspect, kmScalar zNear, kmScalar zFar) { kmScalar r = kmDegreesToRadians(fovY / 2); kmScalar deltaZ = zFar - zNear; kmScalar s = sin(r); kmScalar cotangent = 0; if (deltaZ == 0 || s == 0 || aspect == 0) { return NULL; } //cos(r) / sin(r) = cot(r) cotangent = cos(r) / s; kmMat4Identity(pOut); pOut->mat[0] = cotangent / aspect; pOut->mat[5] = cotangent; pOut->mat[10] = -(zFar + zNear) / deltaZ; pOut->mat[11] = -1; pOut->mat[14] = -2 * zNear * zFar / deltaZ; pOut->mat[15] = 0; return pOut; }
static cxBool cxRotateXMLReadAttr(cxAny xmlAction,cxAny mAction, xmlTextReaderPtr reader) { cxActionXMLReadAttr(xmlAction, mAction, reader); cxRotate this = mAction; cxChar *sx = cxXMLAttr("cxRotate.x"); cxChar *sy = cxXMLAttr("cxRotate.y"); cxChar *sz = cxXMLAttr("cxRotate.z"); if(sx != NULL){ this->raxis = cxVec3fv(1.0f, 0.0f, 0.0f); this->newRadians = kmDegreesToRadians(atof(sx)); }else if(sy != NULL){ this->raxis = cxVec3fv(0.0f, 1.0f, 0.0f); this->newRadians = kmDegreesToRadians(atof(sy)); }else if(sz != NULL){ this->raxis = cxVec3fv(0.0f, 0.0f, 1.0f); this->newRadians = kmDegreesToRadians(atof(sz)); } xmlFree(sx); xmlFree(sy); xmlFree(sz); return true; }
void kmGLRotatef(float angle, float x, float y, float z) { kmVec3 axis; kmMat4 rotation; //Create an axis vector kmVec3Fill(&axis, x, y, z); //Create a rotation matrix using the axis and the angle kmMat4RotationAxisAngle(&rotation, &axis, kmDegreesToRadians(angle)); //Multiply the rotation matrix by the current matrix kmMat4Multiply(current_stack->top, current_stack->top, &rotation); }
void kmGLRotatef(float angle, float x, float y, float z) { km_mat4_stack_context *current_context = (km_mat4_stack_context *)pthread_getspecific(current_context_key); kmVec3 axis; kmMat4 rotation; /*Create an axis vector*/ kmVec3Fill(&axis, x, y, z); /*Create a rotation matrix using the axis and the angle*/ kmMat4RotationAxisAngle(&rotation, &axis, kmDegreesToRadians(angle)); /*Multiply the rotation matrix by the current matrix*/ kmMat4Multiply(current_context->current_stack->top, current_context->current_stack->top, &rotation); }
/** * Rotates the point anticlockwise around a center * by an amount of degrees. * * Code ported from Irrlicht: http://irrlicht.sourceforge.net/ */ kmVec2* kmVec2RotateBy(kmVec2* pOut, const kmVec2* pIn, const kmScalar degrees, const kmVec2* center) { kmScalar x, y; const kmScalar radians = kmDegreesToRadians(degrees); const kmScalar cs = cosf(radians), sn = sinf(radians); pOut->x = pIn->x - center->x; pOut->y = pIn->y - center->y; x = pOut->x * cs - pOut->y * sn; y = pOut->x * sn + pOut->y * cs; pOut->x = x + center->x; pOut->y = y + center->y; return pOut; }
Radians::Radians(const Degrees &rhs) { value_ = kmDegreesToRadians(rhs.value_); }
Radians to_radians(const Degrees& degrees) { return Radians(kmDegreesToRadians(degrees.value_)); }
///< Creates a quaternion from a rotation matrix kmQuaternion* kmQuaternionRotationMatrix(kmQuaternion* pOut, const kmMat3* pIn) { /* Note: The OpenGL matrices are transposed from the description below taken from the Matrix and Quaternion FAQ if ( mat[0] > mat[5] && mat[0] > mat[10] ) { // Column 0: S = sqrt( 1.0 + mat[0] - mat[5] - mat[10] ) * 2; X = 0.25 * S; Y = (mat[4] + mat[1] ) / S; Z = (mat[2] + mat[8] ) / S; W = (mat[9] - mat[6] ) / S; } else if ( mat[5] > mat[10] ) { // Column 1: S = sqrt( 1.0 + mat[5] - mat[0] - mat[10] ) * 2; X = (mat[4] + mat[1] ) / S; Y = 0.25 * S; Z = (mat[9] + mat[6] ) / S; W = (mat[2] - mat[8] ) / S; } else { // Column 2: S = sqrt( 1.0 + mat[10] - mat[0] - mat[5] ) * 2; X = (mat[2] + mat[8] ) / S; Y = (mat[9] + mat[6] ) / S; Z = 0.25 * S; W = (mat[4] - mat[1] ) / S; } */ float x, y, z, w; float *pMatrix = NULL; float m4x4[16] = {0}; float scale = 0.0f; float diagonal = 0.0f; if(!pIn) { return NULL; } /* 0 3 6 1 4 7 2 5 8 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15*/ m4x4[0] = pIn->mat[0]; m4x4[1] = pIn->mat[3]; m4x4[2] = pIn->mat[6]; m4x4[4] = pIn->mat[1]; m4x4[5] = pIn->mat[4]; m4x4[6] = pIn->mat[7]; m4x4[8] = pIn->mat[2]; m4x4[9] = pIn->mat[5]; m4x4[10] = pIn->mat[8]; m4x4[15] = 1; pMatrix = &m4x4[0]; diagonal = pMatrix[0] + pMatrix[5] + pMatrix[10] + 1; if(diagonal > kmEpsilon) { // Calculate the scale of the diagonal scale = (float)sqrt(diagonal ) * 2; // Calculate the x, y, x and w of the quaternion through the respective equation x = ( pMatrix[9] - pMatrix[6] ) / scale; y = ( pMatrix[2] - pMatrix[8] ) / scale; z = ( pMatrix[4] - pMatrix[1] ) / scale; w = 0.25f * scale; } else { // If the first element of the diagonal is the greatest value if ( pMatrix[0] > pMatrix[5] && pMatrix[0] > pMatrix[10] ) { // Find the scale according to the first element, and double that value scale = (float)sqrt( 1.0f + pMatrix[0] - pMatrix[5] - pMatrix[10] ) * 2.0f; // Calculate the x, y, x and w of the quaternion through the respective equation x = 0.25f * scale; y = (pMatrix[4] + pMatrix[1] ) / scale; z = (pMatrix[2] + pMatrix[8] ) / scale; w = (pMatrix[9] - pMatrix[6] ) / scale; } // Else if the second element of the diagonal is the greatest value else if (pMatrix[5] > pMatrix[10]) { // Find the scale according to the second element, and double that value scale = (float)sqrt( 1.0f + pMatrix[5] - pMatrix[0] - pMatrix[10] ) * 2.0f; // Calculate the x, y, x and w of the quaternion through the respective equation x = (pMatrix[4] + pMatrix[1] ) / scale; y = 0.25f * scale; z = (pMatrix[9] + pMatrix[6] ) / scale; w = (pMatrix[2] - pMatrix[8] ) / scale; } // Else the third element of the diagonal is the greatest value else { // Find the scale according to the third element, and double that value scale = (float)sqrt( 1.0f + pMatrix[10] - pMatrix[0] - pMatrix[5] ) * 2.0f; // Calculate the x, y, x and w of the quaternion through the respective equation x = (pMatrix[2] + pMatrix[8] ) / scale; y = (pMatrix[9] + pMatrix[6] ) / scale; z = 0.25f * scale; w = (pMatrix[4] - pMatrix[1] ) / scale; } } pOut->x = x; pOut->y = y; pOut->z = z; pOut->w = w; return pOut; #if 0 kmScalar T = pIn->mat[0] + pIn->mat[5] + pIn->mat[10]; if (T > kmEpsilon) { //If the trace is greater than zero we always use this calculation: /* S = sqrt(T) * 2; X = ( mat[9] - mat[6] ) / S; Y = ( mat[2] - mat[8] ) / S; Z = ( mat[4] - mat[1] ) / S; W = 0.25 * S;*/ /* kmScalar s = sqrtf(T) * 2; pOut->x = (pIn->mat[9] - pIn->mat[6]) / s; pOut->y = (pIn->mat[8] - pIn->mat[2]) / s; pOut->z = (pIn->mat[1] - pIn->mat[4]) / s; pOut->w = 0.25f * s; kmQuaternionNormalize(pOut, pOut); return pOut; } //Otherwise the calculation depends on which major diagonal element has the greatest value. if (pIn->mat[0] > pIn->mat[5] && pIn->mat[0] > pIn->mat[10]) { kmScalar s = sqrtf(1 + pIn->mat[0] - pIn->mat[5] - pIn->mat[10]) * 2; pOut->x = 0.25f * s; pOut->y = (pIn->mat[1] + pIn->mat[4]) / s; pOut->z = (pIn->mat[8] + pIn->mat[2]) / s; pOut->w = (pIn->mat[9] - pIn->mat[6]) / s; } else if (pIn->mat[5] > pIn->mat[10]) { kmScalar s = sqrtf(1 + pIn->mat[5] - pIn->mat[0] - pIn->mat[10]) * 2; pOut->x = (pIn->mat[1] + pIn->mat[4]) / s; pOut->y = 0.25f * s; pOut->z = (pIn->mat[9] + pIn->mat[6]) / s; pOut->w = (pIn->mat[8] - pIn->mat[2]) / s; } else { kmScalar s = sqrt(1.0f + pIn->mat[10] - pIn->mat[0] - pIn->mat[5]) * 2.0f; pOut->x = (pIn->mat[8] + pIn->mat[2] ) / s; pOut->y = (pIn->mat[6] + pIn->mat[9] ) / s; pOut->z = 0.25f * s; pOut->w = (pIn->mat[1] - pIn->mat[4] ) / s; } kmQuaternionNormalize(pOut, pOut); return pOut;*/ #endif // 0 } ///< Create a quaternion from yaw, pitch and roll kmQuaternion* kmQuaternionRotationYawPitchRoll(kmQuaternion* pOut, kmScalar yaw, kmScalar pitch, kmScalar roll) { kmScalar ex, ey, ez; // temp half euler angles kmScalar cr, cp, cy, sr, sp, sy, cpcy, spsy; // temp vars in roll,pitch yaw ex = kmDegreesToRadians(pitch) / 2.0f; // convert to rads and half them ey = kmDegreesToRadians(yaw) / 2.0f; ez = kmDegreesToRadians(roll) / 2.0f; cr = cosf(ex); cp = cosf(ey); cy = cosf(ez); sr = sinf(ex); sp = sinf(ey); sy = sinf(ez); cpcy = cp * cy; spsy = sp * sy; pOut->w = cr * cpcy + sr * spsy; pOut->x = sr * cpcy - cr * spsy; pOut->y = cr * sp * cy + sr * cp * sy; pOut->z = cr * cp * sy - sr * sp * cy; kmQuaternionNormalize(pOut, pOut); return pOut; }