From 7f0a13c02b5ec297fbf851bb046fd943ce1e9613 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Fri, 27 Sep 2013 23:28:06 +0200 Subject: [PATCH] Zone height ranges can now be relative to terrain and water height --- src/rendering/scenery.c | 7 +- src/rendering/scenery.h | 1 + src/rendering/terrain/public.h | 2 + src/rendering/terrain/ter_definition.c | 12 +++ src/rendering/textures/public.h | 1 + src/rendering/textures/tex_definition.c | 6 ++ src/rendering/textures/tex_presets.c | 34 ++++++-- src/rendering/tools/zone.c | 107 ++++++++++++++++-------- src/rendering/tools/zone.h | 3 + src/testing/main.c | 2 + src/testing/test_zone.c | 57 +++++++++++++ src/testing/testing.pro | 3 +- 12 files changed, 191 insertions(+), 44 deletions(-) create mode 100644 src/testing/test_zone.c diff --git a/src/rendering/scenery.c b/src/rendering/scenery.c index 171a7b0..002d674 100644 --- a/src/rendering/scenery.c +++ b/src/rendering/scenery.c @@ -57,7 +57,7 @@ void sceneryAutoPreset(int seed) srand(seed); terrainAutoPreset(_terrain, TERRAIN_PRESET_STANDARD); - texturesAutoPreset(_textures, TEXTURES_PRESET_IRELAND); + texturesAutoPreset(_textures, TEXTURES_PRESET_FULL); atmosphereAutoPreset(_atmosphere, ATMOSPHERE_PRESET_CLEAR_DAY); waterAutoPreset(_water, WATER_PRESET_LAKE); cloudsAutoPreset(_clouds, CLOUDS_PRESET_PARTLY_CLOUDY); @@ -151,6 +151,11 @@ void sceneryGetTerrain(TerrainDefinition* terrain) TerrainDefinitionClass.copy(_terrain, terrain); } +TerrainDefinition* sceneryGetTerrainDirect() +{ + return _terrain; +} + void scenerySetTextures(TexturesDefinition* textures) { TexturesDefinitionClass.copy(textures, _textures); diff --git a/src/rendering/scenery.h b/src/rendering/scenery.h index 0783ab1..ad0a60b 100644 --- a/src/rendering/scenery.h +++ b/src/rendering/scenery.h @@ -44,6 +44,7 @@ void sceneryGetClouds(CloudsDefinition* clouds); void scenerySetTerrain(TerrainDefinition* terrain); void sceneryGetTerrain(TerrainDefinition* terrain); +TerrainDefinition* sceneryGetTerrainDirect(); void scenerySetTextures(TexturesDefinition* textures); void sceneryGetTextures(TexturesDefinition* textures); diff --git a/src/rendering/terrain/public.h b/src/rendering/terrain/public.h index ff9fc08..671d3f5 100644 --- a/src/rendering/terrain/public.h +++ b/src/rendering/terrain/public.h @@ -69,6 +69,8 @@ size_t terrainGetMemoryStats(TerrainDefinition* definition); Renderer* terrainCreatePreviewRenderer(); Color terrainGetPreviewColor(Renderer* renderer, double x, double z, double detail); +HeightInfo terrainGetHeightInfo(TerrainDefinition* definition); + typedef struct { double relative_x; diff --git a/src/rendering/terrain/ter_definition.c b/src/rendering/terrain/ter_definition.c index d61ef46..883bbd3 100644 --- a/src/rendering/terrain/ter_definition.c +++ b/src/rendering/terrain/ter_definition.c @@ -128,3 +128,15 @@ double terrainGetInterpolatedHeight(TerrainDefinition* definition, double x, dou return height; } } + +HeightInfo terrainGetHeightInfo(TerrainDefinition* definition) +{ + HeightInfo result; + + result.min_height = definition->_min_height; + result.max_height = definition->_max_height; + /* TODO This is duplicated in ter_render.c (_realGetWaterHeight) */ + result.base_height = definition->water_height * definition->height * definition->scaling; + + return result; +} diff --git a/src/rendering/textures/public.h b/src/rendering/textures/public.h index f4e08bc..a237399 100644 --- a/src/rendering/textures/public.h +++ b/src/rendering/textures/public.h @@ -14,6 +14,7 @@ extern "C" { typedef enum { + TEXTURES_PRESET_FULL, TEXTURES_PRESET_IRELAND, TEXTURES_PRESET_ALPS, TEXTURES_PRESET_CANYON diff --git a/src/rendering/textures/tex_definition.c b/src/rendering/textures/tex_definition.c index 49da2b4..945c8ea 100644 --- a/src/rendering/textures/tex_definition.c +++ b/src/rendering/textures/tex_definition.c @@ -1,4 +1,5 @@ #include "private.h" +#include "scenery.h" #include @@ -67,6 +68,11 @@ static void _layerValidateDefinition(TexturesLayerDefinition* definition) noiseValidate(definition->_detail_noise); materialValidate(&definition->material); + + /* Update zone height range */ + TerrainDefinition* terrain = sceneryGetTerrainDirect(); + HeightInfo height_info = terrainGetHeightInfo(terrain); + zoneSetRelativeHeight(definition->terrain_zone, height_info.min_height, height_info.base_height, height_info.max_height); } static TexturesLayerDefinition* _layerCreateDefinition() diff --git a/src/rendering/textures/tex_presets.c b/src/rendering/textures/tex_presets.c index 5bf607b..187115e 100644 --- a/src/rendering/textures/tex_presets.c +++ b/src/rendering/textures/tex_presets.c @@ -5,7 +5,25 @@ void texturesAutoPreset(TexturesDefinition* definition, TexturesPreset preset) TexturesLayerDefinition* layer; layersClear(definition->layers); - if (preset == TEXTURES_PRESET_IRELAND) + if (preset == TEXTURES_PRESET_FULL) + { + layer = layersGetLayer(definition->layers, layersAddLayer(definition->layers, NULL)); + texturesLayerAutoPreset(layer, TEXTURES_LAYER_PRESET_ROCK); + layersSetName(definition->layers, 0, "Ground"); + + layer = layersGetLayer(definition->layers, layersAddLayer(definition->layers, NULL)); + texturesLayerAutoPreset(layer, TEXTURES_LAYER_PRESET_GRASS); + layersSetName(definition->layers, 1, "Grass"); + + layer = layersGetLayer(definition->layers, layersAddLayer(definition->layers, NULL)); + texturesLayerAutoPreset(layer, TEXTURES_LAYER_PRESET_SAND); + layersSetName(definition->layers, 2, "Sand"); + + layer = layersGetLayer(definition->layers, layersAddLayer(definition->layers, NULL)); + texturesLayerAutoPreset(layer, TEXTURES_LAYER_PRESET_SNOW); + layersSetName(definition->layers, 3, "Snow"); + } + else if (preset == TEXTURES_PRESET_IRELAND) { layer = layersGetLayer(definition->layers, layersAddLayer(definition->layers, NULL)); texturesLayerAutoPreset(layer, TEXTURES_LAYER_PRESET_ROCK); @@ -16,7 +34,7 @@ void texturesAutoPreset(TexturesDefinition* definition, TexturesPreset preset) layersSetName(definition->layers, 1, "Grass"); } else if (preset == TEXTURES_PRESET_ALPS) -{ + { layer = layersGetLayer(definition->layers, layersAddLayer(definition->layers, NULL)); texturesLayerAutoPreset(layer, TEXTURES_LAYER_PRESET_ROCK); layersSetName(definition->layers, 0, "Ground"); @@ -49,7 +67,7 @@ void texturesLayerAutoPreset(TexturesLayerDefinition* definition, TexturesLayerP definition->material.shininess = 6.0; break; case TEXTURES_LAYER_PRESET_GRASS: - zoneAddHeightRangeQuick(definition->terrain_zone, 1.0, -6.0, -5.0, 3.0, 15.0); + zoneAddHeightRangeQuick(definition->terrain_zone, 1.0, 0.45, 0.5, 0.8, 1.0); zoneAddSlopeRangeQuick(definition->terrain_zone, 1.0, 0.0, 0.0, 0.05, 0.4); definition->displacement_height = 0.0; definition->displacement_scaling = 1.0; @@ -59,17 +77,17 @@ void texturesLayerAutoPreset(TexturesLayerDefinition* definition, TexturesLayerP definition->material.shininess = 4.0; break; case TEXTURES_LAYER_PRESET_SAND: - zoneAddHeightRangeQuick(definition->terrain_zone, 1.0, -5.5, -4.5, -4.0, -3.0); - zoneAddSlopeRangeQuick(definition->terrain_zone, 1.0, 0.0, 0.0, 0.15, 0.3); + zoneAddHeightRangeQuick(definition->terrain_zone, 1.0, 0.48, 0.49, 0.505, 0.51); + zoneAddSlopeRangeQuick(definition->terrain_zone, 1.0, 0.0, 0.0, 0.1, 0.3); definition->displacement_height = 0.0; definition->displacement_scaling = 1.0; definition->displacement_offset = 0.0; - definition->material.base = colorToHSL(colorFromValues(0.30, 0.28, 0.02, 1.0)); + definition->material.base = colorToHSL(colorFromValues(0.93, 0.9, 0.8, 1.0)); definition->material.reflection = 0.008; - definition->material.shininess = 6.0; + definition->material.shininess = 1.0; break; case TEXTURES_LAYER_PRESET_SNOW: - zoneAddHeightRangeQuick(definition->terrain_zone, 1.0, 4.0, 5.0, 100.0, 100.0); + zoneAddHeightRangeQuick(definition->terrain_zone, 1.0, 0.77, 0.85, 1.0, 1.0); zoneAddSlopeRangeQuick(definition->terrain_zone, 1.0, 0.0, 0.0, 0.2, 1.0); definition->displacement_height = 0.0; definition->displacement_scaling = 1.0; diff --git a/src/rendering/tools/zone.c b/src/rendering/tools/zone.c index 12af97f..7e12c09 100644 --- a/src/rendering/tools/zone.c +++ b/src/rendering/tools/zone.c @@ -17,14 +17,16 @@ typedef struct } Circle; struct Zone { + int absolute_height; + double relative_height_min; + double relative_height_middle; + double relative_height_max; + Curve* value_by_height; Curve* value_by_slope; Circle circles_included[MAX_CIRCLES]; int circles_included_count; - - Circle circles_excluded[MAX_CIRCLES]; - int circles_excluded_count; }; Zone* zoneCreate() @@ -33,11 +35,11 @@ Zone* zoneCreate() result = (Zone*)malloc(sizeof(Zone)); result->value_by_height = curveCreate(); + result->absolute_height = 1; curveSetDefault(result->value_by_height, 1.0); result->value_by_slope = curveCreate(); curveSetDefault(result->value_by_slope, 1.0); result->circles_included_count = 0; - result->circles_excluded_count = 0; return result; } @@ -53,6 +55,11 @@ void zoneSave(PackStream* stream, Zone* zone) { int i; + packWriteInt(stream, &zone->absolute_height); + packWriteDouble(stream, &zone->relative_height_min); + packWriteDouble(stream, &zone->relative_height_middle); + packWriteDouble(stream, &zone->relative_height_max); + curveSave(stream, zone->value_by_height); curveSave(stream, zone->value_by_slope); @@ -65,22 +72,17 @@ void zoneSave(PackStream* stream, Zone* zone) packWriteDouble(stream, &zone->circles_included[i].softradius); packWriteDouble(stream, &zone->circles_included[i].hardradius); } - - packWriteInt(stream, &zone->circles_excluded_count); - for (i = 0; i < zone->circles_excluded_count; i++) - { - packWriteDouble(stream, &zone->circles_excluded[i].value); - packWriteDouble(stream, &zone->circles_excluded[i].centerx); - packWriteDouble(stream, &zone->circles_excluded[i].centerz); - packWriteDouble(stream, &zone->circles_excluded[i].softradius); - packWriteDouble(stream, &zone->circles_excluded[i].hardradius); - } } void zoneLoad(PackStream* stream, Zone* zone) { int i; + packReadInt(stream, &zone->absolute_height); + packReadDouble(stream, &zone->relative_height_min); + packReadDouble(stream, &zone->relative_height_middle); + packReadDouble(stream, &zone->relative_height_max); + curveLoad(stream, zone->value_by_height); curveLoad(stream, zone->value_by_slope); @@ -93,28 +95,20 @@ void zoneLoad(PackStream* stream, Zone* zone) packReadDouble(stream, &zone->circles_included[i].softradius); packReadDouble(stream, &zone->circles_included[i].hardradius); } - - packReadInt(stream, &zone->circles_excluded_count); - for (i = 0; i < zone->circles_excluded_count; i++) - { - packReadDouble(stream, &zone->circles_excluded[i].value); - packReadDouble(stream, &zone->circles_excluded[i].centerx); - packReadDouble(stream, &zone->circles_excluded[i].centerz); - packReadDouble(stream, &zone->circles_excluded[i].softradius); - packReadDouble(stream, &zone->circles_excluded[i].hardradius); - } } void zoneCopy(Zone* source, Zone* destination) { + destination->absolute_height = source->absolute_height; + destination->relative_height_min = source->relative_height_min; + destination->relative_height_middle = source->relative_height_middle; + destination->relative_height_max = source->relative_height_max; + curveCopy(source->value_by_height, destination->value_by_height); curveCopy(source->value_by_slope, destination->value_by_slope); memcpy(destination->circles_included, source->circles_included, sizeof(Circle) * source->circles_included_count); destination->circles_included_count = source->circles_included_count; - - memcpy(destination->circles_excluded, source->circles_excluded, sizeof(Circle) * source->circles_excluded_count); - destination->circles_excluded_count = source->circles_excluded_count; } void zoneClear(Zone* zone) @@ -122,7 +116,32 @@ void zoneClear(Zone* zone) curveClear(zone->value_by_height); curveClear(zone->value_by_slope); zone->circles_included_count = 0; - zone->circles_excluded_count = 0; +} + +void zoneSetAbsoluteHeight(Zone* zone) +{ + zone->absolute_height = 1; +} + +void zoneSetRelativeHeight(Zone* zone, double min, double middle, double max) +{ + if (max < min) + { + max = min; + } + if (middle < min) + { + middle = min; + } + if (middle > max) + { + middle = max; + } + + zone->absolute_height = 0; + zone->relative_height_min = min; + zone->relative_height_middle = middle; + zone->relative_height_max = max; } void zoneIncludeCircleArea(Zone* zone, double value, double centerx, double centerz, double softradius, double hardradius) @@ -135,11 +154,6 @@ void zoneIncludeCircleArea(Zone* zone, double value, double centerx, double cent } } -void zoneExcludeCircleArea(Zone* zone, double centerx, double centerz, double softradius, double hardradius) -{ - /* TODO */ -} - void zoneGetHeightCurve(Zone* zone, Curve* curve) { curveCopy(zone->value_by_height, curve); @@ -201,6 +215,7 @@ static inline double _getCircleInfluence(Circle circle, Vector3 position) double zoneGetValue(Zone* zone, Vector3 location, Vector3 normal) { int i; + double final_height; double value, value_height, value_steepness, value_circle; if (zone->circles_included_count > 0) @@ -220,7 +235,31 @@ double zoneGetValue(Zone* zone, Vector3 location, Vector3 normal) value_circle = 1.0; } - value_height = curveGetValue(zone->value_by_height, location.y); + if (zone->absolute_height) + { + final_height = location.y; + } + else + { + if (location.y >= zone->relative_height_max) + { + final_height = 1.0; + } + else if (location.y <= zone->relative_height_min) + { + final_height = 0.0; + } + else if (location.y <= zone->relative_height_middle) + { + final_height = 0.5 * (location.y - zone->relative_height_min) / (zone->relative_height_middle - zone->relative_height_min); + } + else + { + final_height = 0.5 + 0.5 * (location.y - zone->relative_height_middle) / (zone->relative_height_max - zone->relative_height_middle); + } + } + + value_height = curveGetValue(zone->value_by_height, final_height); value_steepness = curveGetValue(zone->value_by_slope, (1.0 - normal.y)); if (value_steepness < value_height) diff --git a/src/rendering/tools/zone.h b/src/rendering/tools/zone.h index 1715ad4..44e74d8 100644 --- a/src/rendering/tools/zone.h +++ b/src/rendering/tools/zone.h @@ -22,6 +22,9 @@ void zoneLoad(PackStream* stream, Zone* zone); void zoneCopy(Zone* source, Zone* destination); void zoneClear(Zone* zone); +void zoneSetAbsoluteHeight(Zone* zone); +void zoneSetRelativeHeight(Zone* zone, double min, double middle, double max); + void zoneIncludeCircleArea(Zone* zone, double value, double centerx, double centerz, double softradius, double hardradius); void zoneExcludeCircleArea(Zone* zone, double centerx, double centerz, double softradius, double hardradius); diff --git a/src/testing/main.c b/src/testing/main.c index 4485451..5c064de 100644 --- a/src/testing/main.c +++ b/src/testing/main.c @@ -13,6 +13,7 @@ extern void test_noise_case(Suite* s); extern void test_terrain_painting_case(Suite* s); extern void test_bruneton_case(Suite* s); extern void test_pack_case(Suite* s); +extern void test_zone_case(Suite* s); int main(int argc, char** argv) { @@ -32,6 +33,7 @@ int main(int argc, char** argv) test_terrain_painting_case(s); test_bruneton_case(s); test_pack_case(s); + test_zone_case(s); SRunner *sr = srunner_create(s); srunner_run_all(sr, CK_NORMAL); diff --git a/src/testing/test_zone.c b/src/testing/test_zone.c new file mode 100644 index 0000000..28c19e4 --- /dev/null +++ b/src/testing/test_zone.c @@ -0,0 +1,57 @@ +#include "testing/common.h" + +#include "rendering/tools/zone.h" + +START_TEST(testZoneAbsoluteHeight) +{ + Zone* zone = zoneCreate(); + + zoneAddHeightRangeQuick(zone, 1.0, -1.0, 2.0, 5.0, 6.0); + + ck_assert_double_eq(zoneGetValue(zone, v3(0.0, -10.0, 0.0), VECTOR_UP), 0.0); + ck_assert_double_eq(zoneGetValue(zone, v3(0.0, -2.0, 0.0), VECTOR_UP), 0.0); + ck_assert_double_eq(zoneGetValue(zone, v3(0.0, -1.0, 0.0), VECTOR_UP), 0.0); + ck_assert_double_eq(zoneGetValue(zone, v3(0.0, -0.5, 0.0), VECTOR_UP), 1.0 / 6.0); + ck_assert_double_eq(zoneGetValue(zone, v3(0.0, 0.0, 0.0), VECTOR_UP), 1.0 / 3.0); + ck_assert_double_eq(zoneGetValue(zone, v3(0.0, 0.5, 0.0), VECTOR_UP), 0.5); + ck_assert_double_eq(zoneGetValue(zone, v3(0.0, 2.0, 0.0), VECTOR_UP), 1.0); + ck_assert_double_eq(zoneGetValue(zone, v3(0.0, 2.1, 0.0), VECTOR_UP), 1.0); + ck_assert_double_eq(zoneGetValue(zone, v3(0.0, 3.5, 0.0), VECTOR_UP), 1.0); + ck_assert_double_eq(zoneGetValue(zone, v3(0.0, 4.9, 0.0), VECTOR_UP), 1.0); + ck_assert_double_eq(zoneGetValue(zone, v3(0.0, 5.0, 0.0), VECTOR_UP), 1.0); + ck_assert_double_eq(zoneGetValue(zone, v3(0.0, 5.2, 0.0), VECTOR_UP), 0.8); + ck_assert_double_eq(zoneGetValue(zone, v3(0.0, 5.7, 0.0), VECTOR_UP), 0.3); + ck_assert_double_eq(zoneGetValue(zone, v3(0.0, 6.0, 0.0), VECTOR_UP), 0.0); + ck_assert_double_eq(zoneGetValue(zone, v3(0.0, 15.0, 0.0), VECTOR_UP), 0.0); + ck_assert_double_eq(zoneGetValue(zone, v3(0.0, 150.0, 0.0), VECTOR_UP), 0.0); + + zoneDelete(zone); +} +END_TEST + +START_TEST(testZoneRelativeHeight) +{ + Zone* zone = zoneCreate(); + + zoneAddHeightRangeQuick(zone, 1.0, 0.2, 0.3, 0.6, 0.9); + zoneSetRelativeHeight(zone, -2.0, 2.0, 8.0); + + ck_assert_double_eq(zoneGetValue(zone, v3(0.0, -10.0, 0.0), VECTOR_UP), 0.0); + ck_assert_double_eq(zoneGetValue(zone, v3(0.0, -2.1, 0.0), VECTOR_UP), 0.0); + ck_assert_double_eq(zoneGetValue(zone, v3(0.0, -2.0, 0.0), VECTOR_UP), 0.0); + ck_assert_double_eq(zoneGetValue(zone, v3(0.0, -1.0, 0.0), VECTOR_UP), 0.0); + ck_assert_double_eq(zoneGetValue(zone, v3(0.0, -0.5, 0.0), VECTOR_UP), 0.0); + ck_assert_double_eq(zoneGetValue(zone, v3(0.0, -0.2, 0.0), VECTOR_UP), 0.25); + ck_assert_double_eq(zoneGetValue(zone, v3(0.0, 0.0, 0.0), VECTOR_UP), 0.5); + ck_assert_double_eq(zoneGetValue(zone, v3(0.0, 0.3, 0.0), VECTOR_UP), 0.875); + ck_assert_double_eq(zoneGetValue(zone, v3(0.0, 0.5, 0.0), VECTOR_UP), 1.0); + ck_assert_double_eq(zoneGetValue(zone, v3(0.0, 1.0, 0.0), VECTOR_UP), 1.0); + + zoneDelete(zone); +} +END_TEST + +TEST_CASE(zone, + testZoneAbsoluteHeight, + testZoneRelativeHeight) + diff --git a/src/testing/testing.pro b/src/testing/testing.pro index 8b51998..c95e195 100644 --- a/src/testing/testing.pro +++ b/src/testing/testing.pro @@ -25,7 +25,8 @@ SOURCES += main.c \ test_euclid.c \ test_clouds.c \ test_camera.c \ - test_bruneton.c + test_bruneton.c \ + test_zone.c HEADERS += \ common.h