paysages : Terrain painting (WIP).

git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@493 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
Michaël Lemaire 2013-01-14 12:08:38 +00:00 committed by ThunderK
parent b816ab1105
commit 5cad0fb39a
15 changed files with 134 additions and 58 deletions

View file

@ -49,7 +49,7 @@ bool ExplorerChunkTerrain::onMaintainEvent()
{
if (_tessellation_current_size == 0 || i % old_tessellation_inc != 0 || j % old_tessellation_inc != 0)
{
double height = renderer->terrain->getHeight(renderer, _startx + _tessellation_step * (double)i, _startz + _tessellation_step * (double)j);
double height = renderer->terrain->getHeight(renderer, _startx + _tessellation_step * (double)i, _startz + _tessellation_step * (double)j, 1);
_tessellation[j * (_tessellation_max_size + 1) + i] = height;
}
}

View file

@ -43,7 +43,7 @@ protected:
{
Vector3 down = {0.0, -1.0, 0.0};
Vector3 location;
double height = _renderer.terrain->getHeight(&_renderer, x, y);
double height = _renderer.terrain->getHeight(&_renderer, x, y, 1);
if (height < _water.height)
{

View file

@ -49,8 +49,8 @@ FormTerrain::FormTerrain(QWidget *parent):
addPreview(previewColor, tr("Lighted preview (no texture)"));
//addInputNoise(tr("Noise"), _definition.height_noise);
addInputDouble(tr("Height"), &_definition->height, 0.0, 20.0, 0.1, 1.0);
addInputDouble(tr("Scaling"), &_definition->scaling, 20.0, 200.0, 1.0, 10.0);
addInputDouble(tr("Scaling"), &_definition->scaling, 0.1, 3.0, 0.03, 0.3);
addInputDouble(tr("Height modifier"), &_definition->height, 0.0, 3.0, 0.01, 0.1);
addInputDouble(tr("Shadow smoothing"), &_definition->shadow_smoothing, 0.0, 0.3, 0.003, 0.03);
revertConfig();

View file

@ -40,7 +40,7 @@ protected:
Vector3 location;
double coverage;
location.x = x;
location.y = _renderer.terrain->getHeight(&_renderer, x, y);
location.y = _renderer.terrain->getHeight(&_renderer, x, y, 1);
location.z = y;
coverage = texturesGetLayerCoverage(_preview_layer, &_renderer, location, this->scaling);
return QColor::fromRgbF(coverage, coverage, coverage, 1.0);

View file

@ -35,7 +35,7 @@ protected:
{
double height;
height = _renderer.terrain->getHeight(&_renderer, x, -y);
height = _renderer.terrain->getHeight(&_renderer, x, -y, 1);
if (height > _definition.height)
{
return colorToQColor(terrainGetPreviewColor(&_renderer, x, -y, scaling));

View file

@ -151,10 +151,10 @@ void WidgetHeightMap::timerEvent(QTimerEvent*)
double brush_strength;
TerrainBrush brush;
brush.relative_x = (_brush_x + 40.0) / 80.0;
brush.relative_z = (_brush_z + 40.0) / 80.0;
brush.hard_radius = _brush_size * (1.0 - _brush_smoothing) / 80.0;
brush.smoothed_size = _brush_size * _brush_smoothing / 80.0;
brush.relative_x = _brush_x;
brush.relative_z = _brush_z;
brush.hard_radius = _brush_size * (1.0 - _brush_smoothing);
brush.smoothed_size = _brush_size * _brush_smoothing;
brush.total_radius = brush.hard_radius + brush.smoothed_size;
brush_strength = _brush_strength * duration / 0.1;
@ -363,10 +363,10 @@ void WidgetHeightMap::updateVertexInfo()
{
_VertexInfo* vertex = _vertices + z * rx + x;
vertex->point.x = 80.0 * (double)x / (double)(rx - 1) - 40.0;
vertex->point.z = 80.0 * (double)z / (double)(rz - 1) - 40.0;
vertex->point.x = (double)x;
vertex->point.z = (double)z;
vertex->point.y = _renderer.terrain->getHeight(&_renderer, vertex->point.x, vertex->point.z);
vertex->point.y = terrainGetGridHeight(_terrain, x, z, 1);
}
}

View file

@ -76,7 +76,7 @@ void cameraValidateDefinition(CameraDefinition* definition, int check_above)
waterDeleteDefinition(&water);
renderer = sceneryCreateStandardRenderer();
terrain_height = renderer.terrain->getHeight(&renderer, definition->location.x, definition->location.z) + 0.5;
terrain_height = renderer.terrain->getHeight(&renderer, definition->location.x, definition->location.z, 1) + 0.5;
rendererDelete(&renderer);
if (definition->location.y < water_height || definition->location.y < terrain_height)

View file

@ -84,25 +84,29 @@ StandardDefinition TerrainDefinitionClass = {
};
/******************** Binding ********************/
static double _fakeGetHeight(Renderer* renderer, double x, double z)
static double _fakeGetHeight(Renderer* renderer, double x, double z, int with_painting)
{
UNUSED(renderer);
UNUSED(x);
UNUSED(z);
UNUSED(with_painting);
return 0.0;
}
static double _getHeight(Renderer* renderer, double x, double z)
static double _getHeight(Renderer* renderer, double x, double z, int with_painting)
{
double height;
TerrainDefinition* definition = renderer->terrain->definition;
x /= definition->scaling;
z /= definition->scaling;
double height = noiseGet2DTotal(definition->_height_noise, x, z);
/* TODO Apply paintings */
if (!with_painting || !terrainHeightmapGetHeight(definition->height_map, x, z, &height))
{
height = noiseGet2DTotal(definition->_height_noise, x, z);
}
return height * definition->height;
return height * definition->height * definition->scaling;
}
static Color _fakeGetFinalColor(Renderer* renderer, Vector3 location, double precision)
@ -123,7 +127,7 @@ static Color _getFinalColor(Renderer* renderer, Vector3 location, double precisi
return color;
}
RayCastingResult _fakeCastRay(Renderer* renderer, Vector3 start, Vector3 direction)
static RayCastingResult _fakeCastRay(Renderer* renderer, Vector3 start, Vector3 direction)
{
UNUSED(renderer);
UNUSED(start);
@ -134,7 +138,7 @@ RayCastingResult _fakeCastRay(Renderer* renderer, Vector3 start, Vector3 directi
return result;
}
RayCastingResult _castRay(Renderer* renderer, Vector3 start, Vector3 direction)
static RayCastingResult _castRay(Renderer* renderer, Vector3 start, Vector3 direction)
{
RayCastingResult result;
TerrainDefinition* definition = renderer->terrain->definition;
@ -145,7 +149,7 @@ RayCastingResult _castRay(Renderer* renderer, Vector3 start, Vector3 direction)
inc_factor = (double)renderer->render_quality;
inc_base = 1.0;
inc_value = inc_base / inc_factor;
lastdiff = start.y - _getHeight(renderer, start.x, start.z);
lastdiff = start.y - _getHeight(renderer, start.x, start.z, 1);
length = 0.0;
do
@ -153,14 +157,14 @@ RayCastingResult _castRay(Renderer* renderer, Vector3 start, Vector3 direction)
inc_vector = v3Scale(direction, inc_value);
length += v3Norm(inc_vector);
start = v3Add(start, inc_vector);
height = _getHeight(renderer, start.x, start.z);
height = _getHeight(renderer, start.x, start.z, 1);
diff = start.y - height;
if (diff < 0.0)
{
if (fabs(diff - lastdiff) > 0.00001)
{
start = v3Add(start, v3Scale(inc_vector, -diff / (diff - lastdiff)));
start.y = _getHeight(renderer, start.x, start.z);
start.y = _getHeight(renderer, start.x, start.z, 1);
}
else
{
@ -236,7 +240,7 @@ static LightDefinition _alterLight(Renderer* renderer, LightDefinition* light, V
inc_vector = v3Scale(direction_to_light, inc_value);
length += v3Norm(inc_vector);
location = v3Add(location, inc_vector);
height = _getHeight(renderer, location.x, location.z);
height = _getHeight(renderer, location.x, location.z, 1);
diff = location.y - height;
if (diff < 0.0)
{
@ -279,6 +283,19 @@ static LightDefinition _alterLight(Renderer* renderer, LightDefinition* light, V
}
}
/******************** Public tools ********************/
double terrainGetGridHeight(TerrainDefinition* definition, int x, int z, int with_painting)
{
double height;
if (!with_painting || !terrainHeightmapGetHeight(definition->height_map, (double)x, (double)z, &height))
{
height = noiseGet2DTotal(definition->_height_noise, (double)x, (double)z);
}
return height;
}
/******************** Renderer ********************/
static TerrainRenderer* _createRenderer()
{

View file

@ -71,13 +71,13 @@ void terrainHeightmapCopy(TerrainHeightMap* source, TerrainHeightMap* destinatio
{
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].zstart = source->fixed_data[i].zstart;
destination->fixed_data[i].zsize = source->fixed_data[i].zsize;
if (destination->fixed_data[i].xsize * destination->fixed_data[i].zsize > 0)
{
destination->fixed_data[i].data = realloc(destination->fixed_data[i].data, sizeof(double) * destination->fixed_data[i].xsize * destination->fixed_data[i].ysize);
destination->fixed_data[i].data = realloc(destination->fixed_data[i].data, sizeof(double) * destination->fixed_data[i].xsize * destination->fixed_data[i].zsize);
}
memcpy(destination->fixed_data[i].data, source->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].zsize);
}
destination->floating_used = 0;
@ -92,9 +92,9 @@ void terrainHeightmapSave(PackStream* stream, TerrainHeightMap* heightmap)
{
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++)
packWriteInt(stream, &heightmap->fixed_data[i].zstart);
packWriteInt(stream, &heightmap->fixed_data[i].zsize);
for (j = 0; j < heightmap->fixed_data[i].xsize * heightmap->fixed_data[i].zsize; j++)
{
packWriteDouble(stream, &heightmap->fixed_data[i].data[j]);
}
@ -112,13 +112,13 @@ void terrainHeightmapLoad(PackStream* stream, TerrainHeightMap* heightmap)
{
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)
packReadInt(stream, &heightmap->fixed_data[i].zstart);
packReadInt(stream, &heightmap->fixed_data[i].zsize);
if (heightmap->fixed_data[i].xsize * heightmap->fixed_data[i].zsize > 0)
{
heightmap->fixed_data[i].data = realloc(heightmap->fixed_data[i].data, sizeof(double) * heightmap->fixed_data[i].xsize * heightmap->fixed_data[i].ysize);
heightmap->fixed_data[i].data = realloc(heightmap->fixed_data[i].data, sizeof(double) * heightmap->fixed_data[i].xsize * heightmap->fixed_data[i].zsize);
}
for (j = 0; j < heightmap->fixed_data[i].xsize * heightmap->fixed_data[i].ysize; j++)
for (j = 0; j < heightmap->fixed_data[i].xsize * heightmap->fixed_data[i].zsize; j++)
{
packReadDouble(stream, &heightmap->fixed_data[i].data[j]);
}
@ -127,32 +127,90 @@ void terrainHeightmapLoad(PackStream* stream, TerrainHeightMap* heightmap)
heightmap->floating_used = 0;
}
static inline int _checkDataHit(TerrainHeightMapData* data, double x, double z, double* result)
{
if (x > (double)data->xstart && x < (double)(data->xstart + data->xsize) && z > (double)data->zstart && z < (double)(data->zstart + data->zsize))
{
/* TODO Get interpolated value */
*result = 0.0;
return 1;
}
else
{
return 0;
}
}
int terrainHeightmapGetHeight(TerrainHeightMap* heightmap, double x, double z, double* result)
{
int i;
for (i = 0; i < heightmap->fixed_count; i++)
{
if (_checkDataHit(heightmap->fixed_data + i, x, z, result))
{
return 1;
}
}
if (heightmap->floating_used && _checkDataHit(&heightmap->floating_data, x, z, result))
{
return 1;
}
else
{
return 0;
}
}
static void _prepareBrushStroke(TerrainHeightMap* heightmap, TerrainBrush* brush)
{
double cx = brush->relative_x / TERRAIN_HEIGHTMAP_DETAIL;
double cz = brush->relative_z / TERRAIN_HEIGHTMAP_DETAIL;
double cx = brush->relative_x;
double cz = brush->relative_z;
double s = brush->smoothed_size + brush->hard_radius;
double sx = s / TERRAIN_HEIGHTMAP_DETAIL;
double sz = s / TERRAIN_HEIGHTMAP_DETAIL;
double sx = s;
double sz = s;
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 */
/* Prepare floating data */
if (heightmap->floating_used)
{
/* Grow floating area */
/* TODO */
}
else
{
/* Init flaoting area */
heightmap->floating_used = 1;
heightmap->floating_data.xstart = x1;
heightmap->floating_data.xsize = x2 - x1 + 1;
heightmap->floating_data.zstart = z1;
heightmap->floating_data.zsize = z2 - z1 + 1;
size_t new_size;
new_size = sizeof(double) * heightmap->floating_data.xsize * heightmap->floating_data.zsize;
heightmap->floating_data.data = realloc(heightmap->floating_data.data, new_size);
memset(heightmap->floating_data.data, 0, new_size);
}
}
void terrainBrushElevation(TerrainHeightMap* heightmap, TerrainBrush* brush, double value)
{
_prepareBrushStroke(heightmap, brush);
}
void terrainBrushSmooth(TerrainHeightMap* heightmap, TerrainBrush* brush, double value)
{
_prepareBrushStroke(heightmap, brush);
}
void terrainBrushAddNoise(TerrainHeightMap* heightmap, TerrainBrush* brush, NoiseGenerator* generator, double value)
{
_prepareBrushStroke(heightmap, brush);
}
void terrainBrushReset(TerrainHeightMap* heightmap, TerrainBrush* brush, double value)

View file

@ -7,14 +7,15 @@
void terrainAutoPreset(TerrainDefinition* definition, TerrainPreset preset)
{
int resolution = 8;
switch (preset)
{
case TERRAIN_PRESET_STANDARD:
noiseClearLevels(definition->_height_noise);
noiseAddLevelsSimple(definition->_height_noise, 8, 12.8, 12.8); /* Detail = 0.1 */
noiseAddLevelsSimple(definition->_height_noise, resolution, pow(2.0, resolution - 1), 25.0);
noiseSetFunctionParams(definition->_height_noise, NOISE_FUNCTION_SIMPLEX, 0.0);
definition->height = 2.0;
definition->scaling = 10.0;
definition->scaling = 1.0;
definition->height = 1.0;
definition->shadow_smoothing = 0.03;
break;
default:

View file

@ -88,7 +88,7 @@ Color terrainGetPreviewColor(Renderer* renderer, double x, double z, double deta
Vector3 point;
point.x = x;
point.y = renderer->terrain->getHeight(renderer, x, z);
point.y = renderer->terrain->getHeight(renderer, x, z, 1);
point.z = z;
return renderer->terrain->getFinalColor(renderer, point, detail);

View file

@ -3,14 +3,12 @@
#include "public.h"
#define TERRAIN_HEIGHTMAP_DETAIL 0.1
typedef struct
{
int xstart;
int ystart;
int zstart;
int xsize;
int ysize;
int zsize;
double* data;
} TerrainHeightMapData;
@ -27,5 +25,6 @@ void terrainHeightmapDelete(TerrainHeightMap* heightmap);
void terrainHeightmapCopy(TerrainHeightMap* source, TerrainHeightMap* destination);
void terrainHeightmapSave(PackStream* stream, TerrainHeightMap* heightmap);
void terrainHeightmapLoad(PackStream* stream, TerrainHeightMap* heightmap);
int terrainHeightmapGetHeight(TerrainHeightMap* heightmap, double x, double z, double* result);
#endif

View file

@ -30,7 +30,7 @@ typedef struct
double _max_height;
} TerrainDefinition;
typedef double (*FuncTerrainGetHeight)(Renderer* renderer, double x, double z);
typedef double (*FuncTerrainGetHeight)(Renderer* renderer, double x, double z, int with_painting);
typedef Color (*FuncTerrainGetFinalColor)(Renderer* renderer, Vector3 location, double precision);
typedef struct
@ -50,6 +50,7 @@ extern StandardRenderer TerrainRendererClass;
void terrainAutoPreset(TerrainDefinition* definition, TerrainPreset preset);
void terrainRenderSurface(Renderer* renderer);
double terrainGetGridHeight(TerrainDefinition* definition, int x, int z, int with_painting);
Renderer terrainCreatePreviewRenderer();
Color terrainGetPreviewColor(Renderer* renderer, double x, double z, double detail);

View file

@ -13,7 +13,7 @@ static inline Vector3 _getPoint(TerrainDefinition* definition, Renderer* rendere
Vector3 result;
result.x = x;
result.y = renderer->terrain->getHeight(renderer, x, z);
result.y = renderer->terrain->getHeight(renderer, x, z, 1);
result.z = z;
return result;

View file

@ -178,25 +178,25 @@ static inline TextureResult _getTerrainResult(Renderer* renderer, double x, doub
center.x = x;
center.z = z;
center.y = renderer->terrain->getHeight(renderer, center.x, center.z);
center.y = renderer->terrain->getHeight(renderer, center.x, center.z, 1);
east.x = x + detail;
east.z = z;
east.y = renderer->terrain->getHeight(renderer, east.x, east.z);
east.y = renderer->terrain->getHeight(renderer, east.x, east.z, 1);
south.x = x;
south.z = z + detail;
south.y = renderer->terrain->getHeight(renderer, south.x, south.z);
south.y = renderer->terrain->getHeight(renderer, south.x, south.z, 1);
if (renderer->render_quality > 5)
{
west.x = x - detail;
west.z = z;
west.y = renderer->terrain->getHeight(renderer, west.x, west.z);
west.y = renderer->terrain->getHeight(renderer, west.x, west.z, 1);
north.x = x;
north.z = z - detail;
north.y = renderer->terrain->getHeight(renderer, north.x, north.z);
north.y = renderer->terrain->getHeight(renderer, north.x, north.z, 1);
result.normal = _getNormal4(center, north, east, south, west);
}