forked from 0ad/0ad
# Updates to random map generator.
- Added a direct addToClass/removeFromClass API for use in noise-based maps. - Raised the sea level in the game world so water can be deeper, and set it to 0 in script coordinates. - Moved some class-related utility functions to rmlibrary.js. - Modified sample maps in light of these changes. - Committed noise class which I forgot last time. This was SVN commit r4659.
This commit is contained in:
parent
aa405024f2
commit
60befbd1cf
@ -31,24 +31,10 @@ const oRockMedium = "geology/stone_granite_med.xml";
|
||||
const oBushMedium = "props/flora/bush_tempe_me.xml";
|
||||
const oBushSmall = "props/flora/bush_tempe_sm.xml";
|
||||
|
||||
// some utility functions to save typing
|
||||
|
||||
function paintClass(cl) {
|
||||
return new TileClassPainter(cl);
|
||||
}
|
||||
|
||||
function avoidClasses(/*class1, dist1, class2, dist2, etc*/) {
|
||||
var ar = new Array(arguments.length/2);
|
||||
for(var i=0; i<arguments.length/2; i++) {
|
||||
ar[i] = new AvoidTileClassConstraint(arguments[2*i], arguments[2*i+1]);
|
||||
}
|
||||
return ar;
|
||||
}
|
||||
|
||||
// initialize map
|
||||
|
||||
println("Initializing map...");
|
||||
init(SIZE, tGrass, 8);
|
||||
init(SIZE, tGrass, 3);
|
||||
|
||||
// create tile classes
|
||||
|
||||
@ -81,7 +67,7 @@ for(i=1; i<=NUM_PLAYERS; i++) {
|
||||
// some constants
|
||||
radius = 17;
|
||||
cliffRadius = 2;
|
||||
elevation = 20;
|
||||
elevation = 15;
|
||||
|
||||
// get the x and y in tiles
|
||||
fx = fractionToTiles(playerX[i]);
|
||||
@ -193,7 +179,7 @@ terrainPainter = new LayeredPainter(
|
||||
[1,1], // widths
|
||||
[tShoreBlend, tShore, tWater] // terrains
|
||||
);
|
||||
elevationPainter = new SmoothElevationPainter(ELEVATION_SET, -2, 3);
|
||||
elevationPainter = new SmoothElevationPainter(ELEVATION_SET, -7, 3);
|
||||
createAreas(placer, [terrainPainter, elevationPainter, paintClass(clWater)],
|
||||
avoidClasses(clPlayer, 2, clWater, 20),
|
||||
round(1.3 * NUM_PLAYERS)
|
||||
@ -215,7 +201,7 @@ terrainPainter = new LayeredPainter(
|
||||
[3], // widths
|
||||
[tCliff, [tGrass,tGrass,tGrassDirt75]] // terrains
|
||||
);
|
||||
elevationPainter = new SmoothElevationPainter(ELEVATION_SET, 17, 2);
|
||||
elevationPainter = new SmoothElevationPainter(ELEVATION_SET, 12, 2);
|
||||
createAreas(placer, [terrainPainter, elevationPainter, paintClass(clHill)],
|
||||
avoidClasses(clPlayer, 2, clWater, 5, clHill, 15),
|
||||
2 * NUM_PLAYERS
|
||||
|
@ -1,7 +1,30 @@
|
||||
const SIZE = 160;
|
||||
const SEA_LEVEL = 5;
|
||||
|
||||
init(SIZE, "ocean_medit_rock_shallow", 0);
|
||||
const sand = "beach_medit_dry";
|
||||
const grass1 = "grass_temperate_a";
|
||||
const grass2 = "grass_mediterranean_green_flowers";
|
||||
const forestFloor = "forrestfloor";
|
||||
const dirt1 = "grass_sand_75";
|
||||
const dirt2 = "grass_sand_50";
|
||||
const dirt3 = "dirt_brown_e";
|
||||
const cliffBase = "cliff base a";
|
||||
const cliffBeach = "beech_cliff_a_75";
|
||||
const cliff = "cliff_face3";
|
||||
|
||||
const oTree = "flora_tree_oak";
|
||||
const oGrass = "props/flora/grass_soft_small.xml"
|
||||
const oMine = "geology_stone_light";
|
||||
|
||||
// Initialize
|
||||
|
||||
init(SIZE, grass1, 0);
|
||||
|
||||
// Create classes
|
||||
|
||||
clImpassable = createTileClass();
|
||||
clRock = createTileClass();
|
||||
|
||||
// Paint elevation
|
||||
|
||||
noise0 = new Noise2D(4 * SIZE/128.0);
|
||||
noise1 = new Noise2D(8 * SIZE/128.0);
|
||||
@ -9,8 +32,6 @@ noise2 = new Noise2D(11 * SIZE/128.0);
|
||||
noise3 = new Noise2D(30 * SIZE/128.0);
|
||||
noise4 = new Noise2D(60 * SIZE/128.0);
|
||||
|
||||
// Paint elevation
|
||||
|
||||
for(ix=0; ix<SIZE+1; ix++) {
|
||||
for(iy=0; iy<SIZE+1; iy++) {
|
||||
x = ix / (SIZE + 1.0);
|
||||
@ -23,35 +44,21 @@ for(ix=0; ix<SIZE+1; ix++) {
|
||||
|
||||
if(n < T) {
|
||||
// Tile is underwater - just scale the height down a bit
|
||||
h = Math.max(-60 * (T-n)/T, -30);
|
||||
h = Math.max(-50 * (T-n)/T, -8);
|
||||
}
|
||||
else {
|
||||
// Tile is above water - add some land noise depending on how far
|
||||
// we are from the shoreline
|
||||
u = 25*noise1.eval(x, y) + 12*noise2.eval(x,y) + 8 * noise3.eval(x,y) - 11;
|
||||
// Tile is above water - add some land noise depending on how far we are from the shoreline
|
||||
u = 27*noise1.eval(x, y) + 14*noise2.eval(x,y) + 9 * noise3.eval(x,y) - 14;
|
||||
h = 8*(n-T) + Math.max(0, lerp(0, u, Math.min(.1, n-T)*10));
|
||||
h += 0.4*noise4.eval(x, y);
|
||||
}
|
||||
|
||||
h += SEA_LEVEL;
|
||||
|
||||
setHeight(ix, iy, h);
|
||||
}
|
||||
}
|
||||
|
||||
// Paint terrains
|
||||
|
||||
sand = "beach_medit_dry";
|
||||
grass1 = "grass_temperate_a";
|
||||
grass2 = "grass_mediterranean_green_flowers";
|
||||
forestFloor = "forrestfloor";
|
||||
dirt1 = "grass_sand_75";
|
||||
dirt2 = "grass_sand_50";
|
||||
dirt3 = "dirt_brown_e";
|
||||
cliffBase = "cliff base a";
|
||||
cliffBeach = "beech_cliff_a_75";
|
||||
cliff = "cliff_face3";
|
||||
|
||||
for(ix=0; ix<SIZE; ix++) {
|
||||
for(iy=0; iy<SIZE; iy++) {
|
||||
h00 = getHeight(ix, iy);
|
||||
@ -60,20 +67,21 @@ for(ix=0; ix<SIZE; ix++) {
|
||||
h11 = getHeight(ix+1, iy+1);
|
||||
maxH = Math.max(h00, h01, h10, h11);
|
||||
minH = Math.min(h00, h01, h10, h11);
|
||||
if(maxH <= SEA_LEVEL) {
|
||||
if(maxH <= 0) {
|
||||
setTexture(ix, iy, sand);
|
||||
addToClass(ix, iy, clImpassable);
|
||||
}
|
||||
else if(maxH - minH > 3.2 && minH >= SEA_LEVEL) {
|
||||
else if(maxH - minH > 3.2) {
|
||||
setTexture(ix, iy, cliff);
|
||||
}
|
||||
else if(maxH - minH > 2.7 && minH < SEA_LEVEL) {
|
||||
setTexture(ix, iy, cliffBeach);
|
||||
addToClass(ix, iy, clImpassable);
|
||||
}
|
||||
else if(maxH - minH > 2.7) {
|
||||
setTexture(ix, iy, cliffBase);
|
||||
addToClass(ix, iy, clImpassable);
|
||||
}
|
||||
else if(minH <= SEA_LEVEL) {
|
||||
else if(minH <= 0) {
|
||||
setTexture(ix, iy, sand);
|
||||
addToClass(ix, iy, clImpassable);
|
||||
}
|
||||
else {
|
||||
setTexture(ix, iy, grass1);
|
||||
@ -81,12 +89,10 @@ for(ix=0; ix<SIZE; ix++) {
|
||||
}
|
||||
}
|
||||
|
||||
oTree = "flora_tree_oak";
|
||||
oGrass = "props/flora/grass_soft_small.xml"
|
||||
// Paint forest and dirt
|
||||
|
||||
forestNoise1 = new Noise2D(20 * SIZE/128.0);
|
||||
forestNoise2 = new Noise2D(40 * SIZE/128.0);
|
||||
|
||||
dirtNoise = new Noise2D(80 * SIZE/128.0);
|
||||
|
||||
for(ix=0; ix<SIZE; ix++) {
|
||||
@ -99,7 +105,7 @@ for(ix=0; ix<SIZE; ix++) {
|
||||
h11 = getHeight(ix+1, iy+1);
|
||||
maxH = Math.max(h00, h01, h10, h11);
|
||||
minH = Math.min(h00, h01, h10, h11);
|
||||
if(maxH - minH < 1.7 && minH > SEA_LEVEL) {
|
||||
if(maxH - minH < 1.7 && minH > 0) {
|
||||
fn = (forestNoise1.eval(x,y) + .5*forestNoise1.eval(x,y)) / 1.5;
|
||||
|
||||
if(minH > .5 && fn < .38 && dirtNoise.eval(x,y) > .55) {
|
||||
@ -113,49 +119,19 @@ for(ix=0; ix<SIZE; ix++) {
|
||||
|
||||
if(fn > .6 && randFloat() < (.3 + .7 * Math.min(fn-.6, .1) / .1) ) {
|
||||
placeObject(oTree, 0, ix+.4+.2*randFloat(), iy+.4+.2*randFloat(), randFloat()*2*Math.PI);
|
||||
addToClass(ix, iy, clImpassable);
|
||||
if(randFloat() < .7) {
|
||||
setTexture(ix, iy, forestFloor);
|
||||
}
|
||||
}
|
||||
else if(getTexture(ix, iy)==grass1 && maxH-minH < 1 && randFloat() < .13) {
|
||||
placeObject(oGrass, 0, ix+.3+.4*randFloat(), iy+.3+.4*randFloat(), randFloat()*2*Math.PI);
|
||||
}
|
||||
else if(getTexture(ix, iy)==grass1 && randFloat() < .03) {
|
||||
placeObject(oTree, 0, ix+.3+.4*randFloat(), iy+.3+.4*randFloat(), randFloat()*2*Math.PI);
|
||||
}
|
||||
|
||||
/*else if(getTerrain(ix, iy)==grass && fn > .5 && randFloat() < .04) {
|
||||
placeBushClump(ix+.5, iy+.5);
|
||||
}
|
||||
else if(randFloat() < .04 && (maxH < .5 || randFloat() < .2)) {
|
||||
placeRockClump(ix+.5, iy+.5);
|
||||
}
|
||||
else if(getTerrain(ix, iy)==grass && maxH-minH < .4 && randFloat() < .1) {
|
||||
addSprite(new Sprite(makeGrass(),
|
||||
ix+.3+.4*randFloat(), iy+.3+.4*randFloat(), STATIC));
|
||||
}
|
||||
else if(randFloat() < .015) {
|
||||
addSprite(new Sprite(makeSmallRock(),
|
||||
ix+randFloat(), iy+randFloat(), STATIC));
|
||||
}
|
||||
else if(getTerrain(ix, iy)==grass && randFloat() < .03) {
|
||||
var t = new Sprite(makeOak(),
|
||||
ix+.3+.4*randFloat(), iy+.3+4*randFloat(), STATIC);
|
||||
t.maxY = 4;
|
||||
t.collidable = true;
|
||||
addSprite(t);
|
||||
}*/
|
||||
}
|
||||
|
||||
/*if(maxH < .5 && minH < -0.3 && minH > -2 && randFloat() < .007) {
|
||||
var l = new Sprite(waterLog, ix+randFloat(), iy+randFloat(), STATIC);
|
||||
l.floating = true;
|
||||
addSprite(l);
|
||||
}
|
||||
else if(maxH < 0 && minH > -3 && randFloat() < .04) {
|
||||
var l = new Sprite(lillies, ix+randFloat(), iy+randFloat(), STATIC);
|
||||
l.floating = true;
|
||||
addSprite(l);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
println("Creating mines...");
|
||||
group = new SimpleGroup([new SimpleObject(oMine, 3,4, 0,2)], true, clRock);
|
||||
createObjectGroups(group, 0,
|
||||
new AvoidTileClassConstraint(clImpassable, 2, clRock, 13),
|
||||
12, 100
|
||||
);
|
||||
|
||||
|
@ -71,6 +71,10 @@ function round(x) {
|
||||
return Math.round(x);
|
||||
}
|
||||
|
||||
function lerp(a, b, t) {
|
||||
return a + (b-a) * t;
|
||||
}
|
||||
|
||||
function println(x) {
|
||||
print(x);
|
||||
print("\n");
|
||||
@ -251,6 +255,18 @@ function SimpleGroup(elements, avoidSelf, tileClass, x, y) {
|
||||
this.y = x!=undefined ? y : -1;
|
||||
}
|
||||
|
||||
function lerp(a, b, t) {
|
||||
return a + (b-a) * t;
|
||||
}
|
||||
// Utility functions for classes
|
||||
|
||||
// Create a painter for the given class
|
||||
function paintClass(cl) {
|
||||
return new TileClassPainter(cl);
|
||||
}
|
||||
|
||||
// Create an avoid constraint for the given classes by the given distances
|
||||
function avoidClasses(/*class1, dist1, class2, dist2, etc*/) {
|
||||
var ar = new Array(arguments.length/2);
|
||||
for(var i=0; i<arguments.length/2; i++) {
|
||||
ar[i] = new AvoidTileClassConstraint(arguments[2*i], arguments[2*i+1]);
|
||||
}
|
||||
return ar;
|
||||
}
|
||||
|
@ -29,6 +29,8 @@ JSFunctionSpec globalFunctions[] = {
|
||||
{"createArea", createArea, 3},
|
||||
{"createObjectGroup", createObjectGroup, 3},
|
||||
{"createTileClass", createTileClass, 0},
|
||||
{"addToClass", addToClass, 0},
|
||||
{"removeFromClass", removeFromClass, 0},
|
||||
{0, 0, 0}
|
||||
};
|
||||
|
||||
@ -367,6 +369,42 @@ JSBool createTileClass(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, js
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool addToClass(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
CheckInit(true, cx, __FUNCTION__);
|
||||
ValidateArgs("iii", cx, argc, argv, __FUNCTION__);
|
||||
|
||||
int x = JSVAL_TO_INT(argv[0]);
|
||||
int y = JSVAL_TO_INT(argv[1]);
|
||||
int classIndex = JSVAL_TO_INT(argv[2]) - 1;
|
||||
|
||||
if(!theMap->validClass(classIndex) || !theMap->validT(x, y)) {
|
||||
JS_ReportError(cx, "addToClass: Invalid arguments for addToClass(x, y, class)");
|
||||
}
|
||||
|
||||
theMap->tileClasses[classIndex]->add(x, y);
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool removeFromClass(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
CheckInit(true, cx, __FUNCTION__);
|
||||
ValidateArgs("iii", cx, argc, argv, __FUNCTION__);
|
||||
|
||||
int x = JSVAL_TO_INT(argv[0]);
|
||||
int y = JSVAL_TO_INT(argv[1]);
|
||||
int classIndex = JSVAL_TO_INT(argv[2]) - 1;
|
||||
|
||||
if(!theMap->validClass(classIndex) || !theMap->validT(x, y)) {
|
||||
JS_ReportError(cx, "addToClass: Invalid arguments for removeFromClass(x, y, class)");
|
||||
}
|
||||
|
||||
theMap->tileClasses[classIndex]->remove(x, y);
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool getMapSize(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
CheckInit(true, cx, __FUNCTION__);
|
||||
|
@ -33,5 +33,7 @@ JSBool createObjectGroup(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
|
||||
// Tile class functions
|
||||
JSBool createTileClass(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
JSBool addToClass(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
JSBool removeFromClass(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
|
||||
#endif
|
@ -219,14 +219,6 @@ int Map::getId(string texture) {
|
||||
}
|
||||
}
|
||||
|
||||
bool Map::validT(int x, int y) {
|
||||
return x>=0 && y>=0 && x<size && y<size;
|
||||
}
|
||||
|
||||
bool Map::validH(int x, int y) {
|
||||
return x>=0 && y>=0 && x<size+1 && y<size+1;
|
||||
}
|
||||
|
||||
string Map::getTexture(int x, int y) {
|
||||
if(!validT(x,y)) JS_ReportError(cx, "getTexture: invalid tile position");
|
||||
return idToName[texture[x][y]];
|
||||
|
@ -29,8 +29,10 @@ public:
|
||||
|
||||
int getId(std::string texture);
|
||||
|
||||
bool validT(int x, int y);
|
||||
bool validH(int x, int y);
|
||||
bool validT(int x, int y) { return x>=0 && y>=0 && x<size && y<size; }
|
||||
bool validH(int x, int y) { return x>=0 && y>=0 && x<=size && y<=size; }
|
||||
|
||||
bool validClass(int c) { return c>=0 && c<(int)tileClasses.size(); }
|
||||
|
||||
std::string getTexture(int x, int y);
|
||||
void setTexture(int x, int y, const std::string& texture);
|
||||
|
152
source/tools/rmgen/noise.cpp
Normal file
152
source/tools/rmgen/noise.cpp
Normal file
@ -0,0 +1,152 @@
|
||||
#include "stdafx.h"
|
||||
#include "Noise.h"
|
||||
#include <cmath>
|
||||
#include "random.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace
|
||||
{
|
||||
/// Utility function used in both noises as an ease curve
|
||||
float easeCurve(float t)
|
||||
{
|
||||
return t*t*t*(t*(t*6-15)+10);
|
||||
}
|
||||
}
|
||||
|
||||
Noise2D::Noise2D(int f)
|
||||
{
|
||||
freq = f;
|
||||
grads = new CVector2D_Maths*[freq];
|
||||
for(int i=0; i<freq; i++)
|
||||
{
|
||||
grads[i] = new CVector2D_Maths[freq];
|
||||
for(int j=0; j<freq; j++)
|
||||
{
|
||||
float a = RandFloat() * 2 * PI;
|
||||
grads[i][j] = CVector2D_Maths(cos(a), sin(a));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Noise2D::~ Noise2D()
|
||||
{
|
||||
for(int i=0; i<freq; i++)
|
||||
{
|
||||
delete[] grads[i];
|
||||
}
|
||||
delete[] grads;
|
||||
}
|
||||
|
||||
float Noise2D::operator()(float x, float y)
|
||||
{
|
||||
x *= freq;
|
||||
y *= freq;
|
||||
|
||||
int ix = (int)floor(x);
|
||||
int iy = (int)floor(y);
|
||||
|
||||
float fx = x - ix;
|
||||
float fy = y - iy;
|
||||
|
||||
ix %= freq; if(ix<0) ix += freq;
|
||||
iy %= freq; if(iy<0) iy += freq;
|
||||
|
||||
int ix1 = (ix+1) % freq;
|
||||
int iy1 = (iy+1) % freq;
|
||||
|
||||
float s = grads[ix][iy].Dot(CVector2D_Maths(fx, fy));
|
||||
float t = grads[ix1][iy].Dot(CVector2D_Maths(fx-1, fy));
|
||||
float u = grads[ix][iy1].Dot(CVector2D_Maths(fx, fy-1));
|
||||
float v = grads[ix1][iy1].Dot(CVector2D_Maths(fx-1, fy-1));
|
||||
|
||||
float ex = easeCurve(fx);
|
||||
float ey = easeCurve(fy);
|
||||
float a = s + ex*(t-s);
|
||||
float b = u + ex*(v-u);
|
||||
return (a + ey*(b-a)) * .5 + .5;
|
||||
}
|
||||
|
||||
Noise3D::Noise3D(int f, int v) : freq(f), vfreq(v)
|
||||
{
|
||||
grads = new CVector3D**[freq];
|
||||
for(int i=0; i<freq; i++)
|
||||
{
|
||||
grads[i] = new CVector3D*[freq];
|
||||
for(int j=0; j<freq; j++)
|
||||
{
|
||||
grads[i][j] = new CVector3D[vfreq];
|
||||
for(int k=0; k<vfreq; k++)
|
||||
{
|
||||
CVector3D v;
|
||||
do {
|
||||
v = CVector3D(2*RandFloat()-1, 2*RandFloat()-1, 2*RandFloat()-1);
|
||||
}
|
||||
while(v.LengthSquared() > 1 || v.LengthSquared() < 0.1);
|
||||
v.Normalize();
|
||||
grads[i][j][k] = CVector3D(v.X, v.Y, v.Z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Noise3D::~ Noise3D()
|
||||
{
|
||||
for(int i=0; i<freq; i++)
|
||||
{
|
||||
for(int j=0; j<freq; j++)
|
||||
{
|
||||
delete[] grads[i][j];
|
||||
}
|
||||
delete[] grads[i];
|
||||
}
|
||||
delete[] grads;
|
||||
}
|
||||
|
||||
float Noise3D::operator()(float x, float y, float z)
|
||||
{
|
||||
x *= freq;
|
||||
y *= freq;
|
||||
z *= vfreq;
|
||||
|
||||
int ix = (int)floor(x);
|
||||
int iy = (int)floor(y);
|
||||
int iz = (int)floor(z);
|
||||
|
||||
float fx = x - ix;
|
||||
float fy = y - iy;
|
||||
float fz = z - iz;
|
||||
|
||||
ix %= freq; if(ix<0) ix += freq;
|
||||
iy %= freq; if(iy<0) iy += freq;
|
||||
iz %= vfreq; if(iz<0) iz += vfreq;
|
||||
|
||||
int ix1 = (ix+1) % freq;
|
||||
int iy1 = (iy+1) % freq;
|
||||
int iz1 = (iz+1) % vfreq;
|
||||
|
||||
float s0 = grads[ix][iy][iz].Dot(CVector3D(fx, fy, fz));
|
||||
float t0 = grads[ix1][iy][iz].Dot(CVector3D(fx-1, fy, fz));
|
||||
float u0 = grads[ix][iy1][iz].Dot(CVector3D(fx, fy-1, fz));
|
||||
float v0 = grads[ix1][iy1][iz].Dot(CVector3D(fx-1, fy-1, fz));
|
||||
|
||||
float s1 = grads[ix][iy][iz1].Dot(CVector3D(fx, fy, fz-1));
|
||||
float t1 = grads[ix1][iy][iz1].Dot(CVector3D(fx-1, fy, fz-1));
|
||||
float u1 = grads[ix][iy1][iz1].Dot(CVector3D(fx, fy-1, fz-1));
|
||||
float v1 = grads[ix1][iy1][iz1].Dot(CVector3D(fx-1, fy-1, fz-1));
|
||||
|
||||
float ex = easeCurve(fx);
|
||||
float ey = easeCurve(fy);
|
||||
float ez = easeCurve(fz);
|
||||
|
||||
float a0 = s0 + ex*(t0-s0);
|
||||
float b0 = u0 + ex*(v0-u0);
|
||||
float c0 = a0 + ey*(b0-a0);
|
||||
|
||||
float a1 = s1 + ex*(t1-s1);
|
||||
float b1 = u1 + ex*(v1-u1);
|
||||
float c1 = a1 + ey*(b1-a1);
|
||||
|
||||
return (c0 + ez*(c1-c0)) * .5 + .5;
|
||||
}
|
||||
|
54
source/tools/rmgen/noise.h
Normal file
54
source/tools/rmgen/noise.h
Normal file
@ -0,0 +1,54 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: Noise.h
|
||||
// Author: Matei Zaharia
|
||||
// Contact: matei@wildfiregames.com
|
||||
//
|
||||
// Description: 2D and 3D seamless Perlin noise classes. Not optimized for speed yet.
|
||||
//
|
||||
// Based on http://www.cs.cmu.edu/~mzucker/code/perlin-noise-math-faq.html
|
||||
// and http://mrl.nyu.edu/~perlin/paper445.pdf.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef NOISE_H
|
||||
#define NOISE_H
|
||||
|
||||
#include "Vector2D.h"
|
||||
#include "Vector3D.h"
|
||||
#include "MathUtil.h"
|
||||
|
||||
class Noise2D
|
||||
{
|
||||
/// Frequency in X and Y
|
||||
int freq;
|
||||
|
||||
/// freq*freq random gradient vectors in the unit cube
|
||||
CVector2D_Maths** grads;
|
||||
public:
|
||||
Noise2D(int freq);
|
||||
~Noise2D();
|
||||
|
||||
/// Evaluate the noise function at a given point
|
||||
float operator() (float x, float y);
|
||||
};
|
||||
|
||||
class Noise3D
|
||||
{
|
||||
/// Frequency in X and Y
|
||||
int freq;
|
||||
|
||||
/// Frequency in Z (vertical frequency)
|
||||
int vfreq;
|
||||
|
||||
/// freq*freq*vfreq random gradient vectors in the unit cube
|
||||
CVector3D*** grads;
|
||||
public:
|
||||
Noise3D(int freq, int vfreq);
|
||||
~Noise3D();
|
||||
|
||||
/// Evaluate the noise function at a given point
|
||||
float operator() (float x, float y, float z);
|
||||
};
|
||||
|
||||
#endif
|
@ -4,11 +4,15 @@
|
||||
#include "map.h"
|
||||
#include "object.h"
|
||||
#include "pmp_file.h"
|
||||
#include <iomanip>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Sea level elevation
|
||||
const float SEA_LEVEL = 20.0f;
|
||||
|
||||
void OutputObject(Map* m, Object* e, ostringstream& xml) {
|
||||
float height = m->getExactHeight(e->x, e->y);
|
||||
float height = m->getExactHeight(e->x, e->y) + SEA_LEVEL;
|
||||
|
||||
if(e->isEntity()) {
|
||||
xml << "\
|
||||
@ -52,7 +56,6 @@ void OutputXml(Map* m, FILE* f) {
|
||||
ostringstream xml;
|
||||
xml << "\
|
||||
<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\n\
|
||||
<!DOCTYPE Scenario SYSTEM \"/maps/scenario_v4.dtd\">\n\
|
||||
<Scenario>\n\
|
||||
<Environment>\n\
|
||||
<SunColour r=\"1\" g=\"1\" b=\"1\" />\n\
|
||||
@ -60,6 +63,7 @@ void OutputXml(Map* m, FILE* f) {
|
||||
<SunRotation angle=\"4.712389\" />\n\
|
||||
<TerrainAmbientColour r=\"0.5\" g=\"0.5\" b=\"0.5\" />\n\
|
||||
<UnitsAmbientColour r=\"0.52\" g=\"0.52\" b=\"0.52\" />\n\
|
||||
<Water><WaterBody><Height>" << SEA_LEVEL-0.1f << "</Height></WaterBody></Water>\n\
|
||||
</Environment>\n\
|
||||
<Entities>\n";
|
||||
OutputObjects(xml, m, true); // print entities
|
||||
@ -67,7 +71,8 @@ void OutputXml(Map* m, FILE* f) {
|
||||
</Entities>\n\
|
||||
<Nonentities>\n";
|
||||
OutputObjects(xml, m, false); // print nonentities
|
||||
xml << "</Nonentities>\n\
|
||||
xml << "\
|
||||
</Nonentities>\n\
|
||||
</Scenario>\n";
|
||||
|
||||
fprintf(f, "%s", xml.str().c_str());
|
||||
@ -117,7 +122,7 @@ struct PMP {
|
||||
u16* heightmap = new u16[(size+1)*(size+1)];
|
||||
for(int x=0; x<size+1; x++) {
|
||||
for(int y=0; y<size+1; y++) {
|
||||
int intHeight = (int) (m->height[x][y] * 256.0f / 0.35f);
|
||||
int intHeight = (int) ((m->height[x][y]+SEA_LEVEL) * 256.0f / 0.35f);
|
||||
if(intHeight > 0xFFFF) {
|
||||
intHeight = 0xFFFF;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user