JD2022-TU1/main/extern/Camcam/CCMath/CCMath.cpp

716 lines
14 KiB
C++

// CCMath.cpp : Defines the entry point for the DLL application.
//
#include "windows.h"
#include "CCMath.h"
#include "math.h"
#ifdef _MANAGED
#pragma managed(push, off)
#endif
#ifdef CCMATH_DLL_MODE
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
#endif
#ifdef _MANAGED
#pragma managed(pop)
#endif
/******************* COULD BE USEFUL **************************
_inline float FastInvSqrt(float x)
{
float xhalf = 0.5f*x;
int i = *(int*)&x; // get bits for floating value
i = 0x5f375a86- (i>>1); // gives initial guess y0
x = *(float*)&i; // convert bits back to float
x = x*(1.5f-xhalf*x*x); // Newton step, repeating increases accuracy
return x;
}
_inline float FastSqrt(float number) {
long i;
float x, y;
x = number * 0.5F;
y = number;
i = * ( long * ) &y;
i = 0x5f3759df - ( i >> 1 );
y = * ( float * ) &i;
y = y * ( 1.5F - ( x * y * y ) );
y = y * ( 1.5F - ( x * y * y ) );// 2nd iteration : Can be removed
return number * y;
}
*/
#define SMALL_FOR_CLEAN 0.0001f
_inline int CheckNAN(float *a)
{
if ((*((int*)a) & 0x7f800000) == 0x7f800000) return 1;
return 0;
}
Vector::Vector(void)
{
}
Vector::Vector(const float _x, const float _y, const float _z)
{
x = _x; y = _y; z = _z;
}
Vector Vector::operator+(const Vector &vec2) const
{
return Vector(x + vec2.x, y + vec2.y, z + vec2.z);
}
Vector Vector::operator-(const Vector &vec2) const
{
return Vector(x - vec2.x, y - vec2.y, z - vec2.z);
}
Vector Vector::operator&(const Vector &vec2) const
{
return Vector(x * vec2.x, y * vec2.y, z * vec2.z);
}
Vector Vector::operator*(const float Value) const
{
return Vector(x * Value, y * Value, z * Value);
}
Vector Vector::operator^(const Vector &B) const
{
return Vector(
(y * B.z) - (z * B.y),
(z * B.x) - (x * B.z),
(x * B.y) - (y * B.x));
}
float Vector::operator*(const Vector &vec2) const
{
return x * vec2.x + y * vec2.y + z * vec2.z;
}
void Vector::operator+=(const Vector &vec2)
{
x += vec2.x; y += vec2.y; z += vec2.z;
}
void Vector::operator+=(const float Value)
{
x += Value; y += Value; z += Value;
}
void Vector::operator-=(const Vector &vec2)
{
x -= vec2.x; y -= vec2.y; z -= vec2.z;
}
void Vector::operator*=(const float Value)
{
x *= Value; y *= Value; z *= Value;
}
void Vector::operator&=(const Vector &vec2)
{
x *= vec2.x; y *= vec2.y; z *= vec2.z;
}
int Vector::operator!=(const Vector &vec2)
{
return x != vec2.x ? 1 : y != vec2.y ? 1 : z != vec2.z ? 1 : 0;
}
int Vector::CheckNAN()
{
return ::CheckNAN(&x)|::CheckNAN(&y)|::CheckNAN(&z);
}
void Vector::Clean()
{
if (fabs(x) < SMALL_FOR_CLEAN) x = 0.0f;
if (fabs(y) < SMALL_FOR_CLEAN) y = 0.0f;
if (fabs(z) < SMALL_FOR_CLEAN) z = 0.0f;
}
int Vector::isRightXY(const Vector &A,const Vector &B) const
{
Vector D,E;
float R;
D = *this - A;
E = B - A;
R = (D.y * E.x) - (D.x * E.y)/* - 0.005f*/;
return *((unsigned int *)&R) >> 31;
}
float Vector::DistanceToLineXY(const Vector &A,const Vector &B) const
{
Vector D,E;
float R;
D = *this - A;
E = B - A;
R = (D.x * E.y) - (D.y * E.x);
return R;
}
Vector Vector::VectorToLine(const Vector &DirNormalized) const
{
Vector D,E;
E = DirNormalized * (DirNormalized * *this);
D = E - *this;
return D;
}
float Vector::SqrNorm() const
{
return (x * x + y * y + z * z);
}
float Vector::Norm() const
{
return sqrtf(x * x + y * y + z * z);
}
float Vector::NormXY() const
{
return sqrtf(x * x + y * y);
}
float Vector::SqrNormXY() const
{
return (x * x + y * y);
}
void Vector::Normalize()
{
float NormV;
NormV = SqrNorm();
if (NormV)
{
NormV = 1.0f / sqrtf(NormV);
x *= NormV ;
y *= NormV ;
z *= NormV ;
}
}
void Vector::Max(const Vector &vecB)
{
x = x > vecB.x ? x : vecB.x;
y = y > vecB.y ? y : vecB.y;
z = z > vecB.z ? z : vecB.z;
}
void Vector::Min(const Vector &vecB)
{
x = x < vecB.x ? x : vecB.x;
y = y < vecB.y ? y : vecB.y;
z = z < vecB.z ? z : vecB.z;
}
int Vector::IsIn2D(const Vector &Min,const Vector &Max)
{
int Ret;
Ret = (x > Min.x) && (x < Max.x) ? 1 : 0;
Ret &= (y > Min.y) && (y < Max.y) ? 1 : 0;
return Ret;
}
#define Swap(a,b) {float SWP; SWP = a ; a = b ; b = SWP;}
inline Vector MATRIX::operator*(const Vector &V) const
{
//Vector Res;
//Res = (I * V.x) + (J * V.y) + (K * V.z) + T;
//return Res;
return Vector( I.x * V.x + J.x * V.y + K.x * V.z + T.x,
I.y * V.x + J.y * V.y + K.y * V.z + T.y,
I.z * V.x + J.z * V.y + K.z * V.z + T.z);
}
int MATRIX::CheckNAN()
{
return I.CheckNAN()|J.CheckNAN()|K.CheckNAN()|T.CheckNAN();
}
void MATRIX::Transp()
{
Swap(I.y,J.x);
Swap(I.z,K.x);
Swap(J.z,K.y);
}
void MATRIX::Clean()
{
I.Clean();
J.Clean();
K.Clean();
T.Clean();
}
void MATRIX::Inverse(MATRIX &Dst)
{
Vector Trans;
memset(&Dst,0,sizeof(MATRIX ));
Dst.I = J ^ K;
Dst.J = I ^ K;
Dst.K = I ^ J;
Dst.I *= 1.0f / (I * Dst.I);
Dst.J *= 1.0f / (J * Dst.J);
Dst.K *= 1.0f / (K * Dst.K);
Dst.Transp();
Dst.T = Vector(0,0,0);
Trans.x = -T.x;
Trans.y = -T.y;
Trans.z = -T.z;
Dst.T = Dst * Trans;
}
void MATRIX::Blend(MATRIX &EndL,float Factor)
{
Vector ZoomB,ZoomE;
Quat QB,QE;
MATRIX End,Ret;
End = EndL;
if (Factor > 1.0f) Factor = 1.0f;
if (Factor < 0.0f) Factor = 0.0f;
ZoomB.x = I.Norm();
ZoomB.y = J.Norm();
ZoomB.z = K.Norm();
ZoomE.x = End.I.Norm();
ZoomE.y = End.J.Norm();
ZoomE.z = End.K.Norm();
I.Normalize();
J.Normalize();
K.Normalize();
End.I.Normalize();
End.J.Normalize();
End.K.Normalize();
QB.ComputeFromMatrix(this);
QE.ComputeFromMatrix(&End);
QB = (QB * (1.0f - Factor)) + (QE * Factor);
QB.Normalize();
QB.TransforToMatrix(&Ret);
Ret.T = (T * (1.0f - Factor)) + (End.T * Factor);
ZoomE = (ZoomB * (1.0f - Factor)) + (ZoomE * Factor);
Ret.I *= ZoomE.x;
Ret.J *= ZoomE.y;
Ret.K *= ZoomE.z;
*this = Ret;
}
void MATRIX::GetScale(Vector &V)
{
V.x = I.Norm();
V.y = J.Norm();
V.z = K.Norm();
}
void MATRIX::SetScale(Vector &V)
{
I.Normalize();
J.Normalize();
K.Normalize();
I *= V.x;
J *= V.y;
K *= V.z;
}
void MATRIX::RotateAround_I(float Alpha)
{
float COSA,SINA;
Vector A,B;
COSA = cosf(Alpha);
SINA = sinf(Alpha);
A = J;
B = K;
J = A * COSA + B * SINA;
K = B * COSA - A * SINA;
}
void MATRIX::RotateAround_J(float Alpha)
{
float COSA,SINA;
Vector A,B;
COSA = cosf(Alpha);
SINA = sinf(Alpha);
A = K;
B = I;
K = A * COSA + B * SINA;
I = B * COSA - A * SINA;
}
void MATRIX::RotateAround_K(float Alpha)
{
float COSA,SINA;
Vector A,B;
COSA = cosf(Alpha);
SINA = sinf(Alpha);
A = I;
B = J;
I = A * COSA + B * SINA;
J = B * COSA - A * SINA;
}
void MATRIX::RotateAround_X(float Alpha)
{
MATRIX II;
Vector SaavetTRans;
II.Identity();
II.RotateAround_I(Alpha);
SaavetTRans = T;
*this *= II;
T = SaavetTRans;
}
void MATRIX::RotateAround_Y(float Alpha)
{
MATRIX II;
Vector SaavetTRans;
II.Identity();
II.RotateAround_J(Alpha);
SaavetTRans = T;
*this *= II;
T = SaavetTRans;
}
void MATRIX::RotateAround_Z(float Alpha)
{
MATRIX II;
Vector SaavetTRans;
II.Identity();
II.RotateAround_K(Alpha);
SaavetTRans = T;
*this *= II;
T = SaavetTRans;
}
void MATRIX::RotateAround(int Axis, float Alpha)
{
switch(Axis)
{
case 0:RotateAround_K(Alpha);break;
case 1:RotateAround_J(Alpha);break;
case 2:RotateAround_I(Alpha);break;
}
}
void MATRIX::operator*=(MATRIX &M)
{
MATRIX Save;
Save = *this;
I.x = Save.I.x * M.I.x + Save.I.y * M.J.x + Save.I.z * M.K.x ;
I.y = Save.I.x * M.I.y + Save.I.y * M.J.y + Save.I.z * M.K.y ;
I.z = Save.I.x * M.I.z + Save.I.y * M.J.z + Save.I.z * M.K.z ;
J.x = Save.J.x * M.I.x + Save.J.y * M.J.x + Save.J.z * M.K.x ;
J.y = Save.J.x * M.I.y + Save.J.y * M.J.y + Save.J.z * M.K.y ;
J.z = Save.J.x * M.I.z + Save.J.y * M.J.z + Save.J.z * M.K.z ;
K.x = Save.K.x * M.I.x + Save.K.y * M.J.x + Save.K.z * M.K.x ;
K.y = Save.K.x * M.I.y + Save.K.y * M.J.y + Save.K.z * M.K.y ;
K.z = Save.K.x * M.I.z + Save.K.y * M.J.z + Save.K.z * M.K.z ;
T.x = (Save.T.x * M.I.x + Save.T.y * M.J.x + Save.T.z * M.K.x) + M.T.x;
T.y = (Save.T.x * M.I.y + Save.T.y * M.J.y + Save.T.z * M.K.y) + M.T.y;
T.z = (Save.T.x * M.I.z + Save.T.y * M.J.z + Save.T.z * M.K.z) + M.T.z;
/*
M.Transp();
I.x = Save.I * M.I;
I.y = Save.I * M.J;
I.z = Save.I * M.K;
J.x = Save.J * M.I;
J.y = Save.J * M.J;
J.z = Save.J * M.K;
K.x = Save.K * M.I;
K.y = Save.K * M.J;
K.z = Save.K * M.K;
T.x = (Save.T * M.I) + M.T.x;
T.y = (Save.T * M.J) + M.T.y;
T.z = (Save.T * M.K) + M.T.z;
M.Transp();
*/
}
void MATRIX::operator*=(float Scale)
{
I *= Scale;
J *= Scale;
K *= Scale;
}
void MATRIX::Identity()
{
I = Vector(1,0,0);
J = Vector(0,1,0);
K = Vector(0,0,1);
T = Vector(0,0,0);
}
MATRIX::MATRIX() {
Identity();
}
float myMod(float val, float mod)
{
mod /= 2;
while (val < -mod)
val += mod;
while (val > mod)
val -= mod;
return val;
}
void MATRIX::ToEuler(Vector &eulerVect)
{
float C;
float trX;
float trY;
float PI = atan(1.0f) * 4;
eulerVect.y = -asin( K.x);
C = cos( eulerVect.y );
if ( fabs( C ) > 0.005 )
{
trX = K.z / C;
trY = -K.y / C;
eulerVect.x = atan2( trY, trX );
trX = I.x / C;
trY = -J.x / C;
eulerVect.z = atan2( trY, trX );
} else
{
eulerVect.x = 0.0f;
trX = J.y;
trY = I.y;
eulerVect.z = atan2( trY, trX );
}
eulerVect.x = myMod(eulerVect.x, 2*PI);
eulerVect.y = myMod(eulerVect.y, 2*PI);
eulerVect.z = myMod(eulerVect.z, 2*PI);
}
void MATRIX::FromEuler(Vector eulerVect)
{
float A,B,C,D,E,F,AD,BD;
A = cos(eulerVect.x);
B = sin(eulerVect.x);
C = cos(eulerVect.y);
D = sin(eulerVect.y);
E = cos(eulerVect.z);
F = sin(eulerVect.z);
AD = A * D;
BD = B * D;
I.x = C * E;
I.y = -C * F;
I.z = -D;
J.x = -BD * E + A * F;
J.y = BD * F + A * E;
J.z = -B * C;
K.x = AD * E + B * F;
K.y = -AD * F + B * E;
K.z = A * C; }
void Quat::ComputeFromMatrix(MATRIX *ActualMat)
{
float T, S;
int iBestColumn;
MATRIX LocalNormed;
LocalNormed = *ActualMat;
LocalNormed.I.Normalize();
LocalNormed.J.Normalize();
LocalNormed.K.Normalize();
if ((LocalNormed.I ^ LocalNormed.J) * LocalNormed.K < 0.0f)
iBestColumn = 0; // <- never enter here !!! */
/* trace of the matrix */
T = LocalNormed.I.x + LocalNormed.J.y + LocalNormed.K.z;
if(T > 0.0f)
{
S = sqrtf(T + 1.0f);
w = S * 0.5f;
S = 0.5f / S;
x = (LocalNormed.J.z - LocalNormed.K.y) * S;
y = (LocalNormed.K.x - LocalNormed.I.z) * S;
z = (LocalNormed.I.y - LocalNormed.J.x) * S;
}
else
{
/* Find the greatest diagonal element */
if(LocalNormed.I.x >= LocalNormed.J.y)
{
if(LocalNormed.I.x >= LocalNormed.K.z)
iBestColumn = 1;
else
iBestColumn = 3;
}
else
{
if(LocalNormed.J.y >= LocalNormed.K.z)
iBestColumn = 2;
else
iBestColumn = 3;
}
switch(iBestColumn)
{
case 1:
S = sqrtf(1.0f + LocalNormed.I.x - LocalNormed.J.y - LocalNormed.K.z);
x = S * 0.5f;
S = 0.5f / S;
y = (LocalNormed.J.x + LocalNormed.I.y) * S;
z = (LocalNormed.K.x + LocalNormed.I.z) * S;
w = (LocalNormed.J.z - LocalNormed.K.y) * S;
break;
case 2:
S = sqrtf(1.0f - LocalNormed.I.x + LocalNormed.J.y - LocalNormed.K.z);
y = S * 0.5f;
S = 0.5f / S;
z = (LocalNormed.K.y + LocalNormed.J.z) * S;
x = (LocalNormed.I.y + LocalNormed.J.x) * S;
w = (LocalNormed.K.x - LocalNormed.I.z) * S;
break;
case 3:
S = sqrtf(1.0f - LocalNormed.I.x - LocalNormed.J.y + LocalNormed.K.z);
z = S * 0.5f;
S = 0.5f / S;
x = (LocalNormed.I.z + LocalNormed.K.x) * S;
y = (LocalNormed.J.z + LocalNormed.K.y) * S;
w = (LocalNormed.I.y - LocalNormed.J.x) * S;
break;
}
}
Normalize();
}
void Quat::TransforToMatrix(MATRIX *ActualMat)
{
float xx, xy, xz, xw, yy, yz, yw, zz, zw;
xx = 0.5f - 2.0f * x * x;
xy = 2.0f * x * y;
xz = 2.0f * x * z;
xw = 2.0f * x * w;
yy = 0.5f - 2.0f * y * y;
yz = 2.0f * y * z;
yw = 2.0f * y * w;
zz = 0.5f - 2.0f * z * z;
zw = 2.0f * z * w;
ActualMat->I.x = yy + zz;
ActualMat->J.x = xy - zw;
ActualMat->K.x = xz + yw;
ActualMat->I.y = xy + zw;
ActualMat->J.y = xx + zz;
ActualMat->K.y = yz - xw;
ActualMat->I.z = xz - yw;
ActualMat->J.z = yz + xw;
ActualMat->K.z = xx + yy;
ActualMat->T = Vector(0,0,0);
}
void Quat::TransforToVector(Vector &V)
{
V.x = x;
V.y = y;
V.z = z;
}
Quat::Quat(void)
{
}
Quat::Quat(float _x,float _y,float _z,float _w)
{
x = _x;y = _y;z = _z;w = _w;
}
Quat::Quat(Vector V,float _w) {
x = V.x;y = V.y;z = V.z;w = _w;
}
Quat::Quat(Vector V)
{
x = V.x;y = V.y;z = V.z;NormalizeW();
}
void Quat::ExtractFrom2Edges(Vector *Src,Vector *Dst)
{
Vector V1,V2,VCP;
V1 = *Src;
V2 = *Dst;
V1.Normalize();
V2.Normalize();
V2 = V1 * 0.5f + V2 * 0.5f;
V2.Normalize();
VCP = V1^V2;
x = VCP.x;
y = VCP.y;
z = VCP.z;
NormalizeW();
}
void Quat::operator*=(const float F)
{
x *= F;
y *= F;
z *= F;
w *= F;
}
void Quat::operator+=(const Quat &Q2)
{
x += Q2.x;
y += Q2.y;
z += Q2.z;
w += Q2.w;
}
Quat Quat::operator+(const Quat &Q2)
{
Quat Res;
Res = *this;
Res.x += Q2.x;
Res.y += Q2.y;
Res.z += Q2.z;
Res.w += Q2.w;
return Res;
}
void Quat::Normalize()
{
float OoN = 1.0f / sqrtf(x*x + y*y + z*z + w*w);
x *= OoN;
y *= OoN;
z *= OoN;
w *= OoN;
}
void Quat::NormalizeW()
{
w = sqrtf(1.0f - x*x - y*y - z*z);
}
Quat Quat::operator*(const Quat &Q2) const
{
Quat Res;
Res.x = (w * Q2.x) + (Q2.w * x) + (y * Q2.z) - (z * Q2.y);
Res.y = (w * Q2.y) + (Q2.w * y) + (z * Q2.x) - (x * Q2.z);
Res.z = (w * Q2.z) + (Q2.w * z) + (x * Q2.y) - (y * Q2.x);
Res.w = (w * Q2.w) - (x * Q2.x + y * Q2.y + z * Q2.z);
return Res;
}
Quat Quat::operator*(const float F) const
{
Quat Res;
Res = *this;
Res *= F;
//Res.NormalizeW();
return Res;
}
void Quat::operator*=(const Quat &Q2)
{
Quat Res;
Res.x = (w * Q2.x) + (Q2.w * x) + (y * Q2.z) - (z * Q2.y);
Res.y = (w * Q2.y) + (Q2.w * y) + (z * Q2.x) - (x * Q2.z);
Res.z = (w * Q2.z) + (Q2.w * z) + (x * Q2.y) - (y * Q2.x);
Res.w = (w * Q2.w) - (x * Q2.x + y * Q2.y + z * Q2.z);
*this = Res;
}