Added sources.
This commit is contained in:
16
Makefile
Normal file
16
Makefile
Normal file
@@ -0,0 +1,16 @@
|
||||
LDLIBS = -lm
|
||||
|
||||
all: CFLAGS = -O3 -ansi -pedantic
|
||||
all: ds
|
||||
|
||||
debug: CFLAGS = -g -ansi -pedantic
|
||||
debug: ds
|
||||
|
||||
ds: main.o ds.o
|
||||
|
||||
main.o: main.c ds.h
|
||||
|
||||
ds.o: ds.c ds.h
|
||||
|
||||
clean:
|
||||
$(RM) *.o ds
|
14
README.md
14
README.md
@@ -2,3 +2,17 @@ DS-Island-generator
|
||||
===================
|
||||
|
||||
A procedural island generator based on the diamond-square mid point displacement and the particle deposition algorithms.
|
||||
|
||||
Compile with:
|
||||
|
||||
make
|
||||
|
||||
Execute as:
|
||||
|
||||
./ds N PREFIX
|
||||
|
||||
Where N is a positive integer greater than zero and PREFIX is a string to append to the output file names.
|
||||
|
||||
The diamond-square mid point displacement implementation is a port of the code outlined in [this post] [1] at Stack Overflow.
|
||||
|
||||
[1]: http://stackoverflow.com/a/2773032
|
||||
|
209
ds.c
Normal file
209
ds.c
Normal file
@@ -0,0 +1,209 @@
|
||||
#ifndef __cplusplus
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#else
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <cfloat>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
#endif
|
||||
|
||||
#include "ds.h"
|
||||
|
||||
static const float SEED = 1000.0;
|
||||
|
||||
static float randomFloat ();
|
||||
|
||||
/**
|
||||
* Port of the java implementation outlined here http://stackoverflow.com/a/2773032
|
||||
*/
|
||||
void ds ( float *** map, const unsigned int DATA_SIZE ) {
|
||||
float avg, r, h = SEED / 2.0;
|
||||
int sideLength, halfSide, x, y;
|
||||
|
||||
srand( time( NULL ) );
|
||||
|
||||
( * map )[ 0 ][ 0 ] = ( * map )[ 0 ][ DATA_SIZE - 1 ] = ( * map )[ DATA_SIZE - 1 ][ 0 ] = ( * map )[ DATA_SIZE - 1 ][ DATA_SIZE - 1 ] = h;
|
||||
|
||||
for ( sideLength = DATA_SIZE - 1; sideLength >= 2; sideLength /= 2, h /= 2.0 ) {
|
||||
halfSide = sideLength / 2;
|
||||
|
||||
for ( x = 0; x < DATA_SIZE -1; x += sideLength ) {
|
||||
for ( y = 0; y < DATA_SIZE - 1; y += sideLength ) {
|
||||
avg = ( * map )[ x ][ y ] +
|
||||
( * map )[ x + sideLength ][ y ] +
|
||||
( * map )[ x ][ y + sideLength ] +
|
||||
( * map )[ x + sideLength ][ y + sideLength ];
|
||||
avg /= 4.0;
|
||||
|
||||
r = randomFloat();
|
||||
|
||||
( * map )[ x + halfSide ][ y + halfSide ] = avg + ( r * 2.0 * h ) - h;
|
||||
}
|
||||
}
|
||||
|
||||
for ( x = 0; x < DATA_SIZE - 1; x += halfSide ) {
|
||||
for ( y = ( x + halfSide ) % sideLength; y < DATA_SIZE - 1; y += sideLength ) {
|
||||
avg = ( * map )[ ( x - halfSide + DATA_SIZE ) % DATA_SIZE ][ y ] +
|
||||
( * map )[ ( x + halfSide ) % DATA_SIZE ][ y ] +
|
||||
( * map )[ x ][ ( y + halfSide ) % DATA_SIZE ] +
|
||||
( * map )[ x ][ ( y - halfSide + DATA_SIZE ) % DATA_SIZE ];
|
||||
avg /= 4.0;
|
||||
|
||||
r = randomFloat();
|
||||
|
||||
avg = avg + ( r * 2.0 * h ) - h;
|
||||
|
||||
( * map )[ x ][ y ] = avg;
|
||||
|
||||
if ( x == 0 ) ( * map )[ DATA_SIZE - 1 ][ y ] = avg;
|
||||
if ( y == 0 ) ( * map )[ x ][ DATA_SIZE - 1 ] = avg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void island ( int ***imap, unsigned int MAP_SIZE ) {
|
||||
const int part = ( MAP_SIZE * 3000 ) / 513;
|
||||
const int life = ( MAP_SIZE * 5000 ) / 513;
|
||||
int x, y, dx, dy, i, c, n, nx, ny, l;
|
||||
|
||||
srand( time( NULL ) );
|
||||
|
||||
for ( i = 0; i < part; ++i ) {
|
||||
x = ( MAP_SIZE / 4 ) + ( random() % ( MAP_SIZE / 2 ) );
|
||||
y = ( MAP_SIZE / 4 ) + ( random() % ( MAP_SIZE / 2 ) );
|
||||
|
||||
for ( l = life; l >= 0; l-- ) {
|
||||
dx = ( random() % 3 ) - 1;
|
||||
dy = ( random() % 3 ) - 1;
|
||||
|
||||
( * imap )[ x ][ y ] += 1;
|
||||
|
||||
c = ( * imap )[ x ][ y ];
|
||||
|
||||
nx = ( x + dx );
|
||||
ny = ( y + dy );
|
||||
|
||||
if ( nx < 0 || nx >= MAP_SIZE || ny < 0 || ny >= MAP_SIZE ) {
|
||||
l--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ( * imap )[ nx ][ ny ] <= c ) {
|
||||
( * imap )[ nx ][ ny ] += 1;
|
||||
}
|
||||
|
||||
x = nx;
|
||||
y = ny;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void norm ( float *** fmap, unsigned int MAP_SIZE ) {
|
||||
int i, j;
|
||||
float max = -FLT_MAX;
|
||||
|
||||
for ( i = 0; i < MAP_SIZE; ++i ) {
|
||||
for ( j = 0; j < MAP_SIZE; ++j ) {
|
||||
max = abs( ( * fmap )[ i ][ j ] ) > max ? abs ( ( * fmap )[ i ][ j ] ) : max;
|
||||
}
|
||||
}
|
||||
|
||||
for ( i = 0; i < MAP_SIZE; ++i ) {
|
||||
for ( j = 0; j < MAP_SIZE; ++j ) {
|
||||
( * fmap )[ i ][ j ] += max;
|
||||
}
|
||||
}
|
||||
|
||||
for ( i = 0; i < MAP_SIZE; ++i ) {
|
||||
for ( j = 0; j < MAP_SIZE; ++j ) {
|
||||
max = abs( ( * fmap )[ i ][ j ] ) > max ? abs ( ( * fmap )[ i ][ j ] ) : max;
|
||||
}
|
||||
}
|
||||
|
||||
for ( i = 0; i < MAP_SIZE; ++i ) {
|
||||
for ( j = 0; j < MAP_SIZE; ++j ) {
|
||||
( * fmap )[ i ][ j ] /= max;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void normInt ( int *** map, unsigned int MAP_SIZE ) {
|
||||
int i, j, max = -1;
|
||||
|
||||
for ( i = 0; i < MAP_SIZE; ++i ) {
|
||||
for ( j = 0; j < MAP_SIZE; ++j ) {
|
||||
max = max < ( * map )[ i ][ j ] ? ( * map )[ i ][ j ] : max;
|
||||
}
|
||||
}
|
||||
|
||||
for ( i = 0; i < MAP_SIZE; ++i ) {
|
||||
for ( j = 0; j < MAP_SIZE; ++j ) {
|
||||
( * map )[ i ][ j ] = ( int ) ( ( ( float ) ( * map )[ i ][ j ] / ( float ) max ) * 255.0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern void mult ( float *** fmap, int *** imap, unsigned int MAP_SIZE ) {
|
||||
int i, j;
|
||||
|
||||
for ( i = 0; i < MAP_SIZE; ++i ) {
|
||||
for ( j = 0; j < MAP_SIZE; ++j ) {
|
||||
/*fprintf ( stderr, "%f %d\n", ( * fmap )[ i ][ j ], ( * imap )[ i ][ j ] );*/
|
||||
( * imap )[ i ][ j ] = ( int )( ( ( * fmap )[ i ][ j ] * ( ( float ) ( * imap )[ i ][ j ] / 255.0f ) ) * 250.0f );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void smooth ( int *** map, unsigned int MAP_SIZE) {
|
||||
int i, j, avg, **temp;
|
||||
|
||||
temp = ( int ** ) malloc ( sizeof ( int * ) * MAP_SIZE );
|
||||
for ( i = 0; i < MAP_SIZE; ++i ){
|
||||
temp[ i ] = ( int * ) malloc ( sizeof ( int ) * MAP_SIZE );
|
||||
}
|
||||
|
||||
for ( i = 0; i < MAP_SIZE; ++i ) {
|
||||
for ( j = 0; j < MAP_SIZE; ++j ) {
|
||||
avg = 0;
|
||||
|
||||
avg += ( * map )[ i ][ j ];
|
||||
avg += ( * map )[ ( i + 1 ) % MAP_SIZE ][ j ];
|
||||
avg += ( * map )[ ( i - 1 ) < 0 ? MAP_SIZE - 1 : i - 1 ][ j ];
|
||||
avg += ( * map )[ i ][ ( j + 1 ) % MAP_SIZE ];
|
||||
avg += ( * map )[ i ][ ( j - 1 ) < 0 ? MAP_SIZE - 1 : j - 1 ];
|
||||
avg += ( * map )[ ( i + 1 ) % MAP_SIZE ][ ( j + 1 ) % MAP_SIZE ];
|
||||
avg += ( * map )[ ( i + 1 ) % MAP_SIZE ][ ( j - 1 ) < 0 ? MAP_SIZE - 1 : j - 1 ];
|
||||
avg += ( * map )[ ( i - 1 ) < 0 ? MAP_SIZE - 1 : i - 1 ][ ( j + 1 ) % MAP_SIZE ];
|
||||
avg += ( * map )[ ( i - 1 ) < 0 ? MAP_SIZE - 1 : i - 1 ][ ( j - 1 ) < 0 ? MAP_SIZE - 1 : j - 1 ];
|
||||
|
||||
avg /= 9;
|
||||
|
||||
temp[ i ][ j ] = avg;
|
||||
}
|
||||
}
|
||||
|
||||
for ( i = 0; i < MAP_SIZE; ++i ){
|
||||
memcpy ( ( * map )[ i ], temp[ i ], MAP_SIZE * sizeof ( int ) );
|
||||
}
|
||||
|
||||
free ( temp );
|
||||
}
|
||||
|
||||
static float randomFloat() {
|
||||
float r = ( float ) random() / ( float ) RAND_MAX;
|
||||
r = ( r * 2.0 ) - 1.0;
|
||||
return r;
|
||||
}
|
43
ds.h
Normal file
43
ds.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef DS_H
|
||||
#define DS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Generate a diamond-square fractal map.
|
||||
*/
|
||||
extern void ds ( float ***, const unsigned int );
|
||||
|
||||
/**
|
||||
* Generate a mask using particle deposition.
|
||||
*/
|
||||
extern void island ( int ***, unsigned int );
|
||||
|
||||
/**
|
||||
* Normalize a float matrix between 0 and 1.
|
||||
*/
|
||||
extern void norm ( float ***, unsigned int );
|
||||
|
||||
/**
|
||||
* Normalize an int matrix between 0 and 255.
|
||||
*/
|
||||
extern void normInt ( int ***, unsigned int );
|
||||
|
||||
/**
|
||||
* Perform a 3x3 average blur.
|
||||
*/
|
||||
extern void smooth ( int ***, unsigned int );
|
||||
|
||||
/**
|
||||
* Multiply the diamond square map with the island mask.
|
||||
* Both matrices must have been normalized before.
|
||||
*/
|
||||
extern void mult ( float ***, int *** , unsigned int);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
223
main.c
Normal file
223
main.c
Normal file
@@ -0,0 +1,223 @@
|
||||
/**
|
||||
* Test main for the Diamond-Square island generator.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ds.h"
|
||||
|
||||
struct COLOR {
|
||||
unsigned char r;
|
||||
unsigned char g;
|
||||
unsigned char b;
|
||||
};
|
||||
|
||||
static void printMapAsPgm ( int ***, const unsigned int, char * );
|
||||
static void printMapAsPgm2 ( int ***, const unsigned int, char * );
|
||||
static void printFloatMapAsPgm ( float ***, const unsigned int, char * );
|
||||
static void printMapAsPpm ( int ***, const unsigned int, char * );
|
||||
static struct COLOR getTerrainType( int );
|
||||
|
||||
int main ( int argc, char **argv ) {
|
||||
int i, m, ** imap;
|
||||
unsigned int n = 0;
|
||||
float ** map;
|
||||
|
||||
if ( argc < 3 ) {
|
||||
fprintf ( stderr, "Usage: %s N <prefix>\nN is an integer greater than 0.\n", argv[0] );
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
m = atoi( argv[1] );
|
||||
|
||||
if ( m <= 0 ) {
|
||||
fprintf ( stderr, "N must be an integer greater than zero: %d\n", m );
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
n = (unsigned int)( pow ( 2.0, m ) ) + 1;
|
||||
|
||||
map = ( float ** ) malloc ( sizeof ( float * ) * n);
|
||||
for ( i = 0; i < n; ++i ) {
|
||||
map[ i ] = ( float * ) calloc ( n, sizeof ( float ) );
|
||||
}
|
||||
|
||||
imap = ( int ** ) malloc ( sizeof ( int * ) * n);
|
||||
for ( i = 0; i < n; ++i ) {
|
||||
imap[ i ] = ( int * ) calloc ( n, sizeof ( int ) );
|
||||
}
|
||||
|
||||
ds ( &map, n );
|
||||
island ( &imap, n );
|
||||
normInt ( &imap, n );
|
||||
printMapAsPgm2 ( &imap, n, argv[2] );
|
||||
norm ( &map, n );
|
||||
printFloatMapAsPgm ( &map, n, argv[2] );
|
||||
mult ( &map, &imap, n );
|
||||
smooth( &imap, n );
|
||||
normInt ( &imap, n );
|
||||
printMapAsPgm ( &imap, n, argv[2] );
|
||||
printMapAsPpm ( &imap, n, argv[2] );
|
||||
|
||||
for ( i = 0; i < n; ++i ) {
|
||||
free ( map[ i ] );
|
||||
}
|
||||
free ( map );
|
||||
|
||||
for ( i = 0; i < n; ++i ) {
|
||||
free ( imap[ i ] );
|
||||
}
|
||||
free ( imap );
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void printFloatMapAsPgm ( float *** map, const unsigned int MAP_SIZE, char * fn ) {
|
||||
int i, j, max = -1;
|
||||
FILE * f;
|
||||
char * filename = ( char * ) malloc ( ( strlen ( "ds_map.pgm" ) + strlen ( fn ) ) * sizeof ( char ) + 1);
|
||||
|
||||
strcpy ( filename, fn );
|
||||
strcat ( filename, "ds_map.pgm" );
|
||||
|
||||
f = fopen ( filename , "w" );
|
||||
|
||||
fprintf ( f, "P2\n" );
|
||||
fprintf ( f, "%u %u\n", MAP_SIZE, MAP_SIZE );
|
||||
fprintf ( f, "255\n" );
|
||||
|
||||
for ( i = 0; i < MAP_SIZE; ++i ) {
|
||||
for ( j = 0; j < MAP_SIZE; ++j ) {
|
||||
fprintf( f, "%d ", ( int )( ( * map )[ i ][ j ] * 255.0f ) );
|
||||
}
|
||||
fprintf( f, "\n" );
|
||||
}
|
||||
|
||||
fclose ( f );
|
||||
free ( filename );
|
||||
}
|
||||
|
||||
void printMapAsPgm ( int *** map, const unsigned int MAP_SIZE, char * fn ) {
|
||||
int i, j, max = -1;
|
||||
FILE * f;
|
||||
char * filename = ( char * ) malloc ( ( strlen ( "hmmap.pgm" ) + strlen ( fn ) ) * sizeof ( char ) + 1);
|
||||
|
||||
strcpy ( filename, fn );
|
||||
strcat ( filename, "hmmap.pgm" );
|
||||
|
||||
f = fopen ( filename , "w" );
|
||||
|
||||
f = fopen ( filename, "w" );
|
||||
|
||||
for ( i = 0; i < MAP_SIZE; ++i ) {
|
||||
for ( j = 0; j < MAP_SIZE; ++j ) {
|
||||
max = max < ( * map )[ i ][ j ] ? ( * map )[ i ][ j ] : max;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf ( f, "P2\n" );
|
||||
fprintf ( f, "%u %u\n", MAP_SIZE, MAP_SIZE );
|
||||
fprintf ( f, "%d\n", max );
|
||||
|
||||
for ( i = 0; i < MAP_SIZE; ++i ) {
|
||||
for ( j = 0; j < MAP_SIZE; ++j ) {
|
||||
fprintf( f, "%d ", ( * map )[ i ][ j ] );
|
||||
}
|
||||
fprintf( f, "\n" );
|
||||
}
|
||||
|
||||
fclose ( f );
|
||||
}
|
||||
|
||||
void printMapAsPgm2 ( int *** map, const unsigned int MAP_SIZE, char * fn ) {
|
||||
int i, j, max = -1;
|
||||
FILE * f;
|
||||
char * filename = ( char * ) malloc ( ( strlen ( "is.pgm" ) + strlen ( fn ) ) * sizeof ( char ) + 1);
|
||||
|
||||
strcpy ( filename, fn );
|
||||
strcat ( filename, "is.pgm" );
|
||||
|
||||
f = fopen ( filename , "w" );
|
||||
|
||||
for ( i = 0; i < MAP_SIZE; ++i ) {
|
||||
for ( j = 0; j < MAP_SIZE; ++j ) {
|
||||
max = max < ( * map )[ i ][ j ] ? ( * map )[ i ][ j ] : max;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf ( f, "P2\n" );
|
||||
fprintf ( f, "%u %u\n", MAP_SIZE, MAP_SIZE );
|
||||
fprintf ( f, "%d\n", max );
|
||||
|
||||
for ( i = 0; i < MAP_SIZE; ++i ) {
|
||||
for ( j = 0; j < MAP_SIZE; ++j ) {
|
||||
fprintf( f, "%d ", ( * map )[ i ][ j ] );
|
||||
}
|
||||
fprintf( f, "\n" );
|
||||
}
|
||||
|
||||
fclose ( f );
|
||||
free ( filename );
|
||||
}
|
||||
|
||||
void printMapAsPpm ( int *** map, const unsigned int MAP_SIZE, char * fn ) {
|
||||
struct COLOR c;
|
||||
int i, j;
|
||||
FILE * f;
|
||||
char * filename = ( char * ) malloc ( ( strlen ( "map.ppm" ) + strlen ( fn ) ) * sizeof ( char ) + 1);
|
||||
|
||||
strcpy ( filename, fn );
|
||||
strcat ( filename, "map.ppm" );
|
||||
|
||||
f = fopen ( filename, "w" );
|
||||
|
||||
fprintf ( f, "P3\n" );
|
||||
fprintf ( f, "%u %u\n", MAP_SIZE, MAP_SIZE );
|
||||
fprintf ( f, "255\n" );
|
||||
|
||||
for ( i = 0; i < MAP_SIZE; ++i ) {
|
||||
for ( j = 0; j < MAP_SIZE; ++j ) {
|
||||
c = getTerrainType( ( * map )[ i ][ j ] );
|
||||
fprintf( f, "%d %d %d\t", c.r, c.g, c.b );
|
||||
}
|
||||
fprintf( f, "\n" );
|
||||
}
|
||||
|
||||
fclose ( f );
|
||||
free ( filename );
|
||||
}
|
||||
|
||||
struct COLOR getTerrainType( int h) {
|
||||
struct COLOR c;
|
||||
|
||||
if ( h < 30 ) {
|
||||
if ( h < 15 ) {
|
||||
c.r = 64; c.g = 64; c.b = 200;
|
||||
return c;
|
||||
} else {
|
||||
c.r = 128; c.g = 128; c.b = 255;
|
||||
return c;
|
||||
}
|
||||
} else {
|
||||
if ( h < 40 ) {
|
||||
c.r = 255; c.g = 234; c.b = 150;
|
||||
return c;
|
||||
} else if ( h >= 40 && h < 100 ) {
|
||||
c.r = 16; c.g = 180; c.b = 40;
|
||||
return c;
|
||||
} else if ( h >= 100 && h < 150 ) {
|
||||
c.r = 70; c.g = 164; c.b = 25;
|
||||
return c;
|
||||
} else if ( h >= 180 ) {
|
||||
c.r = 200; c.g = 200; c.b = 200;
|
||||
return c;
|
||||
} else {
|
||||
c.r = 143; c.g = 111; c.b = 81;
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user