patternsqlMinor
Terrain height map generator
Viewed 0 times
mapgeneratorheightterrain
Problem
I wrote a Perl script that implements the algorithm described in this
article to generate terrain height maps. The idea is to raise a random hill \$i\$ of size \$r_i\$ centered at point \$(x_i, y_i)\$, such that the height at point \$(x, y)\$ is
$$ z = r_i^2 - ((x - x_1)^2 + (y - y_1)^2) $$
The resulting terrain is the sum of many such hills, with some normalization and flattening.
The output of this program is a bunch of inserts into the database and a png. The only problem with it is that it has really bad performance.
article to generate terrain height maps. The idea is to raise a random hill \$i\$ of size \$r_i\$ centered at point \$(x_i, y_i)\$, such that the height at point \$(x, y)\$ is
$$ z = r_i^2 - ((x - x_1)^2 + (y - y_1)^2) $$
The resulting terrain is the sum of many such hills, with some normalization and flattening.
The output of this program is a bunch of inserts into the database and a png. The only problem with it is that it has really bad performance.
#!/usr/bin/perl
# mapgen.pl
# Henry J Schmale
# August 16, 2015
# Generates a height map
use strict;
use warnings;
use DBI;
use Image::Magick;
use constant {
MAX_X => 2000,
MAX_Y => 2000,
MAX_R => 1075,
MIN_R => 100,
NUM_HILLS => 250
};
my @heightmap;
makemap();
sub makemap {
#init heightmap to 0
for(my $i = 0 ; $i $maxvalue){
$maxvalue = $heightmap[$x][$y];
}
}
}
for(my $x = 0; $x 0 and $x > 0 and $y > 0){
$heightmap[$x][$y] += $z;
}
}
}
}
sub dumpToDb {
my $dbh = DBI->connect("dbi:SQLite:dbname=server.sqlite",'','')
or die DBI::errstr;
my $sth = $dbh->prepare("INSERT INTO map_heights(lat_pt, long_pt, z_pt)".
"VALUES(?, ?, ?)");
for(my $x = 0; $x execute($x, $y, $heightmap[$x][$y]);
}
}
$dbh->disconnect();
}
sub dumpToImg {
my $im = Image::Magick->new;
my $junk = MAX_X.'x'.MAX_Y;
print $junk."\n";
$im->Set(size => $junk);
$im->ReadImage('canvas:white');
warn "$im" if "$im";
for(my $x = 0; $x SetPixel(x=>$x, y=>$y, color=>\@pixel);
}
}
my $x = $im->Write('heightmap.png');
warn "$x" if "$x";
}Solution
I see two things right off the bat that may help:
The other thing that looks problematic is setting each individual pixel through a function call. Is there any way to pass a buffer of memory to ImageMagick? If so, it would probably faster to do that.
- Calculate
$maxvalueinsidemakehill()so you don't have to calculate it after
- Do the normalization and flattening in 1 pass. Also, you can do the flattening in a single function call. You're basically raising each value to the 8th power, so use the power function. I don't know
perlreal well, but it's usually calledpow()and takes a value and an exponent.
The other thing that looks problematic is setting each individual pixel through a function call. Is there any way to pass a buffer of memory to ImageMagick? If so, it would probably faster to do that.
Context
StackExchange Code Review Q#101145, answer score: 2
Revisions (0)
No revisions yet.