void Camera::update_following(double dt) { ActorPtr following_actor = following_actor_.lock(); if(following_actor) { kmQuaternion actor_rotation = following_actor->absolute_rotation(); kmVec3 actor_position = following_actor->absolute_position(); kmVec3 actor_forward; kmQuaternionGetForwardVec3RH(&actor_forward, &actor_rotation); kmQuaternion initial_rotation; kmQuaternionAssign(&initial_rotation, &rotation_); float t = ((following_lag_ == 0) ? 1.0 : dt * (1.0 / following_lag_)); kmQuaternionSlerp(&rotation_, &initial_rotation, &actor_rotation, t); kmVec3 rotated_offset; kmQuaternionMultiplyVec3(&rotated_offset, &rotation_, &following_offset_); //kmMat4RotationQuaternion(&new_rotation_matrix, &rotation_); //kmVec3MultiplyMat4(&rotated_offset, &following_offset_, &new_rotation_matrix); kmVec3Add(&position_, &rotated_offset, &actor_position); update_from_parent(); } else { //The actor was destroyed, so reset following_actor_ = ActorRef(); } }
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; }