216 lines
4.5 KiB
C++
216 lines
4.5 KiB
C++
// 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<max; z++ )
|
|
{
|
|
int zm = z*max;
|
|
|
|
for( x=0;x<max;x++ )
|
|
{
|
|
val[zm+x] = SRANDOM;
|
|
}
|
|
}
|
|
|
|
|
|
if(bLoop)
|
|
{
|
|
for( z=0; z<max; z++ )
|
|
{
|
|
val[z*max+0] = val[z*max+max-1];
|
|
val[z*max+1] = val[z*max+max-2];
|
|
}
|
|
|
|
for( x=0; x<max; x++ )
|
|
{
|
|
val[0*max+x] = val[(max-1)*max+x];
|
|
val[1*max+x] = val[(max-2)*max+x];
|
|
}
|
|
}
|
|
|
|
// interpolate horizontal lines through knots
|
|
float *pOldHList = hlist;
|
|
for( i=0;i<max;i++ )
|
|
{
|
|
knots = &val[i*max];
|
|
xk = 0;
|
|
for( x=0;x<xres;x++ )
|
|
{
|
|
// Incremental pointer is faster
|
|
*hlist++ = Spline( xk/dfx,/* 4,*/ knots );
|
|
xk += 1.0f;
|
|
if( xk >= dfx )
|
|
{
|
|
xk -= dfx;
|
|
knots++;
|
|
}
|
|
}
|
|
}
|
|
hlist = pOldHList;
|
|
|
|
// interpolate all vertical lines
|
|
float *pOldBuf = buf;
|
|
for( x=0;x<xres;x++ )
|
|
{
|
|
zk = 0;
|
|
knots = zknots;
|
|
// build knot list
|
|
for( i=0;i<max;i++ )
|
|
{
|
|
knots[i] = hlist[i*xres+x];
|
|
}
|
|
|
|
for( z=0;z<zres;z++ )
|
|
{
|
|
// Incremental pointer is *much* faster
|
|
*buf++ = Spline( zk/dfz, /*4,*/ knots ) * zscale;
|
|
|
|
zk += 1.0f;
|
|
if( zk >= 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;z<zres;z++ )
|
|
{
|
|
pArray2 = pArray[z];
|
|
for( x=0;x<xres;x++ )
|
|
//hBuf->m_Array[z][x] += buf[z*xres+x];
|
|
pArray2 [x] += *buf++;
|
|
}
|
|
|
|
free( val );
|
|
free( pOldBuf );
|
|
free( pOldHList );
|
|
free( zknots );
|
|
}
|
|
|
|
#pragma warning (pop) |