OpenGothic
Open source reimplementation of Gothic I and II
Loading...
Searching...
No Matches
animmath.cpp
Go to the documentation of this file.
1#include "animmath.h"
2
3#include <cmath>
4
5static float mix(float x,float y,float a){
6 return x+(y-x)*a;
7 }
8
9zenkit::Quat slerp(const zenkit::Quat& x, const zenkit::Quat& y, float a) {
10 zenkit::Quat z = y;
11
12 float cosTheta = x.x*y.x +x.y*y.y + x.z*y.z + x.w*y.w;
13 // If cosTheta < 0, the interpolation will take the long way around the sphere.
14 // To fix this, one quat must be negated.
15 if(cosTheta < 0.f) {
16 z.x = -y.x;
17 z.y = -y.y;
18 z.z = -y.z;
19 z.w = -y.w;
20 cosTheta = -cosTheta;
21 }
22
23 // Perform a linear interpolation when cosTheta is close to 1 to avoid side effect of sin(angle) becoming a zero denominator
24 if(cosTheta > 1.f - std::numeric_limits<float>::epsilon()) {
25 // Linear interpolation
26 return zenkit::Quat(mix(x.w, z.w, a),
27 mix(x.x, z.x, a),
28 mix(x.y, z.y, a),
29 mix(x.z, z.z, a));
30 }
31
32 // Essential Mathematics, page 467
33 float angle = std::acos(cosTheta);
34 float kx = std::sin((1.f - a) * angle);
35 float kz = std::sin(a * angle);
36 float div = std::sin(angle);
37 return zenkit::Quat((x.w*kx + z.w*kz)/div,
38 (x.x*kx + z.x*kz)/div,
39 (x.y*kx + z.y*kz)/div,
40 (x.z*kx + z.z*kz)/div);
41 // return (sin((1.f - a) * angle) * x + sin(a * angle) * z) / sin(angle);
42 }
43
44zenkit::AnimationSample mix(const zenkit::AnimationSample& x, const zenkit::AnimationSample& y, float a) {
45 zenkit::AnimationSample r {};
46
47 r.rotation = slerp(x.rotation,y.rotation,a);
48 r.position.x = mix(x.position.x,y.position.x,a);
49 r.position.y = mix(x.position.y,y.position.y,a);
50 r.position.z = mix(x.position.z,y.position.z,a);
51
52 return r;
53}
54
55static Tempest::Matrix4x4 mkMatrix(float x,float y,float z,float w,
56 float px,float py,float pz) {
57 float m[4][4]={};
58
59 m[0][0] = w * w + x * x - y * y - z * z;
60 m[0][1] = 2.0f * (x * y - w * z);
61 m[0][2] = 2.0f * (x * z + w * y);
62 m[1][0] = 2.0f * (x * y + w * z);
63 m[1][1] = w * w - x * x + y * y - z * z;
64 m[1][2] = 2.0f * (y * z - w * x);
65 m[2][0] = 2.0f * (x * z - w * y);
66 m[2][1] = 2.0f * (y * z + w * x);
67 m[2][2] = w * w - x * x - y * y + z * z;
68 m[3][0] = px;
69 m[3][1] = py;
70 m[3][2] = pz;
71 m[3][3] = 1;
72
73 return Tempest::Matrix4x4(reinterpret_cast<float*>(m));
74 }
75
76Tempest::Matrix4x4 mkMatrix(const zenkit::AnimationSample& s) {
77 return mkMatrix(s.rotation.x,s.rotation.y,s.rotation.z,s.rotation.w,
78 s.position.x,s.position.y,s.position.z);
79 }
static Tempest::Matrix4x4 mkMatrix(float x, float y, float z, float w, float px, float py, float pz)
Definition animmath.cpp:55
static float mix(float x, float y, float a)
Definition animmath.cpp:5
zenkit::Quat slerp(const zenkit::Quat &x, const zenkit::Quat &y, float a)
Definition animmath.cpp:9