⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 matrix.cpp

📁 游戏《家园》源码
💻 CPP
字号:
// Copyright (c) 1998 Relic Entertainment Inc.
// Original code written by Keith Hentschel
// Adapted by Janik Joire
//
// $History: $

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "matrix.h"

float identitymatrix[16]=
{
	1.0F,0.0F,0.0F,0.0F,
	0.0F,1.0F,0.0F,0.0F,
	0.0F,0.0F,1.0F,0.0F,
	0.0F,0.0F,0.0F,1.0F
};

enum
{
    M00=0, M01=4, M02=8,  M03=12,
    M10=1, M11=5, M12=9,  M13=13,
    M20=2, M21=6, M22=10, M23=14,
    M30=3, M31=7, M32=11, M33=15
};

void matInvert(float *c,float* m)
{

    float det;
    float tmp[16];    // allow out = in
	float d12,d13,d23,d24,d34,d41;
	float im11,im12,im13,im14;
	
#define MAT(m,r,c) (m)[((c)<<2)+(r)]

#define m11 MAT(m,0,0)
#define m12 MAT(m,0,1)
#define m13 MAT(m,0,2)
#define m14 MAT(m,0,3)
#define m21 MAT(m,1,0)
#define m22 MAT(m,1,1)
#define m23 MAT(m,1,2)
#define m24 MAT(m,1,3)
#define m31 MAT(m,2,0)
#define m32 MAT(m,2,1)
#define m33 MAT(m,2,2)
#define m34 MAT(m,2,3)
#define m41 MAT(m,3,0)
#define m42 MAT(m,3,1)
#define m43 MAT(m,3,2)
#define m44 MAT(m,3,3)

    if((m41 != 0.0F) || (m42 != 0.0F) || (m43 != 0.0F) || (m44 != 1.0F))
    {
        matInvertEx(c,m);
        return;
    }

    // Inverse=adjoint/det

    tmp[0]=m22*m33-m23*m32;
    tmp[1]=m23*m31-m21*m33;
    tmp[2]=m21*m32-m22*m31;

    // Compute determinant using cofactors
    det=m11*tmp[0]+m12*tmp[1]+m13*tmp[2];

    // Singularity test
    if(det == 0.0F) matIdentity(c);
    else
    {
        det=1.0F/det;

        // Compute rest of inverse
        tmp[0]*=det;
        tmp[1]*=det;
        tmp[2]*=det;
        tmp[3]=0.0F;

        im11=m11*det;
        im12=m12*det;
        im13=m13*det;
        im14=m14*det;

        tmp[4]=im13*m32-im12*m33;
        tmp[5]=im11*m33-im13*m31;
        tmp[6]=im12*m31-im11*m32;
        tmp[7]=0.0F;

        // Pre-compute 2x2 dets for first two rows when computing cofactors of last two rows.
		d12=im11*m22-m21*im12;
		d13=im11*m23-m21*im13;
		d23=im12*m23-m22*im13;
		d24=im12*m24-m22*im14;
		d34=im13*m24-m23*im14;
		d41=im14*m21-m24*im11;

        tmp[8]=d23;
        tmp[9]=-d13;
        tmp[10]=d12;
        tmp[11]=0.0F;

        tmp[12]=-(m32*d34-m33*d24+m34*d23);
        tmp[13]=(m31*d34+m33*d41+m34*d13);
        tmp[14]=-(m31*d24+m32*d41+m34*d12);
        tmp[15]=1.0F;

        memcpy(c,tmp,sizeof(float)*16);
    }

#undef m11
#undef m12
#undef m13
#undef m14
#undef m21
#undef m22
#undef m23
#undef m24
#undef m31
#undef m32
#undef m33
#undef m34
#undef m41
#undef m42
#undef m43
#undef m44

#undef MAT

	return;
}

void matInvertEx(float* c,float * m)
{
    float r1[2][2],r2[2][2],r3[2][2],r4[2][2],r5[2][2],r6[2][2],r7[2][2];
    float *A;
    float *C;
    float one_over_det;

    A=m;
    C=c;

    // A is the 4x4 source matrix (to be inverted).
    // C is the 4x4 destination matrix
    // a11 is the 2x2 matrix in the upper left quadrant of A
    // a12 is the 2x2 matrix in the upper right quadrant of A
    // a21 is the 2x2 matrix in the lower left quadrant of A
    // a22 is the 2x2 matrix in the lower right quadrant of A
    // similarly, cXX are the 2x2 quadrants of the destination matrix

    // R1=inverse(a11)
    one_over_det=1.0F/((A[M00]*A[M11])-(A[M10]*A[M01]));
    r1[0][0]=one_over_det*A[M11];
    r1[0][1]=one_over_det*(-A[M01]);
    r1[1][0]=one_over_det*(-A[M10]);
    r1[1][1]=one_over_det*A[M00];

    // R2=a21xR1
    r2[0][0]=A[M20]*r1[0][0]+A[M21]*r1[1][0];
    r2[0][1]=A[M20]*r1[0][1]+A[M21]*r1[1][1];
    r2[1][0]=A[M30]*r1[0][0]+A[M31]*r1[1][0];
    r2[1][1]=A[M30]*r1[0][1]+A[M31]*r1[1][1];

    // R3=R1xa12
    r3[0][0]=r1[0][0]*A[M02]+r1[0][1]*A[M12];
    r3[0][1]=r1[0][0]*A[M03]+r1[0][1]*A[M13];
    r3[1][0]=r1[1][0]*A[M02]+r1[1][1]*A[M12];
    r3[1][1]=r1[1][0]*A[M03]+r1[1][1]*A[M13];

    // R4=a21xR3
    r4[0][0]=A[M20]*r3[0][0]+A[M21]*r3[1][0];
    r4[0][1]=A[M20]*r3[0][1]+A[M21]*r3[1][1];
    r4[1][0]=A[M30]*r3[0][0]+A[M31]*r3[1][0];
    r4[1][1]=A[M30]*r3[0][1]+A[M31]*r3[1][1];

    // R5=R4-a22
    r5[0][0]=r4[0][0]-A[M22];
    r5[0][1]=r4[0][1]-A[M23];
    r5[1][0]=r4[1][0]-A[M32];
    r5[1][1]=r4[1][1]-A[M33];

    // R6=inverse(R5)
    one_over_det=1.0F/((r5[0][0]*r5[1][1])-(r5[1][0]*r5[0][1]));
    r6[0][0]=one_over_det*r5[1][1];
    r6[0][1]=one_over_det*(-r5[0][1]);
    r6[1][0]=one_over_det*(-r5[1][0]);
    r6[1][1]=one_over_det*r5[0][0];

    // c12=R3xR6/
	C[M02]=r3[0][0]*r6[0][0]+r3[0][1]*r6[1][0];
	C[M03]=r3[0][0]*r6[0][1]+r3[0][1]*r6[1][1];
	C[M12]=r3[1][0]*r6[0][0]+r3[1][1]*r6[1][0];
	C[M13]=r3[1][0]*r6[0][1]+r3[1][1]*r6[1][1];

	// c21=R6xR2
	C[M20]=r6[0][0]*r2[0][0]+r6[0][1]*r2[1][0];
	C[M21]=r6[0][0]*r2[0][1]+r6[0][1]*r2[1][1];
	C[M30]=r6[1][0]*r2[0][0]+r6[1][1]*r2[1][0];
	C[M31]=r6[1][0]*r2[0][1]+r6[1][1]*r2[1][1];

	// R7=R3xc21
	r7[0][0]=r3[0][0]*C[M20]+r3[0][1]*C[M30];
	r7[0][1]=r3[0][0]*C[M21]+r3[0][1]*C[M31];
	r7[1][0]=r3[1][0]*C[M20]+r3[1][1]*C[M30];
	r7[1][1]=r3[1][0]*C[M21]+r3[1][1]*C[M31];

    // c11=R1-R7
    C[M00]=r1[0][0]-r7[0][0];
    C[M01]=r1[0][1]-r7[0][1];
    C[M10]=r1[1][0]-r7[1][0];
    C[M11]=r1[1][1]-r7[1][1];

    // c22=-R6
    C[M22]=-r6[0][0];
    C[M23]=-r6[0][1];
    C[M32]=-r6[1][0];
    C[M33]=-r6[1][1];

	return;
}

// Matrix multiply contributed by Thomas Malik
// c[16] = 4x4 dest matrix
// a[16] = 4x4 source matrix, also dest matrix if c = NULL
// b[16] = 4x4 transform matrix
void matProduct(float *c,float *a,float *b)
{
    int i,flag;

	float ai0,ai1,ai2,ai3;
	float tmp[16];

	flag=0;

	if(c == NULL)
	{
		c=tmp;
		flag=1;
	}

#define A(row,col) a[(col<<2)+row]
#define B(row,col) b[(col<<2)+row]
#define P(row,col) c[(col<<2)+row]

    for(i=0;i<4;i++)
    {
		ai0=A(i,0); ai1=A(i,1); ai2=A(i,2); ai3=A(i,3);

		P(i,0)=ai0*B(0,0)+ai1*B(1,0)+ai2*B(2,0)+ai3*B(3,0);
	    P(i,1)=ai0*B(0,1)+ai1*B(1,1)+ai2*B(2,1)+ai3*B(3,1);
	    P(i,2)=ai0*B(0,2)+ai1*B(1,2)+ai2*B(2,2)+ai3*B(3,2);
	    P(i,3)=ai0*B(0,3)+ai1*B(1,3)+ai2*B(2,3)+ai3*B(3,3);
    }

#undef A
#undef B
#undef P

    if(flag == 1) memcpy(a,c,sizeof(float)*16);

	return;
}

// c[3] = dest vector or NULL
// a[3] = source vector, also dest vector if c = NULL
// b[16] = 4x4 transform matrix
void matVectProduct(float *c,float *a,float *b)
{
    int flag;

	float tmp[3];

	flag=0;

	if(c == NULL)
	{
		c=tmp;
		flag=1;
	}

	c[0]=b[0]*a[0]+b[4]*a[1]+b[8]*a[2]+b[12];
	c[1]=b[1]*a[0]+b[5]*a[1]+b[9]*a[2]+b[13];
	c[2]=b[2]*a[0]+b[6]*a[1]+b[10]*a[2]+b[14];

    if(flag == 1) memcpy(a,c,sizeof(float)*3);

	return;
}

// c[3] = dest vector or NULL
// a[3] = source vector, also dest vector if c = NULL
// b[3] = transform vector
void matCrossProduct(float *c,float *a,float *b)
{
    int flag;

	float tmp[3];

	flag=0;

	if(c == NULL)
	{
		c=tmp;
		flag=1;
	}

	c[0]=a[1]*b[2]-a[2]*b[1];
	c[1]=-a[0]*b[2]+a[2]*b[0];
	c[2]=a[0]*b[1]-a[1]*b[0];

    if(flag == 1) memcpy(a,c,sizeof(float)*3);

	return;
}

void matIdentity(float *a)
{
    memcpy(a,identitymatrix,sizeof(float)*16);

	return;
}

void matTranslate(float *a,float x,float y,float z)
{
	a[12]=a[0]*x+a[4]*y+a[8]*z+a[12];
	a[13]=a[1]*x+a[5]*y+a[9]*z+a[13];
	a[14]=a[2]*x+a[6]*y+a[10]*z+a[14];
	a[15]=a[3]*x+a[7]*y+a[11]*z+a[15];

	return;
}

void matScale(float *a,float x,float y,float z)
{
    a[0]*=x; a[4]*=y; a[8]*=z;
    a[1]*=x; a[5]*=y; a[9]*=z;
    a[2]*=x; a[6]*=y; a[10]*=z;
    a[3]*=x; a[7]*=y; a[11]*=z;

	return;
}

void matRotate(float* a,float* axis,float angle)
{
    float mag,s,c;
    float xx,yy,zz,xy,yz,zx,xs,ys,zs,one_c;
    float x,y,z;
	float m[16];

    double rads;

	x=axis[0];
    y=axis[1];
    z=axis[2];

    rads=(double)angle*PI/180.0F;
    s=(float)sin(rads);
    c=(float)cos(rads);

    mag=(float)sqrt(x*x+y*y+z*z);
    if(mag == 0.0)
    {
	    matIdentity(m);
	    return;
    }

    x/=mag;
    y/=mag;
    z/=mag;

#define M(row,col) m[(col<<2)+row]

    xx=x*x;
    yy=y*y;
    zz=z*z;
    xy=x*y;
    yz=y*z;
    zx=z*x;
    xs=x*s;
    ys=y*s;
    zs=z*s;
    one_c=1.0F-c;

    M(0,0)=(one_c*xx)+c;
    M(0,1)=(one_c*xy)-zs;
    M(0,2)=(one_c*zx)+ys;
    M(0,3)=0.0F;

    M(1,0)=(one_c*xy)+zs;
    M(1,1)=(one_c*yy)+c;
    M(1,2)=(one_c*yz)-xs;
    M(1,3)=0.0F;

    M(2,0)=(one_c*zx)-ys;
    M(2,1)=(one_c*yz)+xs;
    M(2,2)=(one_c*zz)+c;
    M(2,3)=0.0F;

    M(3,0)=0.0F;
    M(3,1)=0.0F;
    M(3,2)=0.0F;
    M(3,3)=1.0F;

#undef M

	matProduct(NULL,a,m);
	
	return;
}

void matNormalize(float *a)
{
    float mag;

    mag=(float)sqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2]);
    if(mag != 0.0F)
    {
		a[0]/=mag;
		a[1]/=mag;
		a[2]/=mag;
    }

	return;
}

void matLookAt(float *a,float *aEye,float *aFocus,float *aUp)
{
    float m[16];
    float x[3],y[3],z[3];

    z[0]=aEye[0]-aFocus[0];
    z[1]=aEye[1]-aFocus[1];
    z[2]=aEye[2]-aFocus[2];

	matNormalize(z);
    
	y[0]=aUp[0];
    y[1]=aUp[1];
    y[2]=aUp[2];

	matCrossProduct(x,y,z);
	matNormalize(x);

	matCrossProduct(y,z,x);
	matNormalize(y);

#define M(row,col) m[(col<<2)+row]

    M(0,0)=x[0]; M(0,1)=x[1]; M(0,2)=x[2]; M(0,3)=0.0F;
    M(1,0)=y[0]; M(1,1)=y[1]; M(1,2)=y[2]; M(1,3)=0.0F;
    M(2,0)=z[0]; M(2,1)=z[1]; M(2,2)=z[2]; M(2,3)=0.0F;
    M(3,0)=0.0F; M(3,1)=0.0F; M(3,2)=0.0F; M(3,3)=1.0F;

#undef M

	matProduct(NULL,a,m);
	matTranslate(a,-aEye[0],-aEye[1],-aEye[2]);

	return;
}

void matPerspect(float *a,float fov,float aspect,float cnear,float cfar)
{
    float xmin,xmax,ymin,ymax;

    ymax=cnear*(float)tan(fov*PI/360.0F);
    ymin=-ymax;

    xmin=ymin*aspect;
    xmax=ymax*aspect;

    matFrustum(a,xmin,xmax,ymin,ymax,cnear,cfar);

	return;
}

void matFrustum(float *a,float left,float right,float bottom,float top,float cnear,float cfar)
{
    float x,y,aa,bb,cc,dd;
    float m[16];

    x=(2.0F*cnear)/(right-left);
    y=(2.0F*cnear)/(top-bottom);
    aa=(right+left)/(right-left);
    bb=(top+bottom)/(top-bottom);
    cc=-(cfar+cnear)/(cfar-cnear);
    dd=-(2.0F*cfar*cnear)/(cfar-cnear);

#define M(row,ccol) m[(ccol<<2)+row]

    M(0,0)=x;    M(0,1)=0.0F; M(0,2)=aa;    M(0,3)=0.0F;
    M(1,0)=0.0F; M(1,1)=y;    M(1,2)=bb;    M(1,3)=0.0F;
    M(2,0)=0.0F; M(2,1)=0.0F; M(2,2)=cc;    M(2,3)=dd;
    M(3,0)=0.0F; M(3,1)=0.0F; M(3,2)=-1.0F; M(3,3)=0.0F;

#undef M

	matProduct(NULL,a,m);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -