From 83f995ed225282775a497a689fd5a3e7c9325383 Mon Sep 17 00:00:00 2001 From: Trinton Bullard Date: Thu, 8 Dec 2016 20:35:03 -0700 Subject: [PATCH] Working on slerp --- HandmadeMath.h | 25 +++++++++- test/.vs/HandmadeMath/v14/.suo | Bin 0 -> 6144 bytes test/HandmadeMath.cpp | 86 +++++++++++++++++++++++++++++++++ test/build.bat | 1 + test/vc140.pdb | Bin 0 -> 86016 bytes 5 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 test/.vs/HandmadeMath/v14/.suo create mode 100644 test/build.bat create mode 100644 test/vc140.pdb diff --git a/HandmadeMath.h b/HandmadeMath.h index fdd53fb..4e1d1ff 100644 --- a/HandmadeMath.h +++ b/HandmadeMath.h @@ -473,7 +473,9 @@ HMMDEF hmm_quaternion HMM_QuaternionV4(hmm_vec4 Vector); HMMDEF hmm_quaternion HMM_AddQuat(hmm_quaternion QuaternionOne, hmm_quaternion QuaternionTwo); HMMDEF hmm_quaternion HMM_SubQuat(hmm_quaternion QuaternionOne, hmm_quaternion QuaternionTwo); HMMDEF hmm_quaternion HMM_MulQuat(hmm_quaternion QuaternionOne, hmm_quaternion QuaternionTwo); -HMMDef hmm_quaternion HMM_DivQuat(hmm_quaternion QuaternionOne, hmm_quaternion QuaternionTwo); +HMMDEF hmm_quaternion HMM_DivQuat(hmm_quaternion QuaternionOne, hmm_quaternion QuaternionTwo); +HMMDEF float HMM_DotQuat(hmm_quaternion QuaternionOne, hmm_quaternion QuaternionTwo); +//HMMDef hmm_quaternion HMM_Slerp(hmm_quaternion QuaternionOne, hmm_quaternion QuaternionTwo, float time); //TODO(Trent): Don't forget the line numbers! #ifdef __cplusplus @@ -1520,8 +1522,29 @@ HMM_DivQuat(hmm_quaternion QuaternionOne, hmm_quaternion QuaternionTwo) Result.Y = QuaternionOne.Y * (1/QuaternionTwo.Y); Result.Z = QuaternionOne.Z * (1/QuaternionTwo.Z); Result.W = QuaternionOne.W * (1/QuaternionTwo.W); + + return(Result); } +HINLINE float +HMM_DotQuat(hmm_quaternion QuaternionOne, hmm_quaternion QuaternionTwo) +{ + float Result = 0.00f; + + Result = (QuaternionOne.X * QuaternionTwo.X) + (QuaternionOne.Y * QuaternionTwo.Y) + (QuaternionOne.Z * QuaternionTwo.Z) + (QuaternionOne.W * QuaternionTwo.W); + + return(Result); +} + +/**HMM_Slerp(hmm_quaternion QuaternionOne, hmm_quaternion QuaternionTwo, float time) +{ + hmm_quaternion Result = {0}; + + float Theta = HMM_DotQuat(QuaternionOne, QuaternionTwo); + + return(Result); +}**/ + #ifdef HANDMADE_MATH_CPP_MODE HMMDEF float diff --git a/test/.vs/HandmadeMath/v14/.suo b/test/.vs/HandmadeMath/v14/.suo new file mode 100644 index 0000000000000000000000000000000000000000..2445682386318a16357d17229f9d33f7d1f56f64 GIT binary patch literal 6144 zcmca`Uhu)fjZzO8(10BSGsD0CoD6J8;*1Oo3`{V-00RRH0|Ns{?BDwkj#+G0C7bbLncEC zLn=cNgC0XLLq08gEK=uLn%0{Kt|XxFfoGi0myC; z28j`aL3%*yTo^nUf*4X6k{MFLX1Xw>GL$eRGGsF3FcdR{F=R5NGL(Z9;=meE|AT^) zSo=YFRsm`rC@lVhG@@Zpo(5r%FpLJVNAd6q0ea^D2|qr7^FJ2@1H%DOf@NTU<~)k> zKO-ncK=l-eh9+yg6v+Nzl>fp02L&gw{zuOLAUz-qD!W1D04T46Fh~r9VQh}kx*Zf8 z!w!Su7luJ~5-1&j@)Af46z8D28pH4O8kl}w&n`;X$1IZAF zg*}KSRXZqO!!UaO2Z@8s9L2*o1V(!PCpEudQ;(cFu*uU}j1v1nJybig63|S!I{KI4Lf< z>@~>m$nFENL1Hkx<eNno|A5+B00$f$C05{Px!Lv(cnY zy*}Gn9+}C!VqPbR28c3yL9qk5@xPAInZb%72HKBIXDDJwWXNSuU~mJEprkSsGbk`< zFjO#DFqkoDGQ=?WGGsC&gU6hT8S)v@z$0IvQI=wcQieo^90mn&`=gX01w8Jfz+lK= z!l1`sz!1X_#^B5l1J(=52gM9U49N^J3}s*u$aoN_4VB6e!;s2Q!H~)j&ydWJ&ydTI z3mrcKwQh14{9R>Ntjt?b68E*`%hm;9#h~y3 0 ? (x) : -(x)) +#endif + +#define GB_MATH_TAU_OVER_2 3.14159265358979323846264338327950288f +#define GB_MATH_TAU_OVER_4 1.570796326794896619231321691639751442f +#define GB_MATH_TAU_OVER_8 0.785398163397448309615660845819875721f + +static float gb_arctan(float a); +static float gb_arctan2(float y, float x); + +float gb_arccos(float a) { return gb_arctan2(HMM_SquareRootF((1.0f + a) * (1.0 - a)), a); } + +float +gb_arctan(float a) +{ + float u = a*a; + float u2 = u*u; + float u3 = u2*u; + float u4 = u3*u; + float f = 1.0f + 0.33288950512027f*u - 0.08467922817644f*u2 + 0.03252232640125f*u3 - 0.00749305860992f*u4; + return a / f; +} + +float +gb_arctan2(float y, float x) +{ + if (gb_abs(x) > gb_abs(y)) { + float a = gb_arctan(y / x); + if (x > 0.0f) + return a; + else + return y > 0.0f ? a + GB_MATH_TAU_OVER_2 : a - GB_MATH_TAU_OVER_2; + } + else { + float a = gb_arctan(x / y); + if (x > 0.0f) + return y > 0.0f ? GB_MATH_TAU_OVER_4 - a : -GB_MATH_TAU_OVER_4 - a; + else + return y > 0.0f ? GB_MATH_TAU_OVER_4 + a : -GB_MATH_TAU_OVER_4 + a; + } +} + +int main() { + + hmm_quaternion q1 = { 0,1,0 }; + hmm_quaternion q2 = { 0,0,0 }; + hmm_quaternion Result = { 0 }; + float time = 0.5f; + + hmm_quaternion x, y, z; + float cos_theta, angle; + float s1, s2, is; + + z = q2; + cos_theta = HMM_DotQuat(q1, q2); + + angle = gb_arccos(cos_theta); + + s1 = HMM_SinF(1.0f - time*angle); + s2 = HMM_SinF(time*angle); + is = 1.0f / HMM_SinF(angle); + + x.X = z.X * s1; + x.Y = z.Y * s1; + x.Z = z.Z * s1; + x.W = z.W * s1; + + y.X = z.X * s2; + y.Y = z.Y * s2; + y.Z = z.Z * s2; + y.W = z.W * s2; + + Result.X = x.X + y.X; + Result.Y = x.Y + y.Y; + Result.Z = x.Z + y.Z; + Result.W = x.W + y.W; + + Result.X = Result.X * is; + Result.Y = Result.Y * is; + Result.Z = Result.Z * is; + Result.W = Result.W * is; + +return 0; +} \ No newline at end of file diff --git a/test/build.bat b/test/build.bat new file mode 100644 index 0000000..5200276 --- /dev/null +++ b/test/build.bat @@ -0,0 +1 @@ +cl -Zi HandmadeMath.cpp \ No newline at end of file diff --git a/test/vc140.pdb b/test/vc140.pdb new file mode 100644 index 0000000000000000000000000000000000000000..7fe4e7b773554ccf68acf759b3f72855eb163eb0 GIT binary patch literal 86016 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 literal 0 HcmV?d00001