// Noise.cpp: implementation of the CNoise class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "Noise.h" #include "Util\DynamicArray2D.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif #pragma warning (push) #pragma warning (disable : 4244) ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CNoise::CNoise() { } CNoise::~CNoise() { } __forceinline float CNoise::Spline( float x, float *knot ) { /* * spline(...) * * interpolate a 1d spline * taken from _Texturing & Modeling: A Procedural Approach_ * chapter 2 - by Darwyn Peachey */ // Const is a bit faster, nknots does not need to be of different size const int nknots = 4; const int nspans = nknots - 3; int span; float c0, c1, c2, c3; // coefficients of the cubic /* if( nspans < 1) { // illegal return 0; } */ // find the appropriate 4-point span of the spline x = (x < 0 ? 0 : (x > 1 ? 1 : x)) * nspans; span = ftoi(x); // Slow cast is already fast because of the overloaded C float/int conversion if( span >= nknots -3 ) span = nknots - 3; x -= span; knot += span; // evaluate the span cubic at x using horner's rule c3 = CR00*knot[0] + CR01*knot[1] + CR02*knot[2] + CR03*knot[3]; c2 = CR10*knot[0] + CR11*knot[1] + CR12*knot[2] + CR13*knot[3]; c1 = CR20*knot[0] + CR21*knot[1] + CR22*knot[2] + CR23*knot[3]; c0 = CR30*knot[0] + CR31*knot[1] + CR32*knot[2] + CR33*knot[3]; return ((c3*x + c2)*x + c1)*x + c0; } void CNoise::FracSynthPass( CDynamicArray2D *hBuf, float freq, float zscale, int xres, int zres, BOOL bLoop ) { // WARNING: Function is messy like hell, and lots of dirty optimisation is used... /* * FracSynthPass(...) * * generate basic points * interpolate along spline & scale * add to existing hbuffer */ int i; int x, z; float *val; float dfx, dfz; float *zknots, *knots; float xk, zk; float *hlist; float *buf; // how many to generate (need 4 extra for smooth 2d spline interpolation) const int max = freq + 2; // delta x and z - pixels per spline segment dfx = xres / (freq-1); dfz = zres / (freq-1); // the generated values - to be equally spread across buf val = (float*)calloc( sizeof(float)*max*max, 1 ); if(!val) { CLogFile::WriteLine("Critical calloc error during noise calculation !"); return; } // intermediately calculated spline knots (for 2d) zknots = (float*)calloc( sizeof(float)*max, 1 ); if(!zknots) { CLogFile::WriteLine("Critical calloc error during noise calculation !"); return; } // horizontal lines through knots hlist = (float*)calloc( sizeof(float)*max*xres, 1 ); if(!hlist) { CLogFile::WriteLine("Critical calloc error during noise calculation !"); return; } // local buffer - to be added to hbuf buf = (float*)calloc( sizeof(float)*xres*zres, 1 ); if(!buf) { CLogFile::WriteLine("Critical calloc error during noise calculation !"); return; } // start at -dfx, -dfz - generate knots for( z=0; z= dfx ) { xk -= dfx; knots++; } } } hlist = pOldHList; // interpolate all vertical lines float *pOldBuf = buf; for( x=0;x= dfz ) { zk -= dfz; knots++; } } } buf = pOldBuf; // update hBuf (Some hacks are used to get around the pointer overhead) float **pArray = hBuf->m_Array; float *pArray2 = NULL; for( z=0;zm_Array[z][x] += buf[z*xres+x]; pArray2 [x] += *buf++; } free( val ); free( pOldBuf ); free( pOldHList ); free( zknots ); } #pragma warning (pop)