Skip to content

Instantly share code, notes, and snippets.

@d3x0r
Last active July 1, 2020 21:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save d3x0r/386f1320f0ee43a39a0983347362439e to your computer and use it in GitHub Desktop.
Save d3x0r/386f1320f0ee43a39a0983347362439e to your computer and use it in GitHub Desktop.
Twist JS Function combined
// this = { x: xAngle, y:yAngle, z:zAngle, nL: |x|+|y|+|z|, nR:sqrt( xx+yy+zz ) }
// nR = normRectangular
// nL = normLinear
function twistQuaternion(theta) {
// function getBasis() { // computes xyz basis vectors (matrix)
// this is angle-angle-angle log-quaternion
const q = this;
if( !this.nL ) { // no rotation
/// welll... at least bypass all of this and go down to rotate right/forward....
return {forward:{x:0,y:0,z:1}, right:{x:1,y:0,z:0}, up:{x:0,y:1,z:0}, origin:{x:0,y:0,z:0 }};
}
const sinQ = Math.sin( this.nL ); // sin/cos are the function of exp()
const cosQ = Math.cos( this.nL ); // sin/cos are the function of exp()
const nst = sinQ/this.nR;
const qx = q.x * nst; // normalizes the imaginary parts
const qy = q.y * nst; // set the sin of their composite angle as their total
const qz = q.z * nst; // output = 1(unit vector) * sin in x,y,z parts.
// V = v eHat_r + r dTh/dT * eHat_t + r * dphi/Dt * sinT * eHat_phi
const basis = { forward:null
, right:null
, up:null
, origin: { x:0, y:0, z:0 } };
{ // this is the math-expanded version of the below; with primary terms instead of meta-constants
basis.up = { x : 2 * (sinQ / (q.nR * q.nR )) * ( q.y * q.x * sinQ - cosQ * q.z * q.nR )
, y : 1 - 2 * sinQ*(sinQ / (q.nR * q.nR )) * ( q.z * q.z + q.x * q.x )
, z : 2 * (sinQ / (q.nR * q.nR )) * ( q.z * q.y * sinQ + cosQ * q.x * q.nR ) };
basis.right = { x : 1 - 2 * sinQ *( sinQ / (q.nR * q.nR )) * ( q.y * q.y + q.z * q.z )
, y : 2 * ( sinQ / (q.nR * q.nR )) * ( q.y * q.x * sinQ - cosQ * q.z *q.nR )
, z : 2 * ( sinQ / (q.nR * q.nR )) * ( q.x * q.z * sinQ - cosQ * q.y *q.nR ) };
basis.forward = { x : 2 *(sinQ / (q.nR *q.nR)) * ( q.x * q.z * sinQ + cosQ * q.y * q.nR )
, y : 2 *(sinQ / (q.nR *q.nR)) * ( q.z * q.y * sinQ - cosQ * q.x * q.nR )
, z : 1 - 2 * sinQ *(sinQ / (q.nR *q.nR)) * ( q.x * q.x + q.y * q.y ) };
}
/*
// s = sinQ, qw = cosQ : renamed
{
const tx = 2 * ( -qz );
const tz = 2 * (qx );
basis.up = { x : qw * tx + qy * tz
, y : 1 + qz * tx - tz * qx
, z : qw * tz - tx * qy };
}
{
// for apply, this is cross(q,some point)
const ty = 2 * (qz);
const tz = 2 * (-qy);
basis.right = { x : 1 + ( qy * tz - ty * qz )
, y : qw * ty + ( - tz * qx )
, z : qw * tz + ( qx * ty ) };
}
{
// direct calculation of 'z' rotated by the vector.
const tx = 2 * ( qy );
const ty = 2 * (-qx);
basis.forward = { x : qw * tx + ( - ty * qz )
, y : qw * ty + ( qz * tx )
, z : 1 + 0 + ( qx * ty - tx * qy ) };
}
*/
// return basis; } // This routine would end here...
// This multiplies the forward and right axis by some sin/cos of theta to rotate them around the Y.
// forward/right transform.
const dsin = Math.sin(theta);
const dcos = Math.cos(theta);
const v1 = { x:basis.right.x*dcos, y:basis.right.y*dcos, z:basis.right.z*dcos};
const v2 = { x:basis.forward.x*dsin, y:basis.forward.y*dsin, z: basis.forward.z*dsin };
basis.right.x = v1.x - v2.x;
basis.right.y = v1.y - v2.y;
basis.right.z = v1.z - v2.z;
const v3 = { x:basis.forward.x*dcos, y:basis.forward.y*dcos, z: basis.forward.z*dcos };
const v4 = { x:basis.right.x*dsin, y:basis.right.y*dsin, z:basis.right.z*dsin};
basis.forward.x = v3.x + v4.x;
basis.forward.y = v3.y + v4.y;
basis.forward.z = v3.z + v4.z;
// the above rotation is used only for substitution reference.
// ----------- This is the partial work for the following....
// ([t]otal (step) ( [r]ight, [u]p, [f]orward )
// t0f -> total step 0, forward
//const t0r = basis.right.x;
//const t1r = v1.x - v2.x;
//const t2r = basis.right.x*dcos - basis.forward.x*dsin;
const t3r = dcos - 2 * sinT *( sinT / (q.nR * q.nR )) * ( q.y * q.y + q.z * q.z ) * dcos
-( 2 *(sinT / (q.nR *q.nR)) * ( q.x * q.z * sinT + cosT * q.y * q.nR ) ) * dsin
//const t0u = basis.up.y;
const t1u = 1 - 2 * sinT*(sinT / (q.nR * q.nR )) * ( q.z * q.z + q.x * q.x );
//const t0f = basis.forward.z;
//const t1f = v3.z + v4.z;
//const t2f = basis.forward.z*dcos + basis.right.z*dsin;
const t3f = dcos - 2 * sinT *(sinT / (q.nR *q.nR)) * ( q.x * q.x + q.y * q.y ) * dcos
+( 2 * ( sinT / (q.nR * q.nR )) * ( q.x * q.z * sinT - cosT * q.y *q.nR ) ) * dsin
// partial (sum of t3r, t3f, t1u )
//const t1 = ( 2 - 2 * sinT *( sinT / (q.nR * q.nR )) * ( q.y * q.y + q.z * q.z - q.x * q.x - q.y * q.y ) * dcos
// - ( ( 2 *( sinT / (q.nR * q.nR )) * ( q.x * q.z * sinT + cosT * q.y * q.nR + q.x * q.z * sinT - cosT * q.y *q.nR ) ) ) * dsin
// + ( 1 - 2 * sinT*(sinT / (q.nR * q.nR )) * ( q.z * q.z + q.x * q.x ) );
// (x-1) / 2... this part subtracted the 1, and divided by 2... and remove +q.y-q.y
const t1 = ( 1 - sinT *( sinT / (q.nR * q.nR )) * ( q.z * q.z - q.x * q.x ) ) * dcos
- ( sinT / (q.nR * q.nR )) * ( q.x * q.z * sinT + q.x * q.z * cosT ) * dsin
+( - sinT *( sinT / (q.nR * q.nR )) * ( q.z * q.z + q.x * q.x ) );
// acos(t1)
//const angle1 = acos( ( 1 - sinT *( sinT / (q.nR * q.nR )) * ( q.z * q.z - q.x * q.x ) ) * dcos
// - ( sinT / (q.nR * q.nR )) * ( q.x * q.z * sinT + q.x * q.z * cosT ) * dsin
// - sinT *( sinT / (q.nR * q.nR )) * ( q.z * q.z + q.x * q.x ) )
// );
// this should be the complete expression for the bottom... change in angle.
const angle2 = acos( ( dcos - ( sinT*sinT / (q.nR * q.nR )) * (
( q.z * q.z - q.x * q.x ) * dcos
- ( q.x * q.z * sinT + q.x * q.z * cosT ) * dsin
- ( q.z * q.z + q.x * q.x ) )
);
// lnQuat.prototype.fromBasis = function( basis ) {...
// trace of the matrix is 2 * cosT + 1
// tr(M)=2cos(theta)+1 .
const t = ( ( basis.right.x + basis.up.y + basis.forward.z ) - 1 )/2; // trace/total (expanded above)
const angle = Math.acos(t); // (expanded above)
/*
x = (R21 - R12)/sqrt((R21 - R12)^2+(R02 - R20)^2+(R10 - R01)^2);
y = (R02 - R20)/sqrt((R21 - R12)^2+(R02 - R20)^2+(R10 - R01)^2);
z = (R10 - R01)/sqrt((R21 - R12)^2+(R02 - R20)^2+(R10 - R01)^2);
*/
/*
basis.forward.y -basis.up.z * basis.forward.y -basis.up.z ......
( ( q.z * q.z * q.y * q.y * sinT * sinT - 2 * q.z * q.y * q.x * q.nR * sinT * cosT + q.x * q.x * q.nR * q.nR * cosT * cosT ) * dcos *dcos
+ ( q.y * q.y * q.x * q.x * sinT * sinT - 2 * q.y * q.x * sinT * cosT * q.z * q.nR + cosT * cosT * q.z * q.z * q.nR * q.nR ) * dsin * dsin
+ ( q.z * q.z * q.y * q.y * sinT * sinT + 2 * q.z * q.y * sinT * cosT * q.x * q.nR + cosT * cosT * q.x * q.x * q.nR * q.nR )
+ 2 * ( q.z * q.y * sinT * q.y * q.x * sinT - q.z * q.y * sinT * cosT * q.z * q.nR - cosT * q.x * q.nR * q.y * q.x * sinT + cosT * q.x * q.nR * cosT * q.z * q.nR )*dsin *dcos
+ 2 * ( ( q.z * q.y * sinT - cosT * q.x * q.nR ) )*dcos * ( -q.z * q.y * sinT - cosT * q.x * q.nR )
+ 2 * ( q.y * q.x * sinT - cosT * q.z * q.nR )*dsin * ( q.z * q.y * sinT + cosT * q.x * q.nR )
*/
const tmp = 1 /Math.sqrt((basis.forward.y -basis.up.z)*(basis.forward.y-basis.up.z) + (basis.right.z-basis.forward.x)*(basis.right.z-basis.forward.x) + (basis.up.x-basis.right.y)*(basis.up.x-basis.right.y));
this.nx = (basis.up.z -basis.forward.y) *tmp;
this.ny = (basis.forward.x -basis.right.z ) *tmp;
this.nz = (basis.right.y -basis.up.x ) *tmp;
const lNorm = angle / (Math.abs(this.nx)+Math.abs(this.ny)+Math.abs(this.nz));
this.x = this.nx * lNorm;
this.y = this.ny * lNorm;
this.z = this.nz * lNorm;
this.nx *= angle;
this.ny *= angle;
this.nz *= angle;
this.dirty = true; // update() later will fix nL and nR
return this;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment