/* ** Command & Conquer Renegade(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ /* This file contains some math functions that Jan worked on while visiting westwood between Meltdown and Siggraph 2001. */ #include #include #include #include "p_timer.h" #include "wwmath.h" using namespace std; #undef for #define for if(false); else for /* (1-u)(1-u)(1-u) --------------- 1/6 0/6 6 3*u*u*u - 6u*u +4 --------------- 4/6 1/6 6 -3*u*u*u + 3*u*u + 3*u + 1 --------------- 1/6 4/6 6 u*u*u --------------- 0/6 1/6 6 */ const double pi = 3.1415926535897932384626433832795; const int SINTABLESIZE = 16; float sinTable[SINTABLESIZE+1][3]; /* float sinTable[SINTABLESIZE+1][3] = { 0.f, 0.0327249329938f, 0.0654498139838f, 0.0980171403296f, 0.130584524375f, 0.16299423692f, 0.195090322016f, 0.22718650856f, 0.258968953094f, 0.290284677254f, 0.321600570763f, 0.352449632798f, 0.382683432365f, 0.412917427848f, 0.442536062284f, 0.471396736826f, 0.5002577f, 0.528360611467f, 0.55557023302f, 0.582780177536f, 0.609096734804f, 0.634393284164f, 0.659690191419f, 0.683966978964f, 0.707106781187f, 0.730247032377f, 0.752250161646f, 0.773010453363f, 0.79377112016f, 0.813288873188f, 0.831469612303f, 0.849650815039f, 0.866495135964f, 0.881921264348f, 0.897347904711f, 0.911356511164f, 0.923879532511f, 0.936403079986f, 0.947441092993f, 0.956940335732f, 0.966440181792f, 0.974401217255f, 0.980785280403f, 0.987169903631f, 0.991977366409f, 0.995184726672f, 0.998392578191f, 1.0000003005f, 1.f, 1.0000003005f, 0.998392578191f, }; */ void init_bez_sin() { for(int i=0; i 1.0) continue; if(z*dz < 0.0 || z*dz > 1.0) continue; double yerr, zerr; // if(by > y) // yerr = by/y; // else yerr = y/by; // if(bz > z) // zerr = bz/z; // else zerr = z/bz; yerr -= 1.0; zerr -= 1.0; double se = yerr*yerr + zerr*zerr; if(mse > se) { wy = se; wz = se; mse = se; my = dy; mz = dz; b = false; } else { // if(se > wy) // b = true; // if(se > wz) // break; } } // if(b) // break; } sinTable[i][0] = float(x); sinTable[i][1] = float(y * my); sinTable[i][2] = float(z * mz); cout << setprecision(12); cout << setw(16) << x << "f, " << setw(16) << y*my << "f, " << setw(16) << z*mz << "f," << endl; } } const int ACOSTABLESIZE = 32; //float acosTable[ACOSTABLESIZE+1][3]; float acosTable[ACOSTABLESIZE+1][3] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.09439510239f, 2.07033956061f, 2.04678164613f, 2.02361292154f, 2.00044498842f, 1.97766674853f, 1.95519310129f, 1.93271994669f, 1.91055213001f, 1.88862003072f, 1.86668845355f, 1.84499333386f, 1.82347658194f, 1.80196011523f, 1.7806223216f, 1.75941271297f, 1.73820326172f, 1.71712229397f, 1.69612415796f, 1.67512622765f, 1.65421121018f, 1.63333708859f, 1.61246303408f, 1.59162963139f, 1.57079632679f, 1.54996304584f, 1.52912960772f, 1.508255565f, 1.48738138962f, 1.46646655946f, 1.44546849563f, 1.42447034954f, 1.40338938542f, 1.38217994062f, 1.36097042076f, 1.33963248005f, 1.31811607165f, 1.29659929615f, 1.27490425438f, 1.25297262287f, 1.23104063033f, 1.20887262684f, 1.1863995523f, 1.16392587108f, 1.14114765337f, 1.11797973205f, 1.09481095108f, 1.07125317716f, 1.0471975512f, 1.0231405f, 0.998586616212f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; double calc_cos_plus_45(double cx) { double sx = sqrt(1-cx*cx); cx = cx*cos(pi/4) - sx*sin(pi/4); return cx; } void init_bez_acos() { for(int i=0; i ACOSTABLESIZE/4*3) // continue; double x = acos(float(i*3)/(ACOSTABLESIZE*3)*2-1); double y = acos(float(i*3+1)/(ACOSTABLESIZE*3)*2-1); // * 1.00053f; double z = acos(float(i*3+2)/(ACOSTABLESIZE*3)*2-1); // * 1.00053f; double w; if(i != ACOSTABLESIZE-1) w = acos(float(i*3+3)/(ACOSTABLESIZE*3)*2-1); else w = 0.0;//-acos(float(i*3+1)/(ACOSTABLESIZE*3)*2-1); double mse = 4.0; double my = 1.0; double mz = 1.0; double wy = 4.0; for(double dy=0.9996944; dy<=1.0006926; dy+=16.0/8388608) { bool b = false; double wz = 4.0; for(double dz=0.9997872; dz<=1.0011092; dz+=16.0/8388608) { double by = x * 8.0 / 27.0 + y * dy * 12.0 / 27.0 + z * dz * 6.0 / 27.0 + w / 27.0; double bz = x / 27.0 + y * dy * 6.0 / 27.0 + z * dz * 12.0 / 27.0 + w * 8.0 / 27.0; if(y*dy < 0.0 || y*dy > pi) continue; if(z*dz < 0.0 || z*dz > pi) continue; double yerr, zerr; // if(by > y) // yerr = by/y; // else yerr = y/by; // if(bz > z) // zerr = bz/z; // else zerr = z/bz; yerr -= 1.0; zerr -= 1.0; double se = yerr*yerr + zerr*zerr; if(mse > se) { wy = se; wz = se; mse = se; my = dy; mz = dz; b = false; } else { // if(se > wy) // b = true; // if(se > wz) // break; } } // if(b) // break; } acosTable[i][0] = float(x); acosTable[i][1] = float(y * my); acosTable[i][2] = float(z * mz); cout << setprecision(12); cout << setw(16) << x << "f, " << setw(16) << y*my << "f, " << setw(16) << z*mz << "f," << endl; // cout << my << " " << mz << endl; } acosTable[ACOSTABLESIZE][0] = 0.f; } float bez_sin(float x) { x *= (SINTABLESIZE*4)/(pi*2); int ix0 = int(floor(x)); float u = x - ix0; float nu = 1.f-u; float sign = 1.f; ix0 &= SINTABLESIZE*4-1; if(ix0 >= SINTABLESIZE*2) { sign = -1.f; ix0 -= SINTABLESIZE*2; } if(ix0 >= SINTABLESIZE) { ix0 = (SINTABLESIZE-1)-(ix0-SINTABLESIZE); float t = u; u = nu; nu = t; } int ix1 = ix0+1; // ix0 &= SINTABLESIZE-1; // ix1 &= SINTABLESIZE-1; float u2 = u*u; float nu2 = nu*nu; float r0 = sinTable[ix0][0] * nu2 * nu; float r1 = sinTable[ix0][1] * 3 * u * nu2; float r2 = sinTable[ix0][2] * 3 * u2 * nu; float r3 = sinTable[ix1][0] * u2 * u; r0 += r1; r2 += r3; return (r0+r2) * sign; } float bez_acos(float x) { // double sx = sqrt(1-x*x); // x = x*cos(pi/4) - sx*sin(pi/4); x = calc_cos_plus_45(x); x += 1.f; x *= ACOSTABLESIZE/2; int ix0 = int(floor(x)); float u = x - ix0; float nu = 1.f-u; if(ix0 < 0) return pi-pi/4; // -infinite... if(ix0 >= ACOSTABLESIZE) return 0.f; int ix1 = ix0+1; float u2 = u*u; float nu2 = nu*nu; float r0 = acosTable[ix0][0] * nu2 * nu; float r1 = acosTable[ix0][1] * 3 * u * nu2; float r2 = acosTable[ix0][2] * 3 * u2 * nu; float r3 = acosTable[ix1][0] * u2 * u; r0 += r1; r2 += r3; return (r0+r2)-pi/4; } float mcos(float c, float m) { float ac = acos(c); float c1 = cos(ac*m); float c2 = cos(ac*(1-m)); float c3 = c * cos(m); return c1; } float cheb_asin(float x) { float table[] = { 1.101460576f, +.5764093225f, -.09735417608f, +.003083774398f, -.000844493744f, +.005722363752f, -.005962135984f }; float r = table[0] + table[1]*x; r -= sqrt(1-x*x); x = 2.f*x-1.f; float x2 = x; x *= x; for(int i=2; i 0.707106781186547524400844362104849f) { x = 0.707106781186547524400844362104849f - (x-0.707106781186547524400844362104849f); flip = true; } float r = 1.57079632679489661923132169163975f; float x2 = x*x; for(int i=0; i(&f); // take bit pattern of float into a register int sign = (a>>31); // sign = 0xFFFFFFFF if original value is negative, 0 if positive int mantissa = (a&((1<<23)-1))|(1<<23); // extract mantissa and add the hidden bit int exponent = ((a&0x7fffffff)>>23)-127; // extract the exponent int r = (unsigned int(mantissa)<<8)>>(31-exponent); // ((1<>24 -- (we know that mantissa > (1<<24)) return ((r ^ (sign)) - sign ) &~ (exponent>>31); // add original sign. If exponent was negative, make return value 0. } int intFloor (const float& f) { int a = *reinterpret_cast(&f); // take bit pattern of float into a register int sign = (a>>31); // sign = 0xFFFFFFFF if original value is negative, 0 if positive a&=0x7fffffff; // we don't need the sign any more int exponent = (a>>23)-127; // extract the exponent int expsign = ~(exponent>>31); // 0xFFFFFFFF if exponent is positive, 0 otherwise int imask = ( (1<<(31-(exponent))))-1; // mask for true integer values int mantissa = (a&((1<<23)-1)); // extract mantissa (without the hidden bit) int r = (unsigned int(mantissa|(1<<23))<<8)>>(31-exponent); // ((1<>24 -- (we know that mantissa > (1<<24)) r = ((r & expsign) ^ (sign)) + ((!((mantissa<<8)&imask)&(expsign^((a-1)>>31)))&sign); // if (fabs(value)<1.0) value = 0; copy sign; if (value < 0 && value==(int)(value)) value++; return r; } const int CACHE_TRASH_BUFFER_SIZE = 4024000; int * CacheTrashBuffer = NULL; volatile int ReadVar; void trash_the_cache(void) { // read a million random bytes and overwrite them with a new value for (int j=0; j<1024000; j++) { int address = rand() % CACHE_TRASH_BUFFER_SIZE; ReadVar = CacheTrashBuffer[address]; CacheTrashBuffer[address] = ReadVar+1; //cout<