1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087 |
- #include "../server/exe_headers.h"
- #include "cm_local.h"
- #include "cm_patch.h"
- #include "cm_landscape.h"
- #include "../game/genericparser2.h"
- #include "cm_randomterrain.h"
- #define NOISE_SIZE 256
- #define NOISE_MASK (NOISE_SIZE - 1)
- static float noiseTable[NOISE_SIZE];
- static int noisePerm[NOISE_SIZE];
- static void CM_NoiseInit( CCMLandScape *landscape )
- {
- int i;
- for ( i = 0; i < NOISE_SIZE; i++ )
- {
- noiseTable[i] = landscape->flrand(-1.0f, 1.0f);
- noisePerm[i] = (byte)landscape->irand(0, 255);
- }
- }
- #define VAL( a ) noisePerm[ ( a ) & ( NOISE_MASK )]
- #define INDEX( x, y, z, t ) VAL( x + VAL( y + VAL( z + VAL( t ) ) ) )
- #define LERP( a, b, w ) ( a * ( 1.0f - w ) + b * w )
- static float GetNoiseValue( int x, int y, int z, int t )
- {
- int index = INDEX( ( int ) x, ( int ) y, ( int ) z, ( int ) t );
- return noiseTable[index];
- }
- #if 0
- static float GetNoiseTime( int t )
- {
- int index = VAL( t );
- return (1 + noiseTable[index]);
- }
- #endif
- static float CM_NoiseGet4f( float x, float y, float z, float t )
- {
- int i;
- int ix, iy, iz, it;
- float fx, fy, fz, ft;
- float front[4];
- float back[4];
- float fvalue, bvalue, value[2], finalvalue;
- ix = ( int ) floor( x );
- fx = x - ix;
- iy = ( int ) floor( y );
- fy = y - iy;
- iz = ( int ) floor( z );
- fz = z - iz;
- it = ( int ) floor( t );
- ft = t - it;
- for ( i = 0; i < 2; i++ )
- {
- front[0] = GetNoiseValue( ix, iy, iz, it + i );
- front[1] = GetNoiseValue( ix+1, iy, iz, it + i );
- front[2] = GetNoiseValue( ix, iy+1, iz, it + i );
- front[3] = GetNoiseValue( ix+1, iy+1, iz, it + i );
- back[0] = GetNoiseValue( ix, iy, iz + 1, it + i );
- back[1] = GetNoiseValue( ix+1, iy, iz + 1, it + i );
- back[2] = GetNoiseValue( ix, iy+1, iz + 1, it + i );
- back[3] = GetNoiseValue( ix+1, iy+1, iz + 1, it + i );
- fvalue = LERP( LERP( front[0], front[1], fx ), LERP( front[2], front[3], fx ), fy );
- bvalue = LERP( LERP( back[0], back[1], fx ), LERP( back[2], back[3], fx ), fy );
- value[i] = LERP( fvalue, bvalue, fz );
- }
- finalvalue = LERP( value[0], value[1], ft );
- return finalvalue;
- }
- /****** lincrv.c ******/
- /* Ken Shoemake, 1994 */
- /* Perform a generic vector unary operation. */
- #define V_Op(vdst,gets,vsrc,n) {register int V_i;\
- for(V_i=(n)-1;V_i>=0;V_i--) (vdst)[V_i] gets ((vsrc)[V_i]);}
- static void lerp(float t, float a0, float a1, vec4_t p0, vec4_t p1, int m, vec4_t p)
- {
- register float t0=(a1-t)/(a1-a0), t1=1-t0;
- register int i;
- for (i=m-1; i>=0; i--) p[i] = t0*p0[i] + t1*p1[i];
- }
- /* DialASpline(t,a,p,m,n,work,Cn,interp,val) computes a point val at parameter
- t on a spline with knot values a and control points p. The curve will have
- Cn continuity, and if interp is TRUE it will interpolate the control points.
- Possibilities include Langrange interpolants, Bezier curves, Catmull-Rom
- interpolating splines, and B-spline curves. Points have m coordinates, and
- n+1 of them are provided. The work array must have room for n+1 points.
- */
- static int DialASpline(float t, float a[], vec4_t p[], int m, int n, vec4_t work[],
- unsigned int Cn, bool interp, vec4_t val)
- {
- register int i, j, k, h, lo, hi;
- if (Cn>n-1) Cn = n-1; /* Anything greater gives one polynomial */
- for (k=0; t> a[k]; k++); /* Find enclosing knot interval */
- for (h=k; t==a[k]; k++); /* May want to use fewer legs */
- if (k>n) {k = n; if (h>k) h = k;}
- h = 1+Cn - (k-h); k--;
- lo = k-Cn; hi = k+1+Cn;
- if (interp) { /* Lagrange interpolation steps */
- int drop=0;
- if (lo<0) {lo = 0; drop += Cn-k;
- if (hi-lo<Cn) {drop += Cn-hi; hi = Cn;}}
- if (hi>n) {hi = n; drop += k+1+Cn-n;
- if (hi-lo<Cn) {drop += lo-(n-Cn); lo = n-Cn;}}
- for (i=lo; i<=hi; i++) V_Op(work[i],=,p[i],m);
- for (j=1; j<=Cn; j++) {
- for (i=lo; i<=hi-j; i++) {
- lerp(t,a[i],a[i+j],work[i],work[i+1],m,work[i]);
- }
- }
- h = 1+Cn-drop;
- } else { /* Prepare for B-spline steps */
- if (lo<0) {h += lo; lo = 0;}
- for (i=lo; i<=lo+h; i++) V_Op(work[i],=,p[i],m);
- if (h<0) h = 0;
- }
- for (j=0; j<h; j++) {
- int tmp = 1+Cn-j;
- for (i=h-1; i>=j; i--) {
- lerp(t,a[lo+i],a[lo+i+tmp],work[lo+i],work[lo+i+1],m,work[lo+i+1]);
- }
- }
- V_Op(val,=,work[lo+h],m);
- return (k);
- }
- #define BIG (1.0e12)
- static vec_t Vector2Normalize( vec2_t v )
- {
- float length, ilength;
- length = v[0]*v[0] + v[1]*v[1];
- length = sqrt (length);
- if ( length )
- {
- ilength = 1/length;
- v[0] *= ilength;
- v[1] *= ilength;
- }
-
- return length;
- }
- CPathInfo::CPathInfo(CCMLandScape *landscape, int numPoints, float bx, float by, float ex, float ey,
- float minWidth, float maxWidth, float depth, float deviation, float breadth,
- CPathInfo *Connected, unsigned CreationFlags) :
- mNumPoints(numPoints),
- mMinWidth(minWidth),
- mMaxWidth(maxWidth),
- mDepth(depth),
- mDeviation(deviation),
- mBreadth(breadth)
- {
- int i, numConnected, index;
- float position, goal, deltaGoal;
- // float random, delta;
- bool horizontal;
- float *point;
- float currentWidth;
- float currentPosition;
- vec2_t testPoint, percPoint, diffPoint, normalizedPath;
- float distance, length;
-
- CreateCircle();
- numConnected = -1;
- if (Connected)
- { // we are connecting to an existing spline
- numConnected = Connected->GetNumPoints();
- if (numConnected >= SPLINE_MERGE_SIZE)
- { // plenty of points to choose from
- mNumPoints += SPLINE_MERGE_SIZE;
- }
- else
- { // the existing spline doesn't have enough points
- mNumPoints += numConnected;
- }
- }
- mPoints = (vec4_t *)malloc(sizeof(vec4_t) * mNumPoints);
- mWork = (vec4_t *)malloc(sizeof(vec4_t) * (mNumPoints+1));
- mWeights = (vec_t *)malloc(sizeof(vec_t) * (mNumPoints+1));
- length = sqrt((ex-bx)*(ex-bx) + (ey-by)*(ey-by));
- if (fabs(ex - bx) >= fabs(ey - by))
- { // this appears to be a horizontal path
- mInc = 1.0 / fabs(ex - bx);
- horizontal = true;
- position = by;
- goal = ey;
- deltaGoal = (ey-by) / (numPoints-1);
- }
- else
- { // this appears to be a vertical path
- mInc = 1.0 / fabs(ey - by);
- horizontal = false;
- position = bx;
- goal = ex;
- deltaGoal = (ex-bx) / (numPoints-1);
- }
- normalizedPath[0] = (ex-bx);
- normalizedPath[1] = (ey-by);
- Vector2Normalize(normalizedPath);
- // approx calculate how much we need to iterate through the spline to hit every point
- mInc /= 16;
- currentWidth = landscape->flrand(minWidth, maxWidth);
- currentPosition = 0.0;
- for(i=0;i<mNumPoints;i++)
- {
- // weights are evenly distributed
- mWeights[i] = (float)i / (mNumPoints-1);
- if (i < numConnected && i < SPLINE_MERGE_SIZE)
- { // we are connecting to an existing spline, so copy over the first few points
- if (CreationFlags & PATH_CREATION_CONNECT_FRONT)
- { // copy from the front
- index = i;
- }
- else
- { // copy from the end
- index = numConnected-SPLINE_MERGE_SIZE+i;
- }
- point = Connected->GetPoint(index);
- mPoints[i][0] = point[0];
- mPoints[i][1] = point[1];
- mPoints[i][3] = point[3];
- }
- else
- {
- if (horizontal)
- { // we appear to be going horizontal, so spread the randomness across the vertical
- mPoints[i][0] = ((ex - bx) * currentPosition) + bx;
- mPoints[i][1] = position;
- }
- else
- { // we appear to be going vertical, so spread the randomness across the horizontal
- mPoints[i][0] = position;
- mPoints[i][1] = ((ey - by) * currentPosition) + by;
- }
- currentPosition += 1.0 / (numPoints-1);
- // set the width of the spline
- mPoints[i][3] = currentWidth;
- currentWidth += landscape->flrand(-0.1f, 0.1f);
- if (currentWidth < minWidth)
- {
- currentWidth = minWidth;
- }
- else if (currentWidth > maxWidth)
- {
- currentWidth = maxWidth;
- }
- // see how far we are from the goal
- /* delta = (goal - position) * currentPosition;
- // calculate the randomness we are allowed at this place
- random = landscape->flrand(-mDeviation/1.0, mDeviation/1.0) * (1.0 - currentPosition);
- position += delta + random;*/
- if (i == mNumPoints-2)
- { // -2 because we are calculating for the next point
- position = goal;
- }
- else
- {
- if (i == 0)
- {
- position += deltaGoal + landscape->flrand(-mDeviation/10.0, mDeviation/10.0);
- }
- else
- {
- position += deltaGoal + landscape->flrand(-mDeviation*1.5, mDeviation*1.5);
- }
- }
- if (position > 0.9)
- { // too far over, so move back a bit
- position = 0.9 - landscape->flrand(0.02f, 0.1f);
- }
- if (position < 0.1)
- { // too near, so move bakc a bit
- position = 0.1 + landscape->flrand(0.02f, 0.1f);
- }
- // check our deviation from the straight line to the end
- if (horizontal)
- {
- testPoint[0] = ((ex - bx) * currentPosition) + bx;
- testPoint[1] = position;
- }
- else
- {
- testPoint[0] = position;
- testPoint[1] = ((ey - by) * currentPosition) + by;
- }
- // dot product of the normal of the path to the point we are at
- distance = ((testPoint[0]-bx)*normalizedPath[0]) + ((testPoint[1]-by)*normalizedPath[1]);
- // find the perpendicular place that is intersected by the point and the path
- percPoint[0] = (distance * normalizedPath[0]) + bx;
- percPoint[1] = (distance * normalizedPath[1]) + by;
- // calculate the difference between the perpendicular point and the test point
- diffPoint[0] = testPoint[0] - percPoint[0];
- diffPoint[1] = testPoint[1] - percPoint[1];
- // calculate the distance
- distance = sqrt((diffPoint[0]*diffPoint[0]) + (diffPoint[1]*diffPoint[1]));
- if (distance > mDeviation)
- { // we are beyond our allowed deviation, so head back
- if (horizontal)
- {
- position = (ey-by) * currentPosition + by;
- }
- else
- {
- position = (ex-bx) * currentPosition + bx;
- }
- position += landscape->flrand(-mDeviation/2.0, mDeviation/2.0);
- }
- }
- }
- mWeights[mNumPoints] = (float)BIG;
- }
- CPathInfo::~CPathInfo(void)
- {
- free(mWeights);
- free(mWork);
- free(mPoints);
- }
- void CPathInfo::CreateCircle(void)
- {
- int x, y;
- float r, d;
- memset(mCircleStamp, 0, sizeof(mCircleStamp));
- r = CIRCLE_STAMP_SIZE;
- for(x=0;x<CIRCLE_STAMP_SIZE;x++)
- {
- for(y=0;y<CIRCLE_STAMP_SIZE;y++)
- {
- d = sqrt((float)(x*x + y*y));
- if (d > r)
- {
- mCircleStamp[y][x] = 255;
- }
- else
- {
- mCircleStamp[y][x] = pow(sin((float)(d / r * M_PI / 2)), mBreadth) * 255;
- }
- }
- }
- }
- void CPathInfo::Stamp(int x, int y, int size, int depth, unsigned char *Data, int DataWidth, int DataHeight)
- {
- // int xPos;
- // float yPos;
- int dx, dy, fx, fy;
- float offset;
- byte value;
- byte invDepth;
- offset = (float)(CIRCLE_STAMP_SIZE-1) / size;
- invDepth = 255-depth;
- for(dx = -size; dx <= size; dx++)
- {
- for ( dy = -size; dy <= size; dy ++ )
- {
- float d;
- d = dx * dx + dy * dy ;
- if ( d > size * size )
- {
- continue;
- }
- fx = x + dx;
- if (fx < 2 || fx > DataWidth-2)
- {
- continue;
- }
-
- fy = y + dy;
- if (fy < 2 || fy > DataHeight-2)
- {
- continue;
- }
- value = pow ( sin ( (float)(d / (size * size) * M_PI / 2)), mBreadth ) * invDepth + depth;
- if (value < Data[(fy * DataWidth) + fx])
- {
- Data[(fy * DataWidth) + fx] = value;
- }
- }
- }
- /*
- fx = x + dx;
- if (fx < 2 || fx > DataWidth-2)
- {
- continue;
- }
- xPos = abs((int)(dx*offset));
- yPos = offset*size + offset;
- for(dy = -size; dy < 0; dy++)
- {
- yPos -= offset;
- fy = y + dy;
- if (fy < 2 || fy > DataHeight-2)
- {
- continue;
- }
- value = (invDepth * mCircleStamp[(int)yPos][xPos] / 256) + depth;
- if (value < Data[(fy * DataWidth) + fx])
- {
- Data[(fy * DataWidth) + fx] = value;
- }
- }
- yPos = -offset;
- for(; dy <= size; dy++)
- {
- yPos += offset;
- fy = y + dy;
- if (fy < 2 || fy > DataHeight-2)
- {
- continue;
- }
- value = (invDepth * mCircleStamp[(int)yPos][xPos] / 256) + depth;
- if (value < Data[(fy * DataWidth) + fx])
- {
- Data[(fy * DataWidth) + fx] = value;
- }
- }
- }
- */
- }
- void CPathInfo::GetInfo(float PercentInto, vec4_t Coord, vec4_t Vector)
- {
- vec4_t before, after;
- float testPercent;
- DialASpline(PercentInto, mWeights, mPoints, sizeof(vec4_t) / sizeof(vec_t), mNumPoints-1, mWork, 2, true, Coord);
- testPercent = PercentInto - 0.01;
- if (testPercent < 0)
- {
- testPercent = 0;
- }
- DialASpline(testPercent, mWeights, mPoints, sizeof(vec4_t) / sizeof(vec_t), mNumPoints-1, mWork, 2, true, before);
- testPercent = PercentInto + 0.01;
- if (testPercent > 1.0)
- {
- testPercent = 1.0;
- }
- DialASpline(testPercent, mWeights, mPoints, sizeof(vec4_t) / sizeof(vec_t), mNumPoints-1, mWork, 2, true, after);
- Coord[2] = mDepth;
- Vector[0] = after[0] - before[0];
- Vector[1] = after[1] - before[1];
- }
- void CPathInfo::DrawPath(unsigned char *Data, int DataWidth, int DataHeight )
- {
- float t;
- vec4_t val, vector;//, perp;
- int size;
- float inc;
- int x, y, lastX, lastY;
- float depth;
- inc = mInc / DataWidth;
- lastX = lastY = -999;
- for (t=0.0; t<=1.0; t+=inc)
- {
- GetInfo(t, val, vector);
- /* perp[0] = -vector[1];
- perp[1] = vector[0];
- if (fabs(perp[0]) > fabs(perp[1]))
- {
- perp[1] /= fabs(perp[0]);
- perp[0] /= fabs(perp[0]);
- }
- else
- {
- perp[0] /= fabs(perp[1]);
- perp[1] /= fabs(perp[1]);
- }
- */
- x = val[0] * DataWidth;
- y = val[1] * DataHeight;
- if (x == lastX && y == lastY)
- {
- continue;
- }
- lastX = x;
- lastY = y;
- size = val[3] * DataWidth;
- depth = mDepth * 255.0f;
- Stamp(x, y, size, (int)depth, Data, DataWidth, DataHeight);
- }
- }
- CRandomTerrain::CRandomTerrain(void)
- {
- memset(mPaths, 0, sizeof(mPaths));
- }
- CRandomTerrain::~CRandomTerrain(void)
- {
- Shutdown();
- }
- void CRandomTerrain::Init(CCMLandScape *landscape, byte *grid, int width, int height)
- {
- Shutdown();
- mLandScape = landscape;
- mWidth = width;
- mHeight = height;
- mArea = mWidth * mHeight;
- mBorder = (width + height) >> 6;
- mGrid = grid;
- }
- void CRandomTerrain::ClearPaths(void)
- {
- int i;
- for(i=0;i<MAX_RANDOM_PATHS;i++)
- {
- if (mPaths[i])
- {
- delete mPaths[i];
- mPaths[i] = 0;
- }
- }
- memset(mPaths, 0, sizeof(mPaths));
- }
- void CRandomTerrain::Shutdown(void)
- {
- ClearPaths ( );
- }
- bool CRandomTerrain::CreatePath(int PathID, int ConnectedID, unsigned CreationFlags, int numPoints,
- float bx, float by, float ex, float ey,
- float minWidth, float maxWidth, float depth, float deviation, float breadth )
- {
- CPathInfo *connected = 0;
- if (PathID < 0 || PathID >= MAX_RANDOM_PATHS || mPaths[PathID])
- {
- return false;
- }
- if (ConnectedID >= 0 && ConnectedID < MAX_RANDOM_PATHS)
- {
- connected = mPaths[ConnectedID];
- }
- mPaths[PathID] = new CPathInfo(mLandScape, numPoints, bx, by, ex, ey,
- minWidth, maxWidth, depth, deviation, breadth,
- connected, CreationFlags );
- return true;
- }
- bool CRandomTerrain::GetPathInfo(int PathNum, float PercentInto, vec4_t Coord, vec4_t Vector)
- {
- if (PathNum < 0 || PathNum >= MAX_RANDOM_PATHS || !mPaths[PathNum])
- {
- return false;
- }
- mPaths[PathNum]->GetInfo(PercentInto, Coord, Vector);
- return true;
- }
- void CRandomTerrain::ParseGenerate(const char *GenerateFile)
- {
- }
- void CRandomTerrain::Smooth ( void )
- {
- // Scale down to 1/4 size then back up to smooth out the terrain
- byte *temp;
- int x, y, o;
- temp = mLandScape->GetFlattenMap ( );
- // Copy over anything in the flatten map
- if (temp)
- {
- for ( o = 0; o < mHeight * mWidth; o++)
- {
- if ( temp[o] > 0 )
- {
- mGrid[o] = (byte)temp[o] & 0x7F;
- }
- }
- }
- temp = (byte *)Z_Malloc(mWidth * mHeight, TAG_TEMP_WORKSPACE, qfalse);
- #if 1
- unsigned total, count;
- for(x=1;x<mWidth-1;x++)
- {
- for(y=1;y<mHeight-1;y++)
- {
- total = 0;
- count = 2;
- // Left
- total += mGrid[((y)*mWidth)+(x-1)];
- count++;
- // Right
- total += mGrid[((y)*mWidth)+(x+1)];
- count++;
- // Up
- total += mGrid[((y-1)*mWidth)+(x)];
- count++;
- // Down
- total += mGrid[((y+1)*mWidth)+(x)];
- count++;
- // Up-Left
- total += mGrid[((y-1)*mWidth)+(x-1)];
- count++;
- // Down-Left
- total += mGrid[((y+1)*mWidth)+(x-1)];
- count++;
- // Up-Right
- total += mGrid[((y-1)*mWidth)+(x+1)];
- count++;
- // Down-Right
- total += mGrid[((y+1)*mWidth)+(x+1)];
- count++;
- total += (unsigned)mGrid[((y)*mWidth)+(x)] * 2;
- temp[((y)*mWidth)+(x)] = total / count;
- }
- }
- memcpy(mGrid, temp, mWidth * mHeight);
- #else
- float smoothKernel[FILTER_SIZE][FILTER_SIZE];
- int xx, yy, dx, dy;
- float total, num;
- R_Resample(mGrid, mWidth, mHeight, temp, mWidth >> 1, mHeight >> 1, 1);
- R_Resample(temp, mWidth >> 1, mHeight >> 1, mGrid, mWidth, mHeight, 1);
- // now lets filter it.
- memcpy(temp, mGrid, mWidth * mHeight);
- for (dy = -KERNEL_SIZE; dy <= KERNEL_SIZE; dy++)
- {
- for (dx = -KERNEL_SIZE; dx <= KERNEL_SIZE; dx++)
- {
- smoothKernel[dy + KERNEL_SIZE][dx + KERNEL_SIZE] =
- 1.0f / (1.0f + fabs(float(dx) * float(dx) * float(dx)) + fabs(float(dy) * float(dy) * float(dy)));
- }
- }
- for (y = 0; y < mHeight; y++)
- {
- for (x = 0; x < mWidth; x++)
- {
- total = 0.0f;
- num = 0.0f;
- for (dy = -KERNEL_SIZE; dy <= KERNEL_SIZE; dy++)
- {
- for (dx = -KERNEL_SIZE; dx <= KERNEL_SIZE; dx++)
- {
- xx = x + dx;
- if (xx >= 0 && xx < mWidth)
- {
- yy = y + dy;
- if (yy >= 0 && yy < mHeight)
- {
- total += smoothKernel[dy + KERNEL_SIZE][dx + KERNEL_SIZE] * (float)temp[yy * mWidth + xx];
- num += smoothKernel[dy + KERNEL_SIZE][dx + KERNEL_SIZE];
- }
- }
- }
- }
- total /= num;
- mGrid[y * mWidth + x] = (byte)Com_Clamp(0, 255, (int)Round(total));
- }
- }
- #endif
- Z_Free(temp);
- /* Uncomment to see the symmetry line on the map
- for ( x = 0; x < mWidth; x ++ )
- {
- mGrid[x * mWidth + x] = 255;
- }
- */
- }
- void CRandomTerrain::Generate(int symmetric)
- {
- int i,j;
- // Clear out all existing data
- memset(mGrid, 255, mArea);
- // make landscape a little bumpy
- float t1 = mLandScape->flrand(0, 2);
- float t2 = mLandScape->flrand(0, 2);
- float t3 = mLandScape->flrand(0, 2);
- CM_NoiseInit(mLandScape);
- int x, y;
- for (y = 0; y < mHeight; y++)
- for (x = 0; x < mWidth; x++)
- {
- i = x + y*mWidth;
- byte val = (byte)Com_Clamp(0, 255, (int)(220 + (CM_NoiseGet4f( x*0.25, y*0.25, 0, t3 ) * 20)) + (CM_NoiseGet4f( x*0.5, y*0.5, 0, t2 ) * 15));
- mGrid[i] = val;
- }
- for ( i = 0; mPaths[i] != 0; i ++ )
- {
- mPaths[i]->DrawPath(mGrid, mWidth, mHeight);
- }
- for (y = 0; y < mHeight; y++)
- for (x = 0; x < mWidth; x++)
- {
- i = x + y*mWidth;
- byte val = (byte)Com_Clamp(0, 255, (int)(mGrid[i] + (CM_NoiseGet4f( x, y, 0, t1 ) * 5)));
- mGrid[i] = val;
- }
- // if symmetric, do this now
- if (symmetric)
- {
- assert (mWidth == mHeight); // must be square
- for (y = 0; y < mHeight; y++)
- for (x = 0; x < (mWidth-y); x++)
- {
- i = x + y*mWidth;
- j = (mWidth-1 - x) + (mHeight-1 - y)*mWidth;
- byte val = mGrid[i] < mGrid[j] ? mGrid[i] : mGrid[j];
- mGrid[i] = mGrid[j] = val;
- }
- }
- }
- typedef enum
- {
- RMG_CP_NONE = -1,
- RMG_CP_CONSONANT,
- RMG_CP_COMPLEX_CONSONANT,
- RMG_CP_VOWEL,
- RMG_CP_COMPLEX_VOWEL,
- RMG_CP_ENDING,
- RMG_CP_NUM_PIECES,
- } ECPType;
- typedef struct SCharacterPiece
- {
- char *mPiece;
- int mCommonality;
- } TCharacterPiece;
- static TCharacterPiece Consonants[] =
- {
- { "b", 6 },
- { "c", 8 },
- { "d", 6 },
- { "f", 5 },
- { "g", 4 },
- { "h", 5 },
- { "j", 2 },
- { "k", 4 },
- { "l", 4 },
- { "m", 7 },
- { "n", 7 },
- { "r", 6 },
- { "s", 10 },
- { "t", 10 },
- { "v", 1 },
- { "w", 2 },
- { "x", 1 },
- { "z", 1 },
- { 0, 0 }
- };
- static TCharacterPiece ComplexConsonants[] =
- {
- { "st", 10 },
- { "ck", 10 },
- { "ss", 10 },
- { "tt", 7 },
- { "ll", 8 },
- { "nd", 10 },
- { "rn", 6 },
- { "nc", 6 },
- { "mp", 4 },
- { "sc", 10 },
- { "sl", 10 },
- { "tch", 6 },
- { "th", 4 },
- { "rn", 5 },
- { "cl", 10 },
- { "sp", 10 },
- { "st", 10 },
- { "fl", 4 },
- { "sh", 7 },
- { "ng", 4 },
- // { "" },
- { 0, 0 }
- };
- static TCharacterPiece Vowels[] =
- {
- { "a", 10 },
- { "e", 10 },
- { "i", 10 },
- { "o", 10 },
- { "u", 2 },
- // { "" },
- { 0, 0 }
- };
- static TCharacterPiece ComplexVowels[] =
- {
- { "ea", 10 },
- { "ue", 3 },
- { "oi", 10 },
- { "ai", 8 },
- { "oo", 10 },
- { "io", 10 },
- { "oe", 10 },
- { "au", 3 },
- { "ee", 7 },
- { "ei", 7 },
- { "ou", 7 },
- { "ia", 4 },
- // { "" },
- { 0, 0 }
- };
- static TCharacterPiece Endings[] =
- {
- { "ing", 10 },
- { "ed", 10 },
- { "ute", 10 },
- { "ance", 10 },
- { "ey", 10 },
- { "ation", 10 },
- { "ous", 10 },
- { "ent", 10 },
- { "ate", 10 },
- { "ible", 10 },
- { "age", 10 },
- { "ity", 10 },
- { "ist", 10 },
- { "ism", 10 },
- { "ime", 10 },
- { "ic", 10 },
- { "ant", 10 },
- { "etry", 10 },
- { "ious", 10 },
- { "ative", 10 },
- { "er", 10 },
- { "ize", 10 },
- { "able", 10 },
- { "itude", 10 },
- // { "" },
- { 0, 0 }
- };
- static void FindPiece(ECPType type, char *&pos)
- {
- TCharacterPiece *search, *start;
- int count = 0;
- switch(type)
- {
- case RMG_CP_CONSONANT:
- default:
- start = Consonants;
- break;
- case RMG_CP_COMPLEX_CONSONANT:
- start = ComplexConsonants;
- break;
- case RMG_CP_VOWEL:
- start = Vowels;
- break;
- case RMG_CP_COMPLEX_VOWEL:
- start = ComplexVowels;
- break;
- case RMG_CP_ENDING:
- start = Endings;
- break;
- }
- search = start;
- while(search->mPiece)
- {
- count += search->mCommonality;
- search++;
- }
- count = Q_irand(0, count-1);
- search = start;
- while(count > search->mCommonality)
- {
- count -= search->mCommonality;
- search++;
- }
- strcpy(pos, search->mPiece);
- pos += strlen(search->mPiece);
- }
- unsigned RMG_CreateSeed(char *TextSeed)
- {
- int Length;
- char Ending[256], *pos;
- int ComplexVowelChance, ComplexConsonantChance;
- ECPType LookingFor;
- unsigned SeedValue = 0, high;
- Length = Q_irand(4, 9);
- if (Q_irand(0, 100) < 20)
- {
- LookingFor = RMG_CP_VOWEL;
- }
- else
- {
- LookingFor = RMG_CP_CONSONANT;
- }
- Ending[0] = 0;
- if (Q_irand(0, 100) < 55)
- {
- pos = Ending;
- FindPiece(RMG_CP_ENDING, pos);
- Length -= (pos - Ending);
- }
- pos = TextSeed;
- *pos = 0;
- ComplexVowelChance = -1;
- ComplexConsonantChance = -1;
- while((pos - TextSeed) < Length || LookingFor == RMG_CP_CONSONANT)
- {
- if (LookingFor == RMG_CP_VOWEL)
- {
- if (Q_irand(0, 100) < ComplexVowelChance)
- {
- ComplexVowelChance = -1;
- LookingFor = RMG_CP_COMPLEX_VOWEL;
- }
- else
- {
- ComplexVowelChance += 10;
- }
- FindPiece(LookingFor, pos);
- LookingFor = RMG_CP_CONSONANT;
- }
- else
- {
- if (Q_irand(0, 100) < ComplexConsonantChance)
- {
- ComplexConsonantChance = -1;
- LookingFor = RMG_CP_COMPLEX_CONSONANT;
- }
- else
- {
- ComplexConsonantChance += 45;
- }
- FindPiece(LookingFor, pos);
- LookingFor = RMG_CP_VOWEL;
- }
- }
- if (Ending[0])
- {
- strcpy(pos, Ending);
- }
- pos = TextSeed;
- while(*pos)
- {
- high = SeedValue >> 28;
- SeedValue ^= (SeedValue << 4) + ((*pos)-'a');
- SeedValue ^= high;
- pos++;
- }
- return SeedValue;
- }
|