2012-12-10 22:05:53 +00:00
|
|
|
#include "private.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Terrain height map painting.
|
|
|
|
*/
|
2012-07-13 12:23:58 +00:00
|
|
|
|
|
|
|
#include <stdlib.h>
|
2013-01-10 15:41:14 +00:00
|
|
|
#include <string.h>
|
2013-01-10 21:21:56 +00:00
|
|
|
#include <math.h>
|
2012-12-10 22:05:53 +00:00
|
|
|
|
2013-01-10 15:41:14 +00:00
|
|
|
TerrainHeightMap* terrainHeightMapCreate()
|
2012-07-13 12:23:58 +00:00
|
|
|
{
|
2013-01-10 15:41:14 +00:00
|
|
|
TerrainHeightMap* result;
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2013-01-10 15:41:14 +00:00
|
|
|
result = malloc(sizeof(TerrainHeightMap));
|
|
|
|
result->fixed_count = 0;
|
|
|
|
result->fixed_data = malloc(sizeof(TerrainHeightMapData));
|
|
|
|
result->floating_used = 0;
|
|
|
|
result->floating_data.data = malloc(sizeof(double));
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-07-13 12:23:58 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2012-12-10 22:05:53 +00:00
|
|
|
void terrainHeightmapDelete(TerrainHeightMap* heightmap)
|
2012-07-13 12:23:58 +00:00
|
|
|
{
|
2013-01-10 15:41:14 +00:00
|
|
|
int i;
|
|
|
|
for (i = 0; i < heightmap->fixed_count; i++)
|
|
|
|
{
|
|
|
|
free(heightmap->fixed_data[i].data);
|
|
|
|
}
|
|
|
|
free(heightmap->fixed_data);
|
|
|
|
free(heightmap->floating_data.data);
|
|
|
|
free(heightmap);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void _setFixedCount(TerrainHeightMap* heightmap, int new_count)
|
|
|
|
{
|
|
|
|
int old_count = heightmap->fixed_count;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (new_count > old_count)
|
|
|
|
{
|
|
|
|
heightmap->fixed_data = realloc(heightmap->fixed_data, sizeof(TerrainHeightMapData) * new_count);
|
|
|
|
for (i = old_count; i < new_count; i++)
|
|
|
|
{
|
|
|
|
heightmap->fixed_data[i].data = malloc(sizeof(double));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (new_count < old_count)
|
|
|
|
{
|
|
|
|
for (i = new_count; i < old_count; i++)
|
|
|
|
{
|
|
|
|
free(heightmap->fixed_data[i].data);
|
|
|
|
}
|
|
|
|
if (new_count > 0)
|
|
|
|
{
|
|
|
|
heightmap->fixed_data = realloc(heightmap->fixed_data, sizeof(TerrainHeightMapData) * new_count);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
heightmap->fixed_count = new_count;
|
2012-07-13 12:23:58 +00:00
|
|
|
}
|
|
|
|
|
2012-12-10 22:05:53 +00:00
|
|
|
void terrainHeightmapCopy(TerrainHeightMap* source, TerrainHeightMap* destination)
|
2012-07-13 12:23:58 +00:00
|
|
|
{
|
2013-01-10 21:21:56 +00:00
|
|
|
int i;
|
2013-01-10 15:41:14 +00:00
|
|
|
|
|
|
|
_setFixedCount(destination, source->fixed_count);
|
|
|
|
|
|
|
|
for (i = 0; i < destination->fixed_count; i++)
|
|
|
|
{
|
|
|
|
destination->fixed_data[i].xstart = source->fixed_data[i].xstart;
|
|
|
|
destination->fixed_data[i].xsize = source->fixed_data[i].xsize;
|
|
|
|
destination->fixed_data[i].ystart = source->fixed_data[i].ystart;
|
|
|
|
destination->fixed_data[i].ysize = source->fixed_data[i].ysize;
|
|
|
|
if (destination->fixed_data[i].xsize * destination->fixed_data[i].ysize > 0)
|
|
|
|
{
|
|
|
|
destination->fixed_data[i].data = realloc(destination->fixed_data[i].data, sizeof(double) * destination->fixed_data[i].xsize * destination->fixed_data[i].ysize);
|
|
|
|
}
|
|
|
|
memcpy(destination->fixed_data[i].data, source->fixed_data[i].data, sizeof(double) * destination->fixed_data[i].xsize * destination->fixed_data[i].ysize);
|
|
|
|
}
|
|
|
|
|
|
|
|
destination->floating_used = 0;
|
2012-07-13 12:23:58 +00:00
|
|
|
}
|
|
|
|
|
2012-12-10 22:05:53 +00:00
|
|
|
void terrainHeightmapSave(PackStream* stream, TerrainHeightMap* heightmap)
|
2012-07-13 12:23:58 +00:00
|
|
|
{
|
2013-01-10 15:41:14 +00:00
|
|
|
int i, j;
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2013-01-10 15:41:14 +00:00
|
|
|
packWriteInt(stream, &heightmap->fixed_count);
|
|
|
|
for (i = 0; i < heightmap->fixed_count; i++)
|
2012-07-13 12:23:58 +00:00
|
|
|
{
|
2013-01-10 15:41:14 +00:00
|
|
|
packWriteInt(stream, &heightmap->fixed_data[i].xstart);
|
|
|
|
packWriteInt(stream, &heightmap->fixed_data[i].xsize);
|
|
|
|
packWriteInt(stream, &heightmap->fixed_data[i].ystart);
|
|
|
|
packWriteInt(stream, &heightmap->fixed_data[i].ysize);
|
|
|
|
for (j = 0; j < heightmap->fixed_data[i].xsize * heightmap->fixed_data[i].ysize; j++)
|
|
|
|
{
|
|
|
|
packWriteDouble(stream, &heightmap->fixed_data[i].data[j]);
|
|
|
|
}
|
|
|
|
}
|
2012-07-13 12:23:58 +00:00
|
|
|
}
|
|
|
|
|
2012-12-10 22:05:53 +00:00
|
|
|
void terrainHeightmapLoad(PackStream* stream, TerrainHeightMap* heightmap)
|
2012-07-13 12:23:58 +00:00
|
|
|
{
|
2013-01-10 15:41:14 +00:00
|
|
|
int new_count, i, j;
|
|
|
|
|
|
|
|
packReadInt(stream, &new_count);
|
|
|
|
_setFixedCount(heightmap, new_count);
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2013-01-10 15:41:14 +00:00
|
|
|
for (i = 0; i < heightmap->fixed_count; i++)
|
2012-07-13 12:23:58 +00:00
|
|
|
{
|
2013-01-10 15:41:14 +00:00
|
|
|
packReadInt(stream, &heightmap->fixed_data[i].xstart);
|
|
|
|
packReadInt(stream, &heightmap->fixed_data[i].xsize);
|
|
|
|
packReadInt(stream, &heightmap->fixed_data[i].ystart);
|
|
|
|
packReadInt(stream, &heightmap->fixed_data[i].ysize);
|
|
|
|
if (heightmap->fixed_data[i].xsize * heightmap->fixed_data[i].ysize > 0)
|
|
|
|
{
|
|
|
|
heightmap->fixed_data[i].data = realloc(heightmap->fixed_data[i].data, sizeof(double) * heightmap->fixed_data[i].xsize * heightmap->fixed_data[i].ysize);
|
|
|
|
}
|
|
|
|
for (j = 0; j < heightmap->fixed_data[i].xsize * heightmap->fixed_data[i].ysize; j++)
|
|
|
|
{
|
|
|
|
packReadDouble(stream, &heightmap->fixed_data[i].data[j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
heightmap->floating_used = 0;
|
|
|
|
}
|
|
|
|
|
2013-01-10 21:21:56 +00:00
|
|
|
static void _prepareBrushStroke(TerrainHeightMap* heightmap, TerrainBrush* brush)
|
|
|
|
{
|
|
|
|
double cx = brush->relative_x / TERRAIN_HEIGHTMAP_DETAIL;
|
|
|
|
double cz = brush->relative_z / TERRAIN_HEIGHTMAP_DETAIL;
|
|
|
|
double s = brush->smoothed_size + brush->hard_radius;
|
|
|
|
double sx = s / TERRAIN_HEIGHTMAP_DETAIL;
|
|
|
|
double sz = s / TERRAIN_HEIGHTMAP_DETAIL;
|
|
|
|
|
|
|
|
int x1 = (int)floor(cx - sx);
|
|
|
|
int x2 = (int)ceil(cx + sx);
|
|
|
|
int z1 = (int)floor(cz - sz);
|
|
|
|
int z2 = (int)ceil(cz + sz);
|
|
|
|
|
|
|
|
/* TODO Prepare floating data */
|
|
|
|
}
|
|
|
|
|
2013-01-10 15:41:14 +00:00
|
|
|
void terrainBrushElevation(TerrainHeightMap* heightmap, TerrainBrush* brush, double value)
|
|
|
|
{
|
2012-12-10 22:05:53 +00:00
|
|
|
}
|
|
|
|
|
2013-01-10 15:41:14 +00:00
|
|
|
void terrainBrushSmooth(TerrainHeightMap* heightmap, TerrainBrush* brush, double value)
|
2012-12-10 22:05:53 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2013-01-10 15:41:14 +00:00
|
|
|
void terrainBrushAddNoise(TerrainHeightMap* heightmap, TerrainBrush* brush, NoiseGenerator* generator, double value)
|
2012-12-10 22:05:53 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2013-01-10 15:41:14 +00:00
|
|
|
void terrainBrushReset(TerrainHeightMap* heightmap, TerrainBrush* brush, double value)
|
2012-12-10 22:05:53 +00:00
|
|
|
{
|
2012-07-13 12:23:58 +00:00
|
|
|
}
|
2012-07-13 21:24:19 +00:00
|
|
|
|
2012-12-10 22:05:53 +00:00
|
|
|
#if 0
|
2012-07-19 15:04:27 +00:00
|
|
|
static void _loadFromFilePixel(HeightMap* heightmap, int x, int y, Color col)
|
|
|
|
{
|
|
|
|
assert(x >= 0 && x < heightmap->resolution_x);
|
|
|
|
assert(y >= 0 && y < heightmap->resolution_z);
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-07-19 15:04:27 +00:00
|
|
|
heightmap->data[y * heightmap->resolution_x + x] = (col.r + col.g + col.b) / 3.0;
|
|
|
|
}
|
|
|
|
|
2012-07-23 21:14:26 +00:00
|
|
|
void heightmapGetLimits(HeightMap* heightmap, double* ymin, double* ymax)
|
2012-07-23 09:58:06 +00:00
|
|
|
{
|
|
|
|
double y;
|
|
|
|
int i;
|
|
|
|
*ymin = 1000000.0;
|
|
|
|
*ymax = -1000000.0;
|
|
|
|
/* TODO Keep the value in cache */
|
|
|
|
for (i = 0; i < heightmap->resolution_x * heightmap->resolution_z; i++)
|
|
|
|
{
|
|
|
|
y = heightmap->data[i];
|
|
|
|
if (y < *ymin)
|
|
|
|
{
|
|
|
|
*ymin = y;
|
|
|
|
}
|
|
|
|
if (y > *ymax)
|
|
|
|
{
|
|
|
|
*ymax = y;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
double heightmapGetRawValue(HeightMap* heightmap, double x, double z)
|
|
|
|
{
|
|
|
|
assert(x >= 0.0 && x <= 1.0);
|
|
|
|
assert(z >= 0.0 && z <= 1.0);
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-07-23 09:58:06 +00:00
|
|
|
return heightmap->data[((int)(z * (double)(heightmap->resolution_z - 1))) * heightmap->resolution_x + ((int)(x * (double)(heightmap->resolution_x - 1)))];
|
|
|
|
}
|
|
|
|
|
2012-07-16 20:34:01 +00:00
|
|
|
double heightmapGetValue(HeightMap* heightmap, double x, double z)
|
|
|
|
{
|
2012-07-18 15:04:23 +00:00
|
|
|
int xmax = heightmap->resolution_x - 1;
|
|
|
|
int zmax = heightmap->resolution_z - 1;
|
2012-07-26 21:10:12 +00:00
|
|
|
int xlow;
|
|
|
|
int zlow;
|
2012-07-18 15:04:23 +00:00
|
|
|
double stencil[16];
|
|
|
|
int ix, iz, cx, cz;
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-07-26 21:10:12 +00:00
|
|
|
if (x < 0.0)
|
|
|
|
{
|
|
|
|
x = 0.0;
|
|
|
|
}
|
|
|
|
else if (x > 1.0)
|
|
|
|
{
|
|
|
|
x = 1.0;
|
|
|
|
}
|
|
|
|
if (z < 0.0)
|
|
|
|
{
|
|
|
|
z = 0.0;
|
|
|
|
}
|
|
|
|
else if (z > 1.0)
|
|
|
|
{
|
|
|
|
z = 1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
xlow = floor(x * xmax);
|
|
|
|
zlow = floor(z * zmax);
|
|
|
|
|
2012-07-18 15:04:23 +00:00
|
|
|
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];
|
|
|
|
}
|
|
|
|
}
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-07-18 15:04:23 +00:00
|
|
|
return toolsBicubicInterpolate(stencil, x * xmax - (double)xlow, z * zmax - (double)zlow);
|
2012-07-16 20:34:01 +00:00
|
|
|
}
|
|
|
|
|
2012-08-08 13:30:40 +00:00
|
|
|
|
|
|
|
void heightmapImportFromPicture(HeightMap* heightmap, const char* picturepath)
|
|
|
|
{
|
|
|
|
systemLoadPictureFile(picturepath, (PictureCallbackLoadStarted)heightmapChangeResolution, (PictureCallbackLoadPixel)_loadFromFilePixel, heightmap);
|
|
|
|
}
|
|
|
|
|
|
|
|
void heightmapChangeResolution(HeightMap* heightmap, int resolution_x, int resolution_z)
|
|
|
|
{
|
|
|
|
int i;
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-08-08 13:30:40 +00:00
|
|
|
heightmap->resolution_x = resolution_x;
|
|
|
|
heightmap->resolution_z = resolution_z;
|
|
|
|
heightmap->data = realloc(heightmap->data, sizeof(double) * heightmap->resolution_x * heightmap->resolution_z);
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-08-08 13:30:40 +00:00
|
|
|
for (i = 0; i < heightmap->resolution_x * heightmap->resolution_z; i++)
|
|
|
|
{
|
|
|
|
heightmap->data[i] = 0.0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void heightmapRevertToTerrain(HeightMap* heightmap, TerrainDefinition* terrain, GeoArea* area)
|
|
|
|
{
|
|
|
|
int rx, rz;
|
|
|
|
int x, z;
|
2012-08-08 14:44:37 +00:00
|
|
|
double dx, dz;
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-08-08 13:30:40 +00:00
|
|
|
rx = heightmap->resolution_x;
|
|
|
|
rz = heightmap->resolution_z;
|
|
|
|
for (x = 0; x < rx; x++)
|
|
|
|
{
|
|
|
|
for (z = 0; z < rz; z++)
|
|
|
|
{
|
2012-08-08 14:44:37 +00:00
|
|
|
dx = (double)x / (double)(rx - 1);
|
|
|
|
dz = (double)z / (double)(rz - 1);
|
|
|
|
geoareaFromLocal(area, dx, dz, &dx, &dz);
|
2012-12-09 17:49:28 +00:00
|
|
|
// heightmap->data[z * rx + x] = terrainGetHeight(terrain, dx, dz);
|
2012-08-08 13:30:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-12-10 22:05:53 +00:00
|
|
|
static inline void _getBrushBoundaries(TerrainBrush* brush, int rx, int rz, int* x1, int* x2, int* z1, int* z2)
|
2012-07-24 14:59:06 +00:00
|
|
|
{
|
|
|
|
double cx = brush->relative_x * rx;
|
|
|
|
double cz = brush->relative_z * rz;
|
|
|
|
double s = brush->smoothed_size + brush->hard_radius;
|
|
|
|
double sx = s * rx;
|
|
|
|
double sz = s * rz;
|
|
|
|
*x1 = (int)floor(cx - sx);
|
|
|
|
*x2 = (int)ceil(cx + sx);
|
|
|
|
*z1 = (int)floor(cz - sz);
|
|
|
|
*z2 = (int)ceil(cz + sz);
|
2012-07-26 21:10:12 +00:00
|
|
|
if (*x1 < 0)
|
2012-07-24 14:59:06 +00:00
|
|
|
{
|
|
|
|
*x1 = 0;
|
|
|
|
}
|
2012-07-26 21:10:12 +00:00
|
|
|
else if (*x1 > rx)
|
2012-07-24 14:59:06 +00:00
|
|
|
{
|
|
|
|
*x1 = rx;
|
|
|
|
}
|
2012-07-26 21:10:12 +00:00
|
|
|
if (*x2 < 0)
|
|
|
|
{
|
|
|
|
*x2 = 0;
|
|
|
|
}
|
|
|
|
else if (*x2 > rx)
|
|
|
|
{
|
|
|
|
*x2 = rx;
|
|
|
|
}
|
|
|
|
if (*z1 < 0)
|
2012-07-24 14:59:06 +00:00
|
|
|
{
|
|
|
|
*z1 = 0;
|
|
|
|
}
|
2012-07-26 21:10:12 +00:00
|
|
|
else if (*z1 > rz)
|
2012-07-24 14:59:06 +00:00
|
|
|
{
|
|
|
|
*z1 = rz;
|
|
|
|
}
|
2012-07-26 21:10:12 +00:00
|
|
|
if (*z2 < 0)
|
|
|
|
{
|
|
|
|
*z2 = 0;
|
|
|
|
}
|
|
|
|
else if (*z2 > rz)
|
|
|
|
{
|
|
|
|
*z2 = rz;
|
|
|
|
}
|
2012-07-24 14:59:06 +00:00
|
|
|
}
|
|
|
|
|
2012-12-10 22:05:53 +00:00
|
|
|
typedef double (*BrushCallback)(HeightMap* heightmap, TerrainBrush* brush, double x, double z, double basevalue, double influence, double force, void* data);
|
2012-07-26 11:55:19 +00:00
|
|
|
|
2012-12-10 22:05:53 +00:00
|
|
|
static inline void _applyBrush(HeightMap* heightmap, TerrainBrush* brush, double force, void* data, BrushCallback callback)
|
2012-07-16 15:48:05 +00:00
|
|
|
{
|
2012-07-24 14:59:06 +00:00
|
|
|
int x, x1, x2, z, z1, z2;
|
2012-08-08 13:30:40 +00:00
|
|
|
double dx, dz, distance, influence;
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-07-24 14:59:06 +00:00
|
|
|
_getBrushBoundaries(brush, heightmap->resolution_x - 1, heightmap->resolution_z - 1, &x1, &x2, &z1, &z2);
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-07-24 14:59:06 +00:00
|
|
|
for (x = x1; x <= x2; x++)
|
2012-07-16 15:48:05 +00:00
|
|
|
{
|
|
|
|
dx = (double)x / (double)heightmap->resolution_x;
|
2012-07-24 14:59:06 +00:00
|
|
|
for (z = z1; z <= z2; z++)
|
2012-07-16 15:48:05 +00:00
|
|
|
{
|
|
|
|
dz = (double)z / (double)heightmap->resolution_z;
|
|
|
|
distance = sqrt((brush->relative_x - dx) * (brush->relative_x - dx) + (brush->relative_z - dz) * (brush->relative_z - dz));
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-07-16 15:48:05 +00:00
|
|
|
if (distance > brush->hard_radius)
|
|
|
|
{
|
|
|
|
if (distance <= brush->hard_radius + brush->smoothed_size)
|
|
|
|
{
|
2012-07-26 11:55:19 +00:00
|
|
|
influence = (1.0 - (distance - brush->hard_radius) / brush->smoothed_size);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
continue;
|
2012-07-16 15:48:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-07-26 11:55:19 +00:00
|
|
|
influence = 1.0;
|
2012-07-16 15:48:05 +00:00
|
|
|
}
|
2012-12-09 17:49:28 +00:00
|
|
|
|
2012-07-26 11:55:19 +00:00
|
|
|
heightmap->data[z * heightmap->resolution_x + x] = callback(heightmap, brush, dx, dz, heightmap->data[z * heightmap->resolution_x + x], influence, force, data);
|
2012-07-16 15:48:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-07-24 14:59:06 +00:00
|
|
|
|
2012-12-10 22:05:53 +00:00
|
|
|
static double _applyBrushElevation(HeightMap* heightmap, TerrainBrush* brush, double x, double z, double basevalue, double influence, double force, void* data)
|
2012-07-24 14:59:06 +00:00
|
|
|
{
|
2012-07-26 11:55:19 +00:00
|
|
|
return basevalue + influence * force * brush->total_radius;
|
2012-07-24 14:59:06 +00:00
|
|
|
}
|
|
|
|
|
2012-12-10 22:05:53 +00:00
|
|
|
void terrainBrushElevation(HeightMap* heightmap, TerrainBrush* brush, double value)
|
2012-07-24 14:59:06 +00:00
|
|
|
{
|
2012-07-26 11:55:19 +00:00
|
|
|
_applyBrush(heightmap, brush, value, NULL, _applyBrushElevation);
|
|
|
|
}
|
|
|
|
|
2012-12-10 22:05:53 +00:00
|
|
|
static double _applyBrushSmooth(HeightMap* heightmap, TerrainBrush* brush, double x, double z, double basevalue, double influence, double force, void* data)
|
2012-07-26 11:55:19 +00:00
|
|
|
{
|
|
|
|
double ideal, factor;
|
|
|
|
ideal = heightmapGetValue(heightmap, x + brush->total_radius * 0.5, z);
|
|
|
|
ideal += heightmapGetValue(heightmap, x - brush->total_radius * 0.5, z);
|
|
|
|
ideal += heightmapGetValue(heightmap, x, z - brush->total_radius * 0.5);
|
|
|
|
ideal += heightmapGetValue(heightmap, x, z + brush->total_radius * 0.5);
|
|
|
|
ideal /= 4.0;
|
|
|
|
factor = influence * force;
|
|
|
|
if (factor > 1.0)
|
2012-07-24 14:59:06 +00:00
|
|
|
{
|
2012-07-26 11:55:19 +00:00
|
|
|
factor = 0.0;
|
2012-07-24 14:59:06 +00:00
|
|
|
}
|
2012-07-26 11:55:19 +00:00
|
|
|
return basevalue + (ideal - basevalue) * factor;
|
|
|
|
}
|
|
|
|
|
2012-12-10 22:05:53 +00:00
|
|
|
void terrainBrushSmooth(HeightMap* heightmap, TerrainBrush* brush, double value)
|
2012-07-26 11:55:19 +00:00
|
|
|
{
|
|
|
|
_applyBrush(heightmap, brush, value, NULL, _applyBrushSmooth);
|
|
|
|
}
|
|
|
|
|
2012-12-10 22:05:53 +00:00
|
|
|
static double _applyBrushAddNoise(HeightMap* heightmap, TerrainBrush* brush, double x, double z, double basevalue, double influence, double force, void* data)
|
2012-07-26 11:55:19 +00:00
|
|
|
{
|
|
|
|
return basevalue + noiseGet2DTotal((NoiseGenerator*)data, x / brush->total_radius, z / brush->total_radius) * influence * force * brush->total_radius;
|
|
|
|
}
|
|
|
|
|
2012-12-10 22:05:53 +00:00
|
|
|
void terrainBrushAddNoise(HeightMap* heightmap, TerrainBrush* brush, NoiseGenerator* generator, double value)
|
2012-07-26 11:55:19 +00:00
|
|
|
{
|
|
|
|
_applyBrush(heightmap, brush, value, generator, _applyBrushAddNoise);
|
2012-07-24 14:59:06 +00:00
|
|
|
}
|
2012-12-10 22:05:53 +00:00
|
|
|
#endif
|