android-app-native/app/src/nativecode/rawdraw/CNFG3D.c

542 lines
13 KiB
C

//Copyright 2012-2017 <>< Charles Lohr
//You may license this file under the MIT/x11, NewBSD, or any GPL license.
//This is a series of tools useful for software rendering.
//Use of this file with OpenGL is untested.
#ifdef CNFG3D
#include "CNFG.h"
#ifdef __wasm__
double sin( double v );
double cos( double v );
double tan( double v );
double sqrt( double v );
float sinf( float v );
float cosf( float v );
float tanf( float v );
float sqrtf( float v );
void tdMATCOPY( float * x, const float * y )
{
int i;
for( i = 0; i < 16; i++ ) x[i] = y[i];
}
#else
#include <string.h>
#include <stdio.h>
#endif
#ifdef CNFG3D_USE_OGL_MAJOR
#define m00 0
#define m10 1
#define m20 2
#define m30 3
#define m01 4
#define m11 5
#define m21 6
#define m31 7
#define m02 8
#define m12 9
#define m22 10
#define m32 11
#define m03 12
#define m13 13
#define m23 14
#define m33 15
#else
#define m00 0
#define m01 1
#define m02 2
#define m03 3
#define m10 4
#define m11 5
#define m12 6
#define m13 7
#define m20 8
#define m21 9
#define m22 10
#define m23 11
#define m30 12
#define m31 13
#define m32 14
#define m33 15
#endif
void tdIdentity( float * f )
{
f[m00] = 1; f[m01] = 0; f[m02] = 0; f[m03] = 0;
f[m10] = 0; f[m11] = 1; f[m12] = 0; f[m13] = 0;
f[m20] = 0; f[m21] = 0; f[m22] = 1; f[m23] = 0;
f[m30] = 0; f[m31] = 0; f[m32] = 0; f[m33] = 1;
}
void tdZero( float * f )
{
f[m00] = 0; f[m01] = 0; f[m02] = 0; f[m03] = 0;
f[m10] = 0; f[m11] = 0; f[m12] = 0; f[m13] = 0;
f[m20] = 0; f[m21] = 0; f[m22] = 0; f[m23] = 0;
f[m30] = 0; f[m31] = 0; f[m32] = 0; f[m33] = 0;
}
void tdTranslate( float * f, float x, float y, float z )
{
float ftmp[16];
tdIdentity(ftmp);
ftmp[m03] += x;
ftmp[m13] += y;
ftmp[m23] += z;
tdMultiply( f, ftmp, f );
}
void tdScale( float * f, float x, float y, float z )
{
#if 0
f[m00] *= x;
f[m01] *= x;
f[m02] *= x;
f[m03] *= x;
f[m10] *= y;
f[m11] *= y;
f[m12] *= y;
f[m13] *= y;
f[m20] *= z;
f[m21] *= z;
f[m22] *= z;
f[m23] *= z;
#endif
float ftmp[16];
tdIdentity(ftmp);
ftmp[m00] *= x;
ftmp[m11] *= y;
ftmp[m22] *= z;
tdMultiply( f, ftmp, f );
}
void tdRotateAA( float * f, float angle, float ix, float iy, float iz )
{
float ftmp[16];
float c = tdCOS( angle*tdDEGRAD );
float s = tdSIN( angle*tdDEGRAD );
float absin = tdSQRT( ix*ix + iy*iy + iz*iz );
float x = ix/absin;
float y = iy/absin;
float z = iz/absin;
ftmp[m00] = x*x*(1-c)+c;
ftmp[m01] = x*y*(1-c)-z*s;
ftmp[m02] = x*z*(1-c)+y*s;
ftmp[m03] = 0;
ftmp[m10] = y*x*(1-c)+z*s;
ftmp[m11] = y*y*(1-c)+c;
ftmp[m12] = y*z*(1-c)-x*s;
ftmp[m13] = 0;
ftmp[m20] = x*z*(1-c)-y*s;
ftmp[m21] = y*z*(1-c)+x*s;
ftmp[m22] = z*z*(1-c)+c;
ftmp[m23] = 0;
ftmp[m30] = 0;
ftmp[m31] = 0;
ftmp[m32] = 0;
ftmp[m33] = 1;
tdMultiply( f, ftmp, f );
}
void tdRotateQuat( float * f, float qw, float qx, float qy, float qz )
{
float ftmp[16];
//float qw2 = qw*qw;
float qx2 = qx*qx;
float qy2 = qy*qy;
float qz2 = qz*qz;
ftmp[m00] = 1 - 2*qy2 - 2*qz2;
ftmp[m01] = 2*qx*qy - 2*qz*qw;
ftmp[m02] = 2*qx*qz + 2*qy*qw;
ftmp[m03] = 0;
ftmp[m10] = 2*qx*qy + 2*qz*qw;
ftmp[m11] = 1 - 2*qx2 - 2*qz2;
ftmp[m12] = 2*qy*qz - 2*qx*qw;
ftmp[m13] = 0;
ftmp[m20] = 2*qx*qz - 2*qy*qw;
ftmp[m21] = 2*qy*qz + 2*qx*qw;
ftmp[m22] = 1 - 2*qx2 - 2*qy2;
ftmp[m23] = 0;
ftmp[m30] = 0;
ftmp[m31] = 0;
ftmp[m32] = 0;
ftmp[m33] = 1;
tdMultiply( f, ftmp, f );
}
void tdRotateEA( float * f, float x, float y, float z )
{
float ftmp[16];
//x,y,z must be negated for some reason
float X = -x*2*tdQ_PI/360; //Reduced calulation for speed
float Y = -y*2*tdQ_PI/360;
float Z = -z*2*tdQ_PI/360;
float cx = tdCOS(X);
float sx = tdSIN(X);
float cy = tdCOS(Y);
float sy = tdSIN(Y);
float cz = tdCOS(Z);
float sz = tdSIN(Z);
//Row major (unless CNFG3D_USE_OGL_MAJOR is selected)
//manually transposed
ftmp[m00] = cy*cz;
ftmp[m10] = (sx*sy*cz)-(cx*sz);
ftmp[m20] = (cx*sy*cz)+(sx*sz);
ftmp[m30] = 0;
ftmp[m01] = cy*sz;
ftmp[m11] = (sx*sy*sz)+(cx*cz);
ftmp[m21] = (cx*sy*sz)-(sx*cz);
ftmp[m31] = 0;
ftmp[m02] = -sy;
ftmp[m12] = sx*cy;
ftmp[m22] = cx*cy;
ftmp[m32] = 0;
ftmp[m03] = 0;
ftmp[m13] = 0;
ftmp[m23] = 0;
ftmp[m33] = 1;
tdMultiply( f, ftmp, f );
}
void tdMultiply( float * fin1, float * fin2, float * fout )
{
float fotmp[16];
int i, k;
#ifdef CNFG3D_USE_OGL_MAJOR
fotmp[m00] = fin1[m00] * fin2[m00] + fin1[m01] * fin2[m10] + fin1[m02] * fin2[m20] + fin1[m03] * fin2[m30];
fotmp[m01] = fin1[m00] * fin2[m01] + fin1[m01] * fin2[m11] + fin1[m02] * fin2[m21] + fin1[m03] * fin2[m31];
fotmp[m02] = fin1[m00] * fin2[m02] + fin1[m01] * fin2[m12] + fin1[m02] * fin2[m22] + fin1[m03] * fin2[m32];
fotmp[m03] = fin1[m00] * fin2[m03] + fin1[m01] * fin2[m13] + fin1[m02] * fin2[m23] + fin1[m03] * fin2[m33];
fotmp[m10] = fin1[m10] * fin2[m00] + fin1[m11] * fin2[m10] + fin1[m12] * fin2[m20] + fin1[m13] * fin2[m30];
fotmp[m11] = fin1[m10] * fin2[m01] + fin1[m11] * fin2[m11] + fin1[m12] * fin2[m21] + fin1[m13] * fin2[m31];
fotmp[m12] = fin1[m10] * fin2[m02] + fin1[m11] * fin2[m12] + fin1[m12] * fin2[m22] + fin1[m13] * fin2[m32];
fotmp[m13] = fin1[m10] * fin2[m03] + fin1[m11] * fin2[m13] + fin1[m12] * fin2[m23] + fin1[m13] * fin2[m33];
fotmp[m20] = fin1[m20] * fin2[m00] + fin1[m21] * fin2[m10] + fin1[m22] * fin2[m20] + fin1[m23] * fin2[m30];
fotmp[m21] = fin1[m20] * fin2[m01] + fin1[m21] * fin2[m11] + fin1[m22] * fin2[m21] + fin1[m23] * fin2[m31];
fotmp[m22] = fin1[m20] * fin2[m02] + fin1[m21] * fin2[m12] + fin1[m22] * fin2[m22] + fin1[m23] * fin2[m32];
fotmp[m23] = fin1[m20] * fin2[m03] + fin1[m21] * fin2[m13] + fin1[m22] * fin2[m23] + fin1[m23] * fin2[m33];
fotmp[m30] = fin1[m30] * fin2[m00] + fin1[m31] * fin2[m10] + fin1[m32] * fin2[m20] + fin1[m33] * fin2[m30];
fotmp[m31] = fin1[m30] * fin2[m01] + fin1[m31] * fin2[m11] + fin1[m32] * fin2[m21] + fin1[m33] * fin2[m31];
fotmp[m32] = fin1[m30] * fin2[m02] + fin1[m31] * fin2[m12] + fin1[m32] * fin2[m22] + fin1[m33] * fin2[m32];
fotmp[m33] = fin1[m30] * fin2[m03] + fin1[m31] * fin2[m13] + fin1[m32] * fin2[m23] + fin1[m33] * fin2[m33];
#else
for( i = 0; i < 16; i++ )
{
int xp = i & 0x03;
int yp = i & 0x0c;
fotmp[i] = 0;
for( k = 0; k < 4; k++ )
{
fotmp[i] += fin1[yp+k] * fin2[(k<<2)|xp];
}
}
#endif
tdMATCOPY( fout, fotmp );
}
#ifndef __wasm__
void tdPrint( const float * f )
{
int i;
printf( "{\n" );
#ifdef CNFG3D_USE_OGL_MAJOR
for( i = 0; i < 4; i++ )
{
printf( " %f, %f, %f, %f\n", f[0+i], f[4+i], f[8+i], f[12+i] );
}
#else
for( i = 0; i < 16; i+=4 )
{
printf( " %f, %f, %f, %f\n", f[0+i], f[1+i], f[2+i], f[3+i] );
}
#endif
printf( "}\n" );
}
#endif
void tdTransposeSelf( float * f )
{
float fout[16];
fout[m00] = f[m00]; fout[m01] = f[m10]; fout[m02] = f[m20]; fout[m03] = f[m30];
fout[m10] = f[m01]; fout[m11] = f[m11]; fout[m12] = f[m21]; fout[m13] = f[m31];
fout[m20] = f[m02]; fout[m21] = f[m12]; fout[m22] = f[m22]; fout[m23] = f[m32];
fout[m30] = f[m03]; fout[m31] = f[m13]; fout[m32] = f[m23]; fout[m33] = f[m33];
tdMATCOPY( f, fout );
}
void tdPerspective( float fovy, float aspect, float zNear, float zFar, float * out )
{
float f = 1./tdTAN(fovy * tdQ_PI / 360.0);
out[m00] = f/aspect; out[m01] = 0; out[m02] = 0; out[m03] = 0;
out[m10] = 0; out[m11] = f; out[m12] = 0; out[m13] = 0;
out[m20] = 0; out[m21] = 0;
out[m22] = (zFar + zNear)/(zNear - zFar);
out[m23] = 2*zFar*zNear /(zNear - zFar);
out[m30] = 0; out[m31] = 0; out[m32] = -1; out[m33] = 0;
}
void tdLookAt( float * m, float * eye, float * at, float * up )
{
float out[16];
float F[3] = { at[0] - eye[0], at[1] - eye[1], at[2] - eye[2] };
float fdiv = 1./tdSQRT( F[0]*F[0] + F[1]*F[1] + F[2]*F[2] );
float f[3] = { F[0]*fdiv, F[1]*fdiv, F[2]*fdiv };
float udiv = 1./tdSQRT( up[0]*up[0] + up[1]*up[1] + up[2]*up[2] );
float UP[3] = { up[0]*udiv, up[1]*udiv, up[2]*udiv };
float s[3];
float u[3];
tdCross( f, UP, s );
tdCross( s, f, u );
out[m00] = s[0]; out[m01] = s[1]; out[m02] = s[2]; out[m03] = 0;
out[m10] = u[0]; out[m11] = u[1]; out[m12] = u[2]; out[m13] = 0;
out[m20] = -f[0];out[m21] =-f[1]; out[m22] =-f[2]; out[m23] = 0;
out[m30] = 0; out[m31] = 0; out[m32] = 0; out[m33] = 1;
tdMultiply( m, out, m );
tdTranslate( m, -eye[0], -eye[1], -eye[2] );
}
void tdPTransform( const float * pin, float * f, float * pout )
{
float ptmp[2];
ptmp[0] = pin[0] * f[m00] + pin[1] * f[m01] + pin[2] * f[m02] + f[m03];
ptmp[1] = pin[0] * f[m10] + pin[1] * f[m11] + pin[2] * f[m12] + f[m13];
pout[2] = pin[0] * f[m20] + pin[1] * f[m21] + pin[2] * f[m22] + f[m23];
pout[0] = ptmp[0];
pout[1] = ptmp[1];
}
void tdVTransform( const float * pin, float * f, float * pout )
{
float ptmp[2];
ptmp[0] = pin[0] * f[m00] + pin[1] * f[m01] + pin[2] * f[m02];
ptmp[1] = pin[0] * f[m10] + pin[1] * f[m11] + pin[2] * f[m12];
pout[2] = pin[0] * f[m20] + pin[1] * f[m21] + pin[2] * f[m22];
pout[0] = ptmp[0];
pout[1] = ptmp[1];
}
void td4Transform( float * pin, float * f, float * pout )
{
float ptmp[3];
ptmp[0] = pin[0] * f[m00] + pin[1] * f[m01] + pin[2] * f[m02] + pin[3] * f[m03];
ptmp[1] = pin[0] * f[m10] + pin[1] * f[m11] + pin[2] * f[m12] + pin[3] * f[m13];
ptmp[2] = pin[0] * f[m20] + pin[1] * f[m21] + pin[2] * f[m22] + pin[3] * f[m23];
pout[3] = pin[0] * f[m30] + pin[1] * f[m31] + pin[2] * f[m32] + pin[3] * f[m33];
pout[0] = ptmp[0];
pout[1] = ptmp[1];
pout[2] = ptmp[2];
}
void td4RTransform( float * pin, float * f, float * pout )
{
float ptmp[3];
ptmp[0] = pin[0] * f[m00] + pin[1] * f[m10] + pin[2] * f[m20] + pin[3] * f[m30];
ptmp[1] = pin[0] * f[m01] + pin[1] * f[m11] + pin[2] * f[m21] + pin[3] * f[m31];
ptmp[2] = pin[0] * f[m02] + pin[1] * f[m12] + pin[2] * f[m22] + pin[3] * f[m32];
pout[3] = pin[0] * f[m03] + pin[1] * f[m13] + pin[2] * f[m23] + pin[3] * f[m33];
pout[0] = ptmp[0];
pout[1] = ptmp[1];
pout[2] = ptmp[2];
}
void tdNormalizeSelf( float * vin )
{
float vsq = 1./tdSQRT(vin[0]*vin[0] + vin[1]*vin[1] + vin[2]*vin[2]);
vin[0] *= vsq;
vin[1] *= vsq;
vin[2] *= vsq;
}
void tdCross( float * va, float * vb, float * vout )
{
float vtmp[2];
vtmp[0] = va[1] * vb[2] - va[2] * vb[1];
vtmp[1] = va[2] * vb[0] - va[0] * vb[2];
vout[2] = va[0] * vb[1] - va[1] * vb[0];
vout[0] = vtmp[0];
vout[1] = vtmp[1];
}
float tdDistance( float * va, float * vb )
{
float dx = va[0]-vb[0];
float dy = va[1]-vb[1];
float dz = va[2]-vb[2];
return tdSQRT(dx*dx + dy*dy + dz*dz);
}
float tdDot( float * va, float * vb )
{
return va[0]*vb[0] + va[1]*vb[1] + va[2]*vb[2];
}
//Stack functionality.
static float gsMatricies[2][tdMATRIXMAXDEPTH][16];
float * gSMatrix = gsMatricies[0][0];
static int gsMMode;
static int gsMPlace[2];
void tdPush()
{
if( gsMPlace[gsMMode] > tdMATRIXMAXDEPTH - 2 )
return;
tdMATCOPY( gsMatricies[gsMMode][gsMPlace[gsMMode] + 1], gsMatricies[gsMMode][gsMPlace[gsMMode]] );
gsMPlace[gsMMode]++;
gSMatrix = gsMatricies[gsMMode][gsMPlace[gsMMode]];
}
void tdPop()
{
if( gsMPlace[gsMMode] < 1 )
return;
gsMPlace[gsMMode]--;
gSMatrix = gsMatricies[gsMMode][gsMPlace[gsMMode]];
}
void tdMode( int mode )
{
if( mode < 0 || mode > 1 )
return;
gsMMode = mode;
gSMatrix = gsMatricies[gsMMode][gsMPlace[gsMMode]];
}
static float translateX;
static float translateY;
static float scaleX;
static float scaleY;
void tdSetViewport( float leftx, float topy, float rightx, float bottomy, float pixx, float pixy )
{
translateX = leftx;
translateY = bottomy;
scaleX = pixx/(rightx-leftx);
scaleY = pixy/(topy-bottomy);
}
void tdFinalPoint( float * pin, float * pout )
{
float tdin[4] = { pin[0], pin[1], pin[2], 1. };
float tmp[4];
td4Transform( tdin, gsMatricies[0][gsMPlace[0]], tmp );
// printf( "XFORM1Out: %f %f %f %f\n", tmp[0], tmp[1], tmp[2], tmp[3] );
td4Transform( tmp, gsMatricies[1][gsMPlace[1]], tmp );
// printf( "XFORM2Out: %f %f %f %f\n", tmp[0], tmp[1], tmp[2], tmp[3] );
pout[0] = (tmp[0]/tmp[3] - translateX) * scaleX;
pout[1] = (tmp[1]/tmp[3] - translateY) * scaleY;
pout[2] = tmp[2]/tmp[3];
// printf( "XFORMFOut: %f %f %f\n", pout[0], pout[1], pout[2] );
}
float tdNoiseAt( int x, int y )
{
return ((x*13241*y + y * 33455927)%9293) / 4646. - 1.0;
}
static inline float tdFade( float f )
{
float ft3 = f*f*f;
return ft3 * 10 - ft3 * f * 15 + 6 * ft3 * f * f;
}
float tdFLerp( float a, float b, float t )
{
float fr = tdFade( t );
return a * (1.-fr) + b * fr;
}
static inline float tdFNoiseAt( float x, float y )
{
int ix = x;
int iy = y;
float fx = x - ix;
float fy = y - iy;
float a = tdNoiseAt( ix, iy );
float b = tdNoiseAt( ix+1, iy );
float c = tdNoiseAt( ix, iy+1 );
float d = tdNoiseAt( ix+1, iy+1 );
float top = tdFLerp( a, b, fx );
float bottom = tdFLerp( c, d, fx );
return tdFLerp( top, bottom, fy );
}
float tdPerlin2D( float x, float y )
{
int ndepth = 5;
int depth;
float ret = 0;
for( depth = 0; depth < ndepth; depth++ )
{
float nx = x / (1<<(ndepth-depth-1));
float ny = y / (1<<(ndepth-depth-1));
ret += tdFNoiseAt( nx, ny ) / (1<<(depth+1));
}
return ret;
}
#endif