paysages : Terrain canvas - Added bicubic interpolation and integration mask.
git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@393 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
parent
818b8b7b86
commit
2d2535deae
4 changed files with 73 additions and 18 deletions
|
@ -13,8 +13,8 @@ FormTerrainCanvas::FormTerrainCanvas(QWidget *parent, Layers* layers):
|
|||
addInputNoise(tr("Detail noise"), _definition->detail_noise);
|
||||
addInputDouble(tr("Detail noise height"), &_definition->detail_height_factor, 0.0, 20.0, 0.1, 1.0);
|
||||
addInputDouble(tr("Detail noise scaling"), &_definition->detail_scaling, 0.0, 20.0, 0.1, 1.0);
|
||||
addInputEnum(tr("Mask shape"), &_definition->mask_mode, QStringList(tr("Square")) << tr("Circle"));
|
||||
addInputDouble(tr("Mask smoothing"), &_definition->mask_smoothing, 0.0, 1.0, 0.01, 0.1);
|
||||
addInputEnum(tr("Mask shape"), &_definition->mask.mode, QStringList(tr("Square")) << tr("Circle"));
|
||||
addInputDouble(tr("Mask smoothing"), &_definition->mask.smoothing, 0.0, 1.0, 0.01, 0.1);
|
||||
|
||||
revertConfig();
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "heightmap.h"
|
||||
#include "tools.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -73,8 +74,26 @@ void heightmapChangeResolution(HeightMap* heightmap, int resolution_x, int resol
|
|||
|
||||
double heightmapGetValue(HeightMap* heightmap, double x, double z)
|
||||
{
|
||||
// TODO Bicubic interpolation
|
||||
return heightmap->data[lround(z * (heightmap->resolution_z - 1)) * heightmap->resolution_x + lround(x * (heightmap->resolution_x - 1))];
|
||||
int xmax = heightmap->resolution_x - 1;
|
||||
int zmax = heightmap->resolution_z - 1;
|
||||
int xlow = floor(x * xmax);
|
||||
int zlow = floor(z * zmax);
|
||||
double stencil[16];
|
||||
int ix, iz, cx, cz;
|
||||
|
||||
for (ix = xlow - 1; ix <= xlow + 2; ix++)
|
||||
{
|
||||
for (iz = zlow - 1; iz <= zlow + 2; iz++)
|
||||
{
|
||||
cx = ix < 0 ? 0 : ix;
|
||||
cx = cx > xmax ? xmax : cx;
|
||||
cz = iz < 0 ? 0 : iz;
|
||||
cz = cz > zmax ? zmax : cz;
|
||||
stencil[(iz - (zlow - 1)) * 4 + ix - (xlow - 1)] = heightmap->data[cz * heightmap->resolution_x + cx];
|
||||
}
|
||||
}
|
||||
|
||||
return toolsBicubicInterpolate(stencil, x * xmax - (double)xlow, z * zmax - (double)zlow);
|
||||
}
|
||||
|
||||
void heightmapBrushElevation(HeightMap* heightmap, HeightMapBrush* brush, double value)
|
||||
|
@ -82,7 +101,7 @@ void heightmapBrushElevation(HeightMap* heightmap, HeightMapBrush* brush, double
|
|||
int x, z;
|
||||
double dx, dz, distance;
|
||||
|
||||
// TODO Limit to brush radius
|
||||
/* TODO Limit to brush radius */
|
||||
|
||||
for (x = 0; x < heightmap->resolution_x; x++)
|
||||
{
|
||||
|
|
|
@ -19,8 +19,8 @@ TerrainCanvas* terrainCanvasCreate()
|
|||
result->detail_noise = noiseCreateGenerator();
|
||||
result->detail_height_factor = 0.1;
|
||||
result->detail_scaling = 1.0;
|
||||
result->mask_mode = TERRAINCANVAS_MASKMODE_SQUARE;
|
||||
result->mask_smoothing = 0.0;
|
||||
result->mask.mode = INTEGRATIONMASK_MODE_CIRCLE;
|
||||
result->mask.smoothing = 0.1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -41,8 +41,7 @@ void terrainCanvasCopy(TerrainCanvas* source, TerrainCanvas* destination)
|
|||
noiseCopy(source->detail_noise, destination->detail_noise);
|
||||
destination->detail_height_factor = source->detail_height_factor;
|
||||
destination->detail_scaling = source->detail_scaling;
|
||||
destination->mask_mode = source->mask_mode;
|
||||
destination->mask_smoothing = source->mask_smoothing;
|
||||
destination->mask = source->mask;
|
||||
}
|
||||
|
||||
void terrainCanvasValidate(TerrainCanvas* canvas)
|
||||
|
@ -82,8 +81,8 @@ void terrainCanvasSave(PackStream* stream, TerrainCanvas* canvas)
|
|||
noiseSaveGenerator(stream, canvas->detail_noise);
|
||||
packWriteDouble(stream, &canvas->detail_height_factor);
|
||||
packWriteDouble(stream, &canvas->detail_scaling);
|
||||
packWriteInt(stream, &canvas->mask_mode);
|
||||
packWriteDouble(stream, &canvas->mask_smoothing);
|
||||
packWriteInt(stream, &canvas->mask.mode);
|
||||
packWriteDouble(stream, &canvas->mask.smoothing);
|
||||
}
|
||||
|
||||
void terrainCanvasLoad(PackStream* stream, TerrainCanvas* canvas)
|
||||
|
@ -99,8 +98,8 @@ void terrainCanvasLoad(PackStream* stream, TerrainCanvas* canvas)
|
|||
noiseLoadGenerator(stream, canvas->detail_noise);
|
||||
packReadDouble(stream, &canvas->detail_height_factor);
|
||||
packReadDouble(stream, &canvas->detail_scaling);
|
||||
packReadInt(stream, &canvas->mask_mode);
|
||||
packReadDouble(stream, &canvas->mask_smoothing);
|
||||
packReadInt(stream, &canvas->mask.mode);
|
||||
packReadDouble(stream, &canvas->mask.smoothing);
|
||||
}
|
||||
|
||||
void terrainCanvasRevertToTerrain(TerrainCanvas* canvas, TerrainDefinition* terrain, int only_masked)
|
||||
|
@ -114,7 +113,39 @@ Vector3 terrainCanvasApply(TerrainCanvas* canvas, Vector3 location)
|
|||
location.x <= canvas->area.location_x + canvas->area.size_x &&
|
||||
location.z <= canvas->area.location_z + canvas->area.size_z)
|
||||
{
|
||||
location.y = heightmapGetValue(&canvas->height_map, (location.x - canvas->area.location_x) / canvas->area.size_x, (location.z - canvas->area.location_z) / canvas->area.size_z);
|
||||
double inside_x, inside_z;
|
||||
double height, distance;
|
||||
|
||||
/* Get height map displacement */
|
||||
inside_x = (location.x - canvas->area.location_x) / canvas->area.size_x;
|
||||
inside_z = (location.z - canvas->area.location_z) / canvas->area.size_z;
|
||||
height = heightmapGetValue(&canvas->height_map, inside_x, inside_z);
|
||||
|
||||
/* TODO Apply detail noise */
|
||||
|
||||
/* Apply integration mask */
|
||||
inside_x = (inside_x - 0.5) * 2.0;
|
||||
inside_z = (inside_z - 0.5) * 2.0;
|
||||
if (canvas->mask.mode == INTEGRATIONMASK_MODE_SQUARE)
|
||||
{
|
||||
inside_x = fabs(inside_x);
|
||||
inside_z = fabs(inside_z);
|
||||
distance = inside_x > inside_z ? inside_x : inside_z;
|
||||
}
|
||||
else
|
||||
{
|
||||
distance = sqrt(inside_x * inside_x + inside_z * inside_z);
|
||||
}
|
||||
if (distance <= 1.0 - canvas->mask.smoothing)
|
||||
{
|
||||
location.y = height;
|
||||
}
|
||||
else
|
||||
{
|
||||
double influence = (1.0 - distance) / canvas->mask.smoothing;
|
||||
location.y = influence * height + (1.0 - influence) * location.y;
|
||||
}
|
||||
|
||||
}
|
||||
return location;
|
||||
}
|
||||
|
|
|
@ -22,8 +22,14 @@ typedef struct
|
|||
double size_z;
|
||||
} GeoArea;
|
||||
|
||||
#define TERRAINCANVAS_MASKMODE_SQUARE 0
|
||||
#define TERRAINCANVAS_MASKMODE_CIRCLE 1
|
||||
typedef struct
|
||||
{
|
||||
int mode;
|
||||
double smoothing;
|
||||
} IntegrationMask;
|
||||
|
||||
#define INTEGRATIONMASK_MODE_SQUARE 0
|
||||
#define INTEGRATIONMASK_MODE_CIRCLE 1
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -34,8 +40,7 @@ typedef struct
|
|||
NoiseGenerator* detail_noise;
|
||||
double detail_height_factor;
|
||||
double detail_scaling;
|
||||
int mask_mode;
|
||||
double mask_smoothing;
|
||||
IntegrationMask mask;
|
||||
} TerrainCanvas;
|
||||
|
||||
TerrainCanvas* terrainCanvasCreate();
|
||||
|
|
Loading…
Reference in a new issue