📄 flyclasslib.cpp
字号:
#include "../Fly3D.h"
void mat4x4::lerp(mat4x4& m1,mat4x4& m2,float t)
{
quaternion q1(m1),q2(m2),qt;
qt.lerp(q1,q2,t);
qt.get_mat(*this);
m[3][0]=m1.m[3][0]*(1-t)+m2.m[3][0]*t;
m[3][1]=m1.m[3][1]*(1-t)+m2.m[3][1]*t;
m[3][2]=m1.m[3][2]*(1-t)+m2.m[3][2]*t;
}
void mat4x4::rotate( float ang,vector& dir )
{
static mat4x4 m;
m.set_rotation(ang,dir);
*this=*this*m;
}
void mat4x4::set_rotation( float ang,vector& dir )
{
dir.normalize();
ang*=-PiOver180;
float fCos=(float)cos( ang );
float fSin=(float)sin( ang );
m[0][0] = ( dir.x * dir.x ) * ( 1.0f - fCos ) + fCos;
m[0][1] = ( dir.x * dir.y ) * ( 1.0f - fCos ) - (dir.z * fSin);
m[0][2] = ( dir.x * dir.z ) * ( 1.0f - fCos ) + (dir.y * fSin);
m[1][0] = ( dir.y * dir.x ) * ( 1.0f - fCos ) + (dir.z * fSin);
m[1][1] = ( dir.y * dir.y ) * ( 1.0f - fCos ) + fCos ;
m[1][2] = ( dir.y * dir.z ) * ( 1.0f - fCos ) - (dir.x * fSin);
m[2][0] = ( dir.z * dir.x ) * ( 1.0f - fCos ) - (dir.y * fSin);
m[2][1] = ( dir.z * dir.y ) * ( 1.0f - fCos ) + (dir.x * fSin);
m[2][2] = ( dir.z * dir.z ) * ( 1.0f - fCos ) + fCos;
m[0][3] = m[1][3] = m[2][3] = 0;
m[3][0] = m[3][1] = m[3][2] = 0;
m[3][3] = 1;
}
quaternion::quaternion(mat4x4 &mat)
{
float tr,s,q[4];
int i,j,k;
int nxt[3] = {1, 2, 0};
tr = mat.m[0][0] + mat.m[1][1] + mat.m[2][2];
// check the diagonal
if (tr > 0.0)
{
s = (float)sqrt(tr + 1.0f);
w = s/2.0f;
s = 0.5f/s;
x = (mat.m[1][2] - mat.m[2][1]) * s;
y = (mat.m[2][0] - mat.m[0][2]) * s;
z = (mat.m[0][1] - mat.m[1][0]) * s;
}
else
{
// diagonal is negative
i = 0;
if (mat.m[1][1] > mat.m[0][0]) i = 1;
if (mat.m[2][2] > mat.m[i][i]) i = 2;
j = nxt[i];
k = nxt[j];
s=(float)sqrt((mat.m[i][i]-(mat.m[j][j] + mat.m[k][k])) + 1.0);
q[i]=s*0.5f;
if(s!=0.0f) s = 0.5f/s;
q[3] = (mat.m[j][k] - mat.m[k][j]) * s;
q[j] = (mat.m[i][j] + mat.m[j][i]) * s;
q[k] = (mat.m[i][k] + mat.m[k][i]) * s;
x = q[0];
y = q[1];
z = q[2];
w = q[3];
}
}
void quaternion::get_mat(mat4x4 &mat)
{
float wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2;
// calculate coefficients
x2 = x + x;
y2 = y + y;
z2 = z + z;
xx = x * x2;
xy = x * y2;
xz = x * z2;
yy = y * y2;
yz = y * z2;
zz = z * z2;
wx = w * x2;
wy = w * y2;
wz = w * z2;
mat.m[0][0] = 1.0f-(yy+zz);
mat.m[1][0] = xy - wz;
mat.m[2][0] = xz + wy;
mat.m[3][0] = 0.0;
mat.m[0][1] = xy + wz;
mat.m[1][1] = 1.0f-(xx + zz);
mat.m[2][1] = yz - wx;
mat.m[3][1] = 0.0;
mat.m[0][2] = xz - wy;
mat.m[1][2] = yz + wx;
mat.m[2][2] = 1.0f - (xx + yy);
mat.m[3][2] = 0.0;
mat.m[0][3] = 0;
mat.m[1][3] = 0;
mat.m[2][3] = 0;
mat.m[3][3] = 1;
}
quaternion quaternion::operator *(quaternion &q)
{
float A, B, C, D, E, F, G, H;
quaternion res;
A = (q.w + q.x)*(w + x);
B = (q.z - q.y)*(y - z);
C = (q.w - q.x)*(y + z);
D = (q.y + q.z)*(w - x);
E = (q.x + q.z)*(x + y);
F = (q.x - q.z)*(x - y);
G = (q.w + q.y)*(w - z);
H = (q.w - q.y)*(w + z);
res.w = B + (-E - F + G + H) /2;
res.x = A - (E + F + G + H)/2;
res.y = C + (E - F + G - H)/2;
res.z = D + (E - F - G + H)/2;
return res;
}
void quaternion::normalize()
{
float factor = 1.0f/(float)sqrt(x*x+y*y+z*z+w*w);
x*=factor;
y*=factor;
z*=factor;
w*=factor;
}
void quaternion::get_rotate(float &angle, vector &axis)
{
angle=(float)acos(w)*2*PiUnder180;
float f=(float)sin(angle*PiOver180*0.5f);
axis.x=x/f;
axis.y=x/f;
axis.z=x/f;
}
void quaternion::lerp(quaternion& q1,quaternion& q2,float t)
{
float v; // complement to t
float o; // complement to v (t)
float theta; // angle between q1 & q2
float sin_t; // sin(theta)
float cos_t; // cos(theta)
float phi; // spins added to theta
int flip; // flag for negating q2
cos_t = q1[0] * q2[0] + q1[1] * q2[1] + q1[2] * q2[2] + q1[3] * q2[3];
if (cos_t < 0.0)
{
cos_t = -cos_t;
flip = TRUE;
}
else flip = FALSE;
if (1.0 - cos_t < 1e-6)
{
v = 1.0f - t;
}
else
{
theta = (float)acos(cos_t);
phi = theta;
sin_t = (float)sin(theta);
v = (float)sin(theta - t * phi) / sin_t;
o = (float)sin(t * phi) / sin_t;
}
if (flip) o = -o;
x = v * q1[0] + o * q2[0];
y = v * q1[1] + o * q2[1];
z = v * q1[2] + o * q2[2];
w = v * q1[3] + o * q2[3];
}
void local_system::align_z(vector& z)
{
if (fabs(z.z)>=0.99f)
{
Y.x=-z.y*z.x;
Y.y=1-z.y*z.y;
Y.z=-z.y*z.z;
Y.normalize();
X.cross(Y,z);
}
else
{
Y.x=-z.z*z.x;
Y.y=-z.z*z.y;
Y.z=1-z.z*z.z;
Y.normalize();
X.cross(Y,z);
}
Z=z;
update_mat();
}
void local_system::update_mat()
{
memset(&mat,0,sizeof(mat));
mat.m[0][0]=X.x;
mat.m[0][1]=X.y;
mat.m[0][2]=X.z;
mat.m[1][0]=Y.x;
mat.m[1][1]=Y.y;
mat.m[1][2]=Y.z;
mat.m[2][0]=Z.x;
mat.m[2][1]=Z.y;
mat.m[2][2]=Z.z;
mat.m[3][3]=1;
int i,j;
for( i=0;i<4;i++ )
for( j=0;j<4;j++ )
mat_t.m[i][j]=mat.m[j][i];
}
void local_system::rotate(vector &v, vector &u, float maxang)
{
vector c;
float f;
c.cross(v, u);
f=c.length();
if(f>0.01)
{
c.x/=f; c.y/=f; c.z/=f;
f=(float)acos(vec_dot(v, u))*180.0f/M_Pi;
if(f>maxang)
f=maxang;
else if(f<-maxang)
f=-maxang;
rotate(f, c);
}
}
void local_system::rotate(vector& rot)
{
static mat4x4 m;
m.set_rotation(rot.x,X);
m.rotate(rot.y,Y);
m.rotate(rot.z,Z);
X=X*m;
Y=Y*m;
Z=Z*m;
update_mat();
}
void local_system::rotate(float ang,vector& v)
{
static mat4x4 m;
m.set_rotation(ang,v);
X=X*m;
Y=Y*m;
Z=Z*m;
update_mat();
}
void boundbox::add_point(vector& p)
{
if (p.x>max.x)
max.x=p.x;
if (p.y>max.y)
max.y=p.y;
if (p.z>max.z)
max.z=p.z;
if (p.x<min.x)
min.x=p.x;
if (p.y<min.y)
min.y=p.y;
if (p.z<min.z)
min.z=p.z;
}
void boundbox::add_point(float x,float y,float z)
{
if (x>max.x)
max.x=x;
if (y>max.y)
max.y=y;
if (z>max.z)
max.z=z;
if (x<min.x)
min.x=x;
if (y<min.y)
min.y=y;
if (z<min.z)
min.z=z;
}
int boundbox::ray_intersect(vector& ro,vector& rd,float& tnear,float& tfar)
{
static float *rd_,*ro_,*min_,*max_,t1,t2,t;
rd_=&rd.x;
ro_=&ro.x;
min_=&min.x;
max_=&max.x;
tnear=-BIG;
tfar=BIG;
int a;
for( a=0;a<3;a++ )
{
if (rd_[a]>-SMALL && rd_[a]<SMALL)
if (ro_[a]<min_[a] || ro_[a]>max_[a])
return 0;
else ;
else {
t1=(min_[a]-ro_[a])/rd_[a];
t2=(max_[a]-ro_[a])/rd_[a];
if (t1>t2)
{ t=t1; t1=t2; t2=t; }
if (t1>tnear)
tnear=t1;
if (t2<tfar)
tfar=t2;
if (tnear>tfar || tfar<SMALL)
return 0;
}
}
if (tnear>tfar || tfar<SMALL)
return 0;
return 2;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -