/** * Build a rotation matrix from an axis and an angle. Result is stored in pOut. * pOut is returned. */ kmMat4* kmMat4RotationAxisAngle(kmMat4* pOut, const kmVec3* axis, kmScalar radians) { kmQuaternion quat; kmQuaternionRotationAxisAngle(&quat, axis, radians); kmMat4RotationQuaternion(pOut, &quat); return pOut; }
uint8_t lite3d_scene_node_update(lite3d_scene_node *node) { uint8_t updated = LITE3D_FALSE; SDL_assert(node); if (node->recalc) { kmMat4 transMat; kmMat4 scaleMat; kmQuaternionNormalize(&node->rotation, &node->rotation); kmMat4RotationQuaternion(&node->localView, &node->rotation); kmMat4Translation(&transMat, node->isCamera ? -node->position.x : node->position.x, node->isCamera ? -node->position.y : node->position.y, node->isCamera ? -node->position.z : node->position.z); if (node->scale.x != 1.0f || node->scale.y != 1.0f || node->scale.z != 1.0f) { kmMat4Scaling(&scaleMat, node->scale.x, node->scale.y, node->scale.z); kmMat4Multiply(&transMat, &transMat, &scaleMat); } if (node->rotationCentered) kmMat4Multiply(&node->localView, &transMat, &node->localView); else kmMat4Multiply(&node->localView, &node->localView, &transMat); if (node->baseNode) { kmMat4Multiply(&node->worldView, &node->baseNode->worldView, &node->localView); } else { node->worldView = node->localView; } kmMat3NormalMatrix(&node->normalModel, &node->worldView); node->recalc = LITE3D_FALSE; node->invalidated = LITE3D_TRUE; updated = LITE3D_TRUE; } return updated; }
void sls_trackball_set(slsTrackball *t, kmVec2 p1, kmVec2 p2) { sls_trackball_calc_quat(&t->rotation, t->radius, t->rotation_speed, &p1, &p2); kmMat4RotationQuaternion(&t->rotation_mat, &t->rotation); }
void dlAdvanceAnimTick( dlAnimTick *animTick, float pTime ) { dlAnim *anim; dlNodeAnim *node; dlAnimTickOldNode *oldNode; unsigned int frame, nextFrame; dlVectorKey *vkey, *nextvKey; dlQuatKey *qkey, *nextqKey; kmVec3 presentTranslation, presentScaling; kmQuaternion presentRotation; float diffTime, factor; float ticksPerSecond; CALL("%p, %f", animTick, pTime); /* get dlAnim */ anim = animTick->anim; ticksPerSecond = anim->ticksPerSecond != 0.0 ? anim->ticksPerSecond : 25.0f; pTime *= ticksPerSecond; /* map into anim's duration */ float time = 0.0f; if( anim->duration > 0.0) time = fmod( pTime, anim->duration); /* calculate the transformations for each animation channel */ node = anim->node; oldNode = animTick->oldNode; while(node && oldNode) { /* ******** Position **** */ presentTranslation.x = 0; presentTranslation.y = 0; presentTranslation.z = 0; if(node->translation) { frame = (time >= animTick->oldTime) ? oldNode->translationTime : 0; while( frame < node->num_translation - 1) { if( time < oldNode->translation[frame+1]->time) break; ++frame; } /* interpolate between this frame's value and next frame's value */ nextFrame = (frame + 1) % node->num_translation; vkey = oldNode->translation[frame]; nextvKey = oldNode->translation[nextFrame]; diffTime = nextvKey->time - vkey->time; #if 1 if( diffTime < 0.0) diffTime += anim->duration; if( diffTime > 0) { factor = (time - vkey->time) / diffTime; presentTranslation.x = vkey->value.x + (nextvKey->value.x - vkey->value.x) * factor; presentTranslation.y = vkey->value.y + (nextvKey->value.y - vkey->value.y) * factor; presentTranslation.z = vkey->value.z + (nextvKey->value.z - vkey->value.z) * factor; } else { presentTranslation = vkey->value; } #else presentTranslation = vkey->value; #endif oldNode->translationTime = frame; } /* ******** Rotation ******** */ presentRotation.w = 0; presentRotation.x = 0; presentRotation.y = 0; presentRotation.z = 0; if(node->rotation) { frame = (time >= animTick->oldTime) ? oldNode->rotationTime : 0; while( frame < node->num_rotation - 1) { if( time < oldNode->rotation[frame+1]->time) break; ++frame; } /* interpolate between this frame's value and next frame's value */ nextFrame = (frame + 1) % node->num_rotation; qkey = oldNode->rotation[frame]; nextqKey = oldNode->rotation[nextFrame]; diffTime = nextqKey->time - qkey->time; #if 1 if( diffTime < 0.0f) diffTime += anim->duration; if( diffTime > 0.0f) { factor = (time - qkey->time) / diffTime; kmQuaternionSlerp( &presentRotation, &qkey->value, &nextqKey->value, factor); } else { presentRotation = qkey->value; } #else presentRotation = qkey->value; #endif oldNode->rotationTime = frame; } /* ******** Scaling ********** */ presentScaling.x = 1; presentScaling.y = 1; presentScaling.z = 1; if(node->scaling) { frame = (time >= animTick->oldTime) ? oldNode->scalingTime : 0; while( frame < node->num_scaling - 1) { if( time < oldNode->scaling[frame+1]->time) break; ++frame; } /* TODO: (thom) interpolation maybe? This time maybe even logarithmic, not linear */ presentScaling = oldNode->scaling[frame]->value; oldNode->scalingTime = frame; } // build a transformation matrix from it kmMat4 *mat = &node->bone->relativeMatrix; kmMat4RotationQuaternion( mat, &presentRotation ); mat->mat[0] *= presentScaling.x; mat->mat[4] *= presentScaling.x; mat->mat[8] *= presentScaling.x; mat->mat[1] *= presentScaling.y; mat->mat[5] *= presentScaling.y; mat->mat[9] *= presentScaling.y; mat->mat[2] *= presentScaling.z; mat->mat[6] *= presentScaling.z; mat->mat[10] *= presentScaling.z; mat->mat[3] = presentTranslation.x; mat->mat[7] = presentTranslation.y; mat->mat[11] = presentTranslation.z; node = node->next; oldNode = oldNode->next; } /* old time */ animTick->oldTime = time; }