From 5e4b4e59a91de29b2900d0d319f63f569200c039 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Sat, 25 May 2013 15:20:11 +0200 Subject: [PATCH 01/19] Working on clouds walking --- src/rendering/clouds/clo_lighting.c | 2 ++ src/rendering/clouds/clo_lighting.h | 30 +++++++++++++++++++++++++ src/rendering/clouds/clo_walking.c | 8 +++++-- src/rendering/clouds/clo_walking.h | 34 +++++++++++++++++++++++++---- src/testing/test_clouds.c | 22 +++++++++---------- 5 files changed, 79 insertions(+), 17 deletions(-) create mode 100644 src/rendering/clouds/clo_lighting.c create mode 100644 src/rendering/clouds/clo_lighting.h diff --git a/src/rendering/clouds/clo_lighting.c b/src/rendering/clouds/clo_lighting.c new file mode 100644 index 0000000..3576b55 --- /dev/null +++ b/src/rendering/clouds/clo_lighting.c @@ -0,0 +1,2 @@ +#include "clo_lighting.h" + diff --git a/src/rendering/clouds/clo_lighting.h b/src/rendering/clouds/clo_lighting.h new file mode 100644 index 0000000..6c5cd1c --- /dev/null +++ b/src/rendering/clouds/clo_lighting.h @@ -0,0 +1,30 @@ +#ifndef _PAYSAGES_CLOUDS_LIGHTING_H_ +#define _PAYSAGES_CLOUDS_LIGHTING_H_ + +#include "public.h" +#include "../tools/euclid.h" + +/** + * Cloud lighting helpers. + */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* + * Bind fake lighting functions to a renderer. + */ +void cloudsBindFakeLightingToRenderer(CloudsRenderer* renderer); + +/* + * Bind real lighting functions to a renderer. + */ +void cloudsBindRealLightingToRenderer(CloudsRenderer* renderer); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/rendering/clouds/clo_walking.c b/src/rendering/clouds/clo_walking.c index 5efb929..e4987ee 100644 --- a/src/rendering/clouds/clo_walking.c +++ b/src/rendering/clouds/clo_walking.c @@ -136,8 +136,8 @@ int cloudsGetLayerPrimarySegments(Renderer* renderer, CloudsLayerDefinition* lay /* exiting the cloud */ segment_length += step_length; - out_segments->enter = segment_start; - out_segments->exit = walker; + out_segments->entry_point = segment_start; + out_segments->exit_point = walker; out_segments->length = segment_length; out_segments++; if (++segment_count >= max_segments) @@ -155,3 +155,7 @@ int cloudsGetLayerPrimarySegments(Renderer* renderer, CloudsLayerDefinition* lay return segment_count; } + +int cloudsGetLayerSecondarySampling(Renderer* renderer, CloudsLayerDefinition* layer, CloudPrimarySegment* segment, int max_control_points, CloudSecondaryControlPoint* out_control_points) +{ +} diff --git a/src/rendering/clouds/clo_walking.h b/src/rendering/clouds/clo_walking.h index 2ad19b3..489be79 100644 --- a/src/rendering/clouds/clo_walking.h +++ b/src/rendering/clouds/clo_walking.h @@ -5,7 +5,7 @@ #include "../tools/euclid.h" /** - * Functions to walk through a cloud layer. + * Functions to walk through a cloud layer (sampling). */ #ifdef __cplusplus @@ -15,11 +15,25 @@ extern "C" typedef struct { - Vector3 enter; - Vector3 exit; + Vector3 entry_point; + Vector3 exit_point; double length; } CloudPrimarySegment; +typedef struct +{ + /** Distance factor of the control point from the segment start */ + double distance; + /** Location of the control point */ + Vector3 location; + /** Global density at the control point (no edge noise applied) */ + double global_density; + /** Particle dentisy at the control point, using edge noise */ + double particle_density; + /** Estimated distance to nearest cloud exit */ + double nearest_exit_distance; +} CloudSecondaryControlPoint; + /** * Optimize the search limits in a layer. * @@ -38,11 +52,23 @@ int cloudsOptimizeWalkingBounds(CloudsLayerDefinition* layer, Vector3* start, Ve * @param start Start position of the lookup * @param end End position of the lookup * @param max_segments Maximum number of segments to collect - * @param out_segments Allocated space to fill found segments + * @param out_segments Allocated space to fill found segments (must be at least 'max_segments' long) * @return Number of segments found */ int cloudsGetLayerPrimarySegments(Renderer* renderer, CloudsLayerDefinition* layer, Vector3 start, Vector3 end, int max_segments, CloudPrimarySegment* out_segments); +/** + * Sample a primary segment with refined details, collecting material interaction. + * + * @param renderer The renderer environment + * @param layer The cloud layer + * @param segment The primary segment to sample + * @param max_control_points Maximum number of control points to sample + * @param out_control_points Allocated space to fill with secondary control points (must be at least 'max_control_points' long) + * @return Number of control points sampled + */ +int cloudsGetLayerSecondarySampling(Renderer* renderer, CloudsLayerDefinition* layer, CloudPrimarySegment* segment, int max_control_points, CloudSecondaryControlPoint* out_control_points); + #ifdef __cplusplus } #endif diff --git a/src/testing/test_clouds.c b/src/testing/test_clouds.c index 7ab715e..8636c7a 100644 --- a/src/testing/test_clouds.c +++ b/src/testing/test_clouds.c @@ -221,18 +221,18 @@ START_TEST(test_clouds_primary_segments) ck_assert_int_eq(segment_count, 2); for (i = 0; i < segment_count; i++) { - ck_assert_double_eq(segments[i].enter.y, 0.0); - ck_assert_double_eq(segments[i].enter.z, 0.0); - ck_assert_double_eq(segments[i].exit.y, 0.0); - ck_assert_double_eq(segments[i].exit.z, 0.0); + ck_assert_double_eq(segments[i].entry_point.y, 0.0); + ck_assert_double_eq(segments[i].entry_point.z, 0.0); + ck_assert_double_eq(segments[i].exit_point.y, 0.0); + ck_assert_double_eq(segments[i].exit_point.z, 0.0); } - ck_assert_double_in_range(segments[0].enter.x, -0.5, 0.0); - ck_assert_double_in_range(segments[0].exit.x, 0.5, 1.0); - ck_assert_double_in_range(segments[0].length, 0.5, 1.5); - ck_assert_double_gte(segments[1].enter.x, segments[0].exit.x); - ck_assert_double_in_range(segments[1].enter.x, 0.5, 1.0); - ck_assert_double_in_range(segments[1].exit.x, 1.5, 2.0); - ck_assert_double_in_range(segments[1].length, 0.5, 1.5); + ck_assert_double_in_range(segments[0].entry_point.x, -0.4, 0.0); + ck_assert_double_in_range(segments[0].exit_point.x, 0.5, 1.0); + ck_assert_double_in_range(segments[0].length, 0.5, 1.3); + ck_assert_double_gte(segments[1].entry_point.x, segments[0].exit_point.x); + ck_assert_double_in_range(segments[1].entry_point.x, 0.5, 1.0); + ck_assert_double_in_range(segments[1].exit_point.x, 1.5, 1.9); + ck_assert_double_in_range(segments[1].length, 0.5, 1.3); cloudsGetLayerType().callback_delete(layer); rendererDelete(renderer); From af3e0c2fe60f17d3713fe309421c33e873af8423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Sun, 26 May 2013 20:28:44 +0200 Subject: [PATCH 02/19] Draft for new cloud walking algorithm --- src/rendering/clouds/clo_tools.c | 20 ++---- src/rendering/clouds/clo_walking.c | 107 +---------------------------- src/rendering/clouds/clo_walking.h | 80 +++++++++++---------- src/testing/test_clouds.c | 18 ++--- 4 files changed, 58 insertions(+), 167 deletions(-) diff --git a/src/rendering/clouds/clo_tools.c b/src/rendering/clouds/clo_tools.c index 5337e54..bacf5b5 100644 --- a/src/rendering/clouds/clo_tools.c +++ b/src/rendering/clouds/clo_tools.c @@ -89,22 +89,16 @@ static Color _applyLayerLighting(CloudsLayerDefinition* definition, Renderer* re Color cloudsApplyLayer(CloudsLayerDefinition* definition, Color base, Renderer* renderer, Vector3 start, Vector3 end) { - int segment_count; - Color col; - CloudPrimarySegment segments[MAX_SEGMENT_COUNT]; + Color col = COLOR_TRANSPARENT; - segment_count = cloudsGetLayerPrimarySegments(renderer, definition, start, end, MAX_SEGMENT_COUNT, segments); - /* TODO Crawl in segments for render */ - - col = definition->material.base; - /*if (definition->transparencydepth == 0 || inside_length >= definition->transparencydepth) + if (!cloudsOptimizeWalkingBounds(definition, &start, &end)) { - col.a = 1.0; + return base; } - else - { - col.a = inside_length / definition->transparencydepth; - }*/ + + /* TODO Walk through the cloud */ + + /*segment_count = cloudsGetLayerPrimarySegments(renderer, definition, start, end, MAX_SEGMENT_COUNT, segments);*/ col = renderer->atmosphere->applyAerialPerspective(renderer, start, col).final; col.a = 0.0; diff --git a/src/rendering/clouds/clo_walking.c b/src/rendering/clouds/clo_walking.c index e4987ee..35a0029 100644 --- a/src/rendering/clouds/clo_walking.c +++ b/src/rendering/clouds/clo_walking.c @@ -2,6 +2,7 @@ #include "../renderer.h" + int cloudsOptimizeWalkingBounds(CloudsLayerDefinition* layer, Vector3* start, Vector3* end) { Vector3 diff; @@ -51,111 +52,5 @@ int cloudsOptimizeWalkingBounds(CloudsLayerDefinition* layer, Vector3* start, Ve } } - /* TODO Limit the search length */ return 1; } - -int cloudsGetLayerPrimarySegments(Renderer* renderer, CloudsLayerDefinition* layer, Vector3 start, Vector3 end, int max_segments, CloudPrimarySegment* out_segments) -{ - int inside, segment_count; - double step_length, segment_length; - Vector3 diff, walker, segment_start; - double render_precision, density; - double diff_length, progress; - - if (max_segments <= 0) - { - return 0; - } - - if (!cloudsOptimizeWalkingBounds(layer, &start, &end)) - { - return 0; - } - - diff = v3Sub(end, start); - diff_length = v3Norm(diff); - - if (diff_length < 0.000001) - { - return 0; - } - - render_precision = 1.005 - 0.01 * (double)(renderer->render_quality * renderer->render_quality); - /*if (render_precision > max_total_length / 10.0) - { - render_precision = max_total_length / 10.0; - } - else if (render_precision < max_total_length / 10000.0) - { - render_precision = max_total_length / 10000.0; - }*/ - - segment_count = 0; - segment_length = 0.0; - density = renderer->clouds->getLayerDensity(renderer, layer, start); - progress = 0.0; - step_length = render_precision; - inside = (density > 0.0); - - do - { - progress += step_length; - walker = v3Add(start, v3Scale(diff, progress / diff_length)); - - if (progress >= diff_length) - { - density = 0.0; - } - else - { - density = renderer->clouds->getLayerDensity(renderer, layer, walker); - } - - if (density > 0.0) - { - if (inside) - { - /* inside the cloud */ - segment_length += step_length; - } - else - { - /* entering the cloud */ - segment_length = step_length; - segment_start = v3Add(start, v3Scale(diff, (progress - step_length) / diff_length)); - /* TODO Refine entry position */ - - inside = 1; - } - } - else - { - if (inside) - { - /* exiting the cloud */ - segment_length += step_length; - - out_segments->entry_point = segment_start; - out_segments->exit_point = walker; - out_segments->length = segment_length; - out_segments++; - if (++segment_count >= max_segments) - { - break; - } - /* TODO Refine exit position */ - - inside = 0; - } - } - /* step = v3Scale(direction, (info.distance_to_edge < render_precision) ? render_precision : info.distance_to_edge); */ - } - while (inside || (walker.y <= layer->lower_altitude + layer->thickness + 0.001 && walker.y >= layer->lower_altitude - 0.001 && progress < diff_length)); - - return segment_count; -} - -int cloudsGetLayerSecondarySampling(Renderer* renderer, CloudsLayerDefinition* layer, CloudPrimarySegment* segment, int max_control_points, CloudSecondaryControlPoint* out_control_points) -{ -} diff --git a/src/rendering/clouds/clo_walking.h b/src/rendering/clouds/clo_walking.h index 489be79..7984c66 100644 --- a/src/rendering/clouds/clo_walking.h +++ b/src/rendering/clouds/clo_walking.h @@ -5,7 +5,7 @@ #include "../tools/euclid.h" /** - * Functions to walk through a cloud layer (sampling). + * Functions to walk through a cloud layer. */ #ifdef __cplusplus @@ -13,26 +13,47 @@ extern "C" { #endif +/** + * Information on a segment yielded by walking. + */ typedef struct { - Vector3 entry_point; - Vector3 exit_point; - double length; -} CloudPrimarySegment; + Renderer* renderer; + CloudsLayerDefinition* layer; + double walked_distance; + Vector3 start; + Vector3 end; + double length; + + int refined; + int subdivision_level; + double precision_asked; + + void* data; +} CloudWalkingInfo; + +/** + * Control of the next walking order. + */ +typedef enum +{ + CLOUD_WALKING_CONTINUE, + CLOUD_WALKING_STOP, + CLOUD_WALKING_REFINE, + CLOUD_WALKING_SUBDIVIDE +} CloudWalkingOrder; + +/** + * Additional info for walking orders. + */ typedef struct { - /** Distance factor of the control point from the segment start */ - double distance; - /** Location of the control point */ - Vector3 location; - /** Global density at the control point (no edge noise applied) */ - double global_density; - /** Particle dentisy at the control point, using edge noise */ - double particle_density; - /** Estimated distance to nearest cloud exit */ - double nearest_exit_distance; -} CloudSecondaryControlPoint; + double precision; + int max_segments; +} CloudWalkingOrderInfo; + +typedef CloudWalkingOrder(*FuncCloudSegmentCallback)(CloudWalkingInfo* segment, CloudWalkingOrderInfo* order); /** * Optimize the search limits in a layer. @@ -45,29 +66,18 @@ typedef struct int cloudsOptimizeWalkingBounds(CloudsLayerDefinition* layer, Vector3* start, Vector3* end); /** - * Go through the cloud layer to find segments (parts of the lookup that are likely to contain cloud). + * Start walking through a segment. * + * For better performance, the segment should by optimized using cloudsOptimizeWalkingBounds. + * The callback will be called with each segment found, giving info and asking for desired alteration on walking. * @param renderer The renderer environment * @param layer The cloud layer - * @param start Start position of the lookup - * @param end End position of the lookup - * @param max_segments Maximum number of segments to collect - * @param out_segments Allocated space to fill found segments (must be at least 'max_segments' long) - * @return Number of segments found + * @param start Start position of the lookup, already optimized + * @param end End position of the lookup, already optimized + * @param callback Callback to be called with each found segment + * @param data User data that will be passed back in the callback */ -int cloudsGetLayerPrimarySegments(Renderer* renderer, CloudsLayerDefinition* layer, Vector3 start, Vector3 end, int max_segments, CloudPrimarySegment* out_segments); - -/** - * Sample a primary segment with refined details, collecting material interaction. - * - * @param renderer The renderer environment - * @param layer The cloud layer - * @param segment The primary segment to sample - * @param max_control_points Maximum number of control points to sample - * @param out_control_points Allocated space to fill with secondary control points (must be at least 'max_control_points' long) - * @return Number of control points sampled - */ -int cloudsGetLayerSecondarySampling(Renderer* renderer, CloudsLayerDefinition* layer, CloudPrimarySegment* segment, int max_control_points, CloudSecondaryControlPoint* out_control_points); +void cloudsStartWalking(Renderer* renderer, CloudsLayerDefinition* layer, Vector3 start, Vector3 end, FuncCloudSegmentCallback callback, void* data); #ifdef __cplusplus } diff --git a/src/testing/test_clouds.c b/src/testing/test_clouds.c index 8636c7a..4bd6c57 100644 --- a/src/testing/test_clouds.c +++ b/src/testing/test_clouds.c @@ -200,7 +200,7 @@ static double _getLayerDensitySinX(Renderer* renderer, CloudsLayerDefinition* la return (density > 0.0) ? density : 0.0; } -START_TEST(test_clouds_primary_segments) +/*START_TEST(test_clouds_primary_segments) { int segment_count, i; CloudPrimarySegment segments[10]; @@ -237,16 +237,8 @@ START_TEST(test_clouds_primary_segments) cloudsGetLayerType().callback_delete(layer); rendererDelete(renderer); } -END_TEST +END_TEST*/ -START_TEST(test_clouds_preview_color) -{ - Renderer* renderer = cloudsCreatePreviewColorRenderer(); - - /* TODO Test the density overriding */ - - rendererDelete(renderer); -} -END_TEST - -TEST_CASE(clouds, test_clouds_density, test_clouds_walking_boundaries, test_clouds_primary_segments, test_clouds_preview_color) +TEST_CASE(clouds, + test_clouds_density, + test_clouds_walking_boundaries) From 6e8e1bc3074adec96f68f8821436387662bcc0c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Tue, 28 May 2013 22:43:51 +0200 Subject: [PATCH 03/19] WIP on clouds walking --- src/rendering/clouds/clo_rendering.c | 41 ++++++-- src/rendering/clouds/clo_tools.c | 143 --------------------------- src/rendering/clouds/clo_walking.c | 53 ++++++++++ src/rendering/clouds/clo_walking.h | 87 +++++++++++----- src/testing/test_clouds.c | 27 +---- 5 files changed, 153 insertions(+), 198 deletions(-) delete mode 100644 src/rendering/clouds/clo_tools.c diff --git a/src/rendering/clouds/clo_rendering.c b/src/rendering/clouds/clo_rendering.c index e5e8ada..e0e827a 100644 --- a/src/rendering/clouds/clo_rendering.c +++ b/src/rendering/clouds/clo_rendering.c @@ -4,6 +4,7 @@ #include "../tools.h" #include "../renderer.h" #include "clo_density.h" +#include "clo_walking.h" /******************** Fake ********************/ static int _fakeAlterLight(Renderer* renderer, LightDefinition* light, Vector3 location) @@ -25,13 +26,9 @@ static Color _fakeGetColor(Renderer* renderer, Color base, Vector3 start, Vector } /******************** Real ********************/ -/*static int _cmpLayer(const void* layer1, const void* layer2) -{ - return (((CloudsLayerDefinition*)layer1)->lower_altitude > ((CloudsLayerDefinition*)layer2)->lower_altitude) ? -1 : 1; -}*/ - static int _alterLight(Renderer* renderer, LightDefinition* light, Vector3 location) { +#if 0 CloudsDefinition* definition = renderer->clouds->definition; int i, n; @@ -43,6 +40,18 @@ static int _alterLight(Renderer* renderer, LightDefinition* light, Vector3 locat /* TODO Reduce light->reflection too */ } return n > 0; +#endif + return 0; +} + +typedef struct +{ + Color result; +} AccumulatedMaterialData; + +static void _walkerMaterialCallback(CloudsWalker* walker) +{ + /*AccumulatedMaterialData* data = (AccumulatedMaterialData*)segment->data;*/ } static Color _getColor(Renderer* renderer, Color base, Vector3 start, Vector3 end) @@ -59,7 +68,27 @@ static Color _getColor(Renderer* renderer, Color base, Vector3 start, Vector3 en /* TODO Iter layers in sorted order */ for (i = 0; i < n; i++) { - base = cloudsApplyLayer(layersGetLayer(definition->layers, i), base, renderer, start, end); + CloudsLayerDefinition* layer = (CloudsLayerDefinition*)layersGetLayer(renderer->clouds->definition->layers, i); + Vector3 ostart, oend; + + ostart = start; + oend = end; + if (!cloudsOptimizeWalkingBounds(layer, &ostart, &oend)) + { + continue; + } + else + { + CloudsWalker* walker; + AccumulatedMaterialData data; + data.result = COLOR_TRANSPARENT; + + walker = cloudsCreateWalker(renderer, layer, start, end); + cloudsStartWalking(walker, _walkerMaterialCallback, &data); + cloudsDeleteWalker(walker); + + colorMask(&base, &data.result); + } } return base; diff --git a/src/rendering/clouds/clo_tools.c b/src/rendering/clouds/clo_tools.c deleted file mode 100644 index bacf5b5..0000000 --- a/src/rendering/clouds/clo_tools.c +++ /dev/null @@ -1,143 +0,0 @@ -#include "private.h" - -/* - * Clouds tools. - */ - -#include "clo_walking.h" -#include "../renderer.h" -#include "../tools.h" - -static inline Vector3 _getNormal(CloudsLayerDefinition* layer, Vector3 position, double detail) -{ - Vector3 result = {0.0, 0.0, 0.0}; - /*Vector3 dposition; - double val, dval; - - val = _getDistanceToBorder(layer, position); - - dposition.x = position.x + detail; - dposition.y = position.y; - dposition.z = position.z; - dval = val - _getDistanceToBorder(layer, dposition); - result.x += dval; - - dposition.x = position.x - detail; - dval = val - _getDistanceToBorder(layer, dposition); - result.x -= dval; - - dposition.x = position.x; - dposition.y = position.y + detail; - dval = val - _getDistanceToBorder(layer, dposition); - result.y += dval; - - dposition.y = position.y - detail; - dval = val - _getDistanceToBorder(layer, dposition); - result.y -= dval; - - dposition.y = position.y; - dposition.z = position.z + detail; - dval = val - _getDistanceToBorder(layer, dposition); - result.z += dval; - - dposition.z = position.z - detail; - dval = val - _getDistanceToBorder(layer, dposition); - result.z -= dval;*/ - - return v3Normalize(result); -} - -static Color _applyLayerLighting(CloudsLayerDefinition* definition, Renderer* renderer, Vector3 location, double detail) -{ - Vector3 normal; - Color col1, col2; - LightStatus* lighting; - - normal = _getNormal(definition, location, 3.0); - if (renderer->render_quality > 3) - { - normal = v3Add(normal, _getNormal(definition, location, 2.0)); - normal = v3Add(normal, _getNormal(definition, location, 1.0)); - } - if (renderer->render_quality > 5) - { - normal = v3Add(normal, _getNormal(definition, location, 0.5)); - } - if (renderer->render_quality > 8) - { - normal = v3Add(normal, _getNormal(definition, location, 0.75)); - normal = v3Add(normal, _getNormal(definition, location, 1.25)); - normal = v3Add(normal, _getNormal(definition, location, 2.5)); - } - normal = v3Scale(v3Normalize(normal), definition->hardness); - - return renderer->applyLightingToSurface(renderer, location, normal, &definition->material); - - lighting = lightingCreateStatus(renderer->lighting, location, renderer->getCameraLocation(renderer, location)); - renderer->atmosphere->getLightingStatus(renderer, lighting, normal, 0); - col1 = lightingApplyStatus(lighting, normal, &definition->material); - col2 = lightingApplyStatus(lighting, v3Scale(normal, -1.0), &definition->material); - lightingDeleteStatus(lighting); - - col1.r = (col1.r + col2.r) / 2.0; - col1.g = (col1.g + col2.g) / 2.0; - col1.b = (col1.b + col2.b) / 2.0; - col1.a = (col1.a + col2.a) / 2.0; - - return col1; -} - -Color cloudsApplyLayer(CloudsLayerDefinition* definition, Color base, Renderer* renderer, Vector3 start, Vector3 end) -{ - Color col = COLOR_TRANSPARENT; - - if (!cloudsOptimizeWalkingBounds(definition, &start, &end)) - { - return base; - } - - /* TODO Walk through the cloud */ - - /*segment_count = cloudsGetLayerPrimarySegments(renderer, definition, start, end, MAX_SEGMENT_COUNT, segments);*/ - - col = renderer->atmosphere->applyAerialPerspective(renderer, start, col).final; - col.a = 0.0; - - colorMask(&base, &col); - - return base; -} - -Color cloudsLayerFilterLight(CloudsLayerDefinition* definition, Renderer* renderer, Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light) -{ - /*double inside_depth, total_depth, factor; - CloudSegment segments[MAX_SEGMENT_COUNT]; - - if (!cloudsOptimizeWalkingBounds(definition, &location, &light_location)) - { - return light; - } - - _getPrimarySegments(definition, renderer, location, direction_to_light, MAX_SEGMENT_COUNT, definition->lighttraversal, v3Norm(v3Sub(light_location, location)), &inside_depth, &total_depth, segments); - - if (definition->lighttraversal < 0.0001) - { - factor = 0.0; - } - else - { - factor = inside_depth / definition->lighttraversal; - if (factor > 1.0) - { - factor = 1.0; - } - } - - factor = 1.0 - (1.0 - definition->minimumlight) * factor; - - light.r = light.r * factor; - light.g = light.g * factor; - light.b = light.b * factor;*/ - - return light; -} diff --git a/src/rendering/clouds/clo_walking.c b/src/rendering/clouds/clo_walking.c index 35a0029..6c74c7f 100644 --- a/src/rendering/clouds/clo_walking.c +++ b/src/rendering/clouds/clo_walking.c @@ -2,6 +2,27 @@ #include "../renderer.h" +/** + * Control of the next walking order. + */ +typedef enum +{ + CLOUD_WALKING_CONTINUE, + CLOUD_WALKING_STOP, + CLOUD_WALKING_REFINE, + CLOUD_WALKING_SUBDIVIDE +} CloudWalkingOrder; + +/** + * Additional info for walking orders. + */ +typedef struct +{ + CloudWalkingOrder order; + double precision; + int max_segments; +} CloudWalkingNextAction; + int cloudsOptimizeWalkingBounds(CloudsLayerDefinition* layer, Vector3* start, Vector3* end) { @@ -54,3 +75,35 @@ int cloudsOptimizeWalkingBounds(CloudsLayerDefinition* layer, Vector3* start, Ve return 1; } + +CloudsWalker* cloudsCreateWalker(Renderer* renderer, CloudsLayerDefinition* layer, Vector3 start, Vector3 end) +{ +} + +void cloudsDeleteWalker(CloudsWalker* walker) +{ +} + +void cloudsWalkerPerformStep(CloudsWalker* walker) +{ +} + +void cloudsWalkerOrderStop(CloudsWalker* walker) +{ +} + +void cloudsWalkerOrderRefine(CloudsWalker* walker, double precision) +{ +} + +void cloudsWalkerOrderSubdivide(CloudsWalker* walker, double max_segments) +{ +} + +CloudWalkerStepInfo* cloudsWalkerGetLastSegment(CloudsWalker* walker) +{ +} + +void cloudsStartWalking(CloudsWalker* walker, FuncCloudsWalkingCallback callback, void* data) +{ +} diff --git a/src/rendering/clouds/clo_walking.h b/src/rendering/clouds/clo_walking.h index 7984c66..28a77b7 100644 --- a/src/rendering/clouds/clo_walking.h +++ b/src/rendering/clouds/clo_walking.h @@ -31,29 +31,11 @@ typedef struct double precision_asked; void* data; -} CloudWalkingInfo; +} CloudWalkerStepInfo; -/** - * Control of the next walking order. - */ -typedef enum -{ - CLOUD_WALKING_CONTINUE, - CLOUD_WALKING_STOP, - CLOUD_WALKING_REFINE, - CLOUD_WALKING_SUBDIVIDE -} CloudWalkingOrder; +typedef struct CloudsWalker CloudsWalker; -/** - * Additional info for walking orders. - */ -typedef struct -{ - double precision; - int max_segments; -} CloudWalkingOrderInfo; - -typedef CloudWalkingOrder(*FuncCloudSegmentCallback)(CloudWalkingInfo* segment, CloudWalkingOrderInfo* order); +typedef void (*FuncCloudsWalkingCallback)(CloudsWalker* walker); /** * Optimize the search limits in a layer. @@ -66,18 +48,69 @@ typedef CloudWalkingOrder(*FuncCloudSegmentCallback)(CloudWalkingInfo* segment, int cloudsOptimizeWalkingBounds(CloudsLayerDefinition* layer, Vector3* start, Vector3* end); /** - * Start walking through a segment. + * Create a cloud walker. * * For better performance, the segment should by optimized using cloudsOptimizeWalkingBounds. + * @param renderer Renderer context + * @param layer The cloud layer to traverse + * @param start Start of the walk + * @param end End of the walk + */ +CloudsWalker* cloudsCreateWalker(Renderer* renderer, CloudsLayerDefinition* layer, Vector3 start, Vector3 end); + +/** + * Delete a cloud walker. + * + * @param walker The walker to free + */ +void cloudsDeleteWalker(CloudsWalker* walker); + +/** + * Perform a single step. + * + * @param walker The walker to use + */ +void cloudsWalkerPerformStep(CloudsWalker* walker); + +/** + * Order the walker to stop. + * + * @param walker The walker to use + */ +void cloudsWalkerOrderStop(CloudsWalker* walker); + +/** + * Order the walker to refine the search for cloud entry or exit. + * + * @param walker The walker to use + * @param precision Precision wanted for the refinement + */ +void cloudsWalkerOrderRefine(CloudsWalker* walker, double precision); + +/** + * Order the walker to subdivide the previous segment in smaller segments. + * + * @param walker The walker to use + * @param max_segments Maximal number of segments + */ +void cloudsWalkerOrderSubdivide(CloudsWalker* walker, double max_segments); + +/** + * Get the last segment information. + * + * @param walker The walker to use + */ +CloudWalkerStepInfo* cloudsWalkerGetLastSegment(CloudsWalker* walker); + +/** + * Start walking automatically through a segment. + * * The callback will be called with each segment found, giving info and asking for desired alteration on walking. - * @param renderer The renderer environment - * @param layer The cloud layer - * @param start Start position of the lookup, already optimized - * @param end End position of the lookup, already optimized + * @param walker The walker to use * @param callback Callback to be called with each found segment * @param data User data that will be passed back in the callback */ -void cloudsStartWalking(Renderer* renderer, CloudsLayerDefinition* layer, Vector3 start, Vector3 end, FuncCloudSegmentCallback callback, void* data); +void cloudsStartWalking(CloudsWalker* walker, FuncCloudsWalkingCallback callback, void* data); #ifdef __cplusplus } diff --git a/src/testing/test_clouds.c b/src/testing/test_clouds.c index 4bd6c57..68c6c05 100644 --- a/src/testing/test_clouds.c +++ b/src/testing/test_clouds.c @@ -200,11 +200,8 @@ static double _getLayerDensitySinX(Renderer* renderer, CloudsLayerDefinition* la return (density > 0.0) ? density : 0.0; } -/*START_TEST(test_clouds_primary_segments) +START_TEST(test_clouds_walking) { - int segment_count, i; - CloudPrimarySegment segments[10]; - CloudsLayerDefinition* layer; layer = cloudsGetLayerType().callback_create(); layer->lower_altitude = -1.0; @@ -217,28 +214,14 @@ static double _getLayerDensitySinX(Renderer* renderer, CloudsLayerDefinition* la renderer->render_quality = 8; renderer->clouds->getLayerDensity = _getLayerDensitySinX; - segment_count = cloudsGetLayerPrimarySegments(renderer, layer, v3(-0.4, 0.0, 0.0), v3(1.9, 0.0, 0.0), 10, segments); - ck_assert_int_eq(segment_count, 2); - for (i = 0; i < segment_count; i++) - { - ck_assert_double_eq(segments[i].entry_point.y, 0.0); - ck_assert_double_eq(segments[i].entry_point.z, 0.0); - ck_assert_double_eq(segments[i].exit_point.y, 0.0); - ck_assert_double_eq(segments[i].exit_point.z, 0.0); - } - ck_assert_double_in_range(segments[0].entry_point.x, -0.4, 0.0); - ck_assert_double_in_range(segments[0].exit_point.x, 0.5, 1.0); - ck_assert_double_in_range(segments[0].length, 0.5, 1.3); - ck_assert_double_gte(segments[1].entry_point.x, segments[0].exit_point.x); - ck_assert_double_in_range(segments[1].entry_point.x, 0.5, 1.0); - ck_assert_double_in_range(segments[1].exit_point.x, 1.5, 1.9); - ck_assert_double_in_range(segments[1].length, 0.5, 1.3); + // TODO cloudsGetLayerType().callback_delete(layer); rendererDelete(renderer); } -END_TEST*/ +END_TEST TEST_CASE(clouds, test_clouds_density, - test_clouds_walking_boundaries) + test_clouds_walking_boundaries, + test_clouds_walking) From a484479fb7b378a4b49eb22e24048050658b9556 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Wed, 29 May 2013 22:01:09 +0200 Subject: [PATCH 04/19] clouds_walking: Added iterator system for walking --- src/rendering/clouds/clo_walking.c | 79 +++++++++++++++++++++++++++++- src/rendering/clouds/clo_walking.h | 15 ++++-- src/testing/test_clouds.c | 31 +++++++++++- 3 files changed, 120 insertions(+), 5 deletions(-) diff --git a/src/rendering/clouds/clo_walking.c b/src/rendering/clouds/clo_walking.c index 6c74c7f..5dd6672 100644 --- a/src/rendering/clouds/clo_walking.c +++ b/src/rendering/clouds/clo_walking.c @@ -23,6 +23,24 @@ typedef struct int max_segments; } CloudWalkingNextAction; +/* + * Private structure for the walker. + */ +struct CloudsWalker +{ + Vector3 start; + Vector3 end; + Vector3 diff; + + double cursor; + double max_length; + double step_size; + + CloudWalkerStepInfo last_segment; + + CloudWalkingNextAction next_action; +}; + int cloudsOptimizeWalkingBounds(CloudsLayerDefinition* layer, Vector3* start, Vector3* end) { @@ -78,32 +96,91 @@ int cloudsOptimizeWalkingBounds(CloudsLayerDefinition* layer, Vector3* start, Ve CloudsWalker* cloudsCreateWalker(Renderer* renderer, CloudsLayerDefinition* layer, Vector3 start, Vector3 end) { + CloudsWalker* result; + + result = (CloudsWalker*)malloc(sizeof (CloudsWalker)); + + result->start = start; + result->end = end; + result->diff = v3Sub(end, start); + result->max_length = v3Norm(result->diff); + result->cursor = 0.0; + result->step_size = 1.0; + + result->last_segment.renderer = renderer; + result->last_segment.layer = layer; + result->last_segment.walked_distance = 0.0; + result->last_segment.end = start; + + result->next_action.order = CLOUD_WALKING_CONTINUE; + + return result; } void cloudsDeleteWalker(CloudsWalker* walker) { + free(walker); } -void cloudsWalkerPerformStep(CloudsWalker* walker) +void cloudsSetStepSize(CloudsWalker* walker, double step) { + /* TODO Negative step => automatic */ + walker->step_size = step; +} + +int cloudsWalkerPerformStep(CloudsWalker* walker) +{ + if (walker->next_action.order == CLOUD_WALKING_STOP || walker->cursor >= walker->max_length) + { + walker->next_action.order = CLOUD_WALKING_STOP; + return 0; + } + else if (walker->next_action.order == CLOUD_WALKING_CONTINUE) + { + /* TODO Limit to end */ + walker->last_segment.start = walker->last_segment.end; + walker->last_segment.walked_distance = walker->cursor; + + walker->cursor += walker->step_size; + + walker->last_segment.end = v3Add(walker->start, v3Scale(walker->diff, walker->cursor / walker->max_length)); + walker->last_segment.length = walker->step_size; + + return 1; + } + else + { + /* TODO */ + return 0; + } } void cloudsWalkerOrderStop(CloudsWalker* walker) { + walker->next_action.order = CLOUD_WALKING_STOP; } void cloudsWalkerOrderRefine(CloudsWalker* walker, double precision) { + walker->next_action.order = CLOUD_WALKING_REFINE; + walker->next_action.precision = precision; } void cloudsWalkerOrderSubdivide(CloudsWalker* walker, double max_segments) { + walker->next_action.order = CLOUD_WALKING_SUBDIVIDE; + walker->next_action.max_segments = max_segments; } CloudWalkerStepInfo* cloudsWalkerGetLastSegment(CloudsWalker* walker) { + return &walker->last_segment; } void cloudsStartWalking(CloudsWalker* walker, FuncCloudsWalkingCallback callback, void* data) { + while (cloudsWalkerPerformStep(walker)) + { + callback(walker); + } } diff --git a/src/rendering/clouds/clo_walking.h b/src/rendering/clouds/clo_walking.h index 28a77b7..49366da 100644 --- a/src/rendering/clouds/clo_walking.h +++ b/src/rendering/clouds/clo_walking.h @@ -26,9 +26,9 @@ typedef struct Vector3 end; double length; - int refined; + /*int refined; int subdivision_level; - double precision_asked; + double precision_asked;*/ void* data; } CloudWalkerStepInfo; @@ -65,12 +65,21 @@ CloudsWalker* cloudsCreateWalker(Renderer* renderer, CloudsLayerDefinition* laye */ void cloudsDeleteWalker(CloudsWalker* walker); +/** + * Define the segment size for next steps. + * + * @param walker The walker to configure + * @param step The step length, negative for automatic + */ +void cloudsSetStepSize(CloudsWalker* walker, double step); + /** * Perform a single step. * * @param walker The walker to use + * @return 1 to continue the loop, 0 to stop */ -void cloudsWalkerPerformStep(CloudsWalker* walker); +int cloudsWalkerPerformStep(CloudsWalker* walker); /** * Order the walker to stop. diff --git a/src/testing/test_clouds.c b/src/testing/test_clouds.c index 68c6c05..add42e7 100644 --- a/src/testing/test_clouds.c +++ b/src/testing/test_clouds.c @@ -202,6 +202,7 @@ static double _getLayerDensitySinX(Renderer* renderer, CloudsLayerDefinition* la START_TEST(test_clouds_walking) { + /* Init */ CloudsLayerDefinition* layer; layer = cloudsGetLayerType().callback_create(); layer->lower_altitude = -1.0; @@ -214,7 +215,35 @@ START_TEST(test_clouds_walking) renderer->render_quality = 8; renderer->clouds->getLayerDensity = _getLayerDensitySinX; - // TODO + CloudsWalker* walker = cloudsCreateWalker(renderer, layer, v3(-0.4, 0.0, 0.0), v3(10.0, 0.0, 0.0)); + CloudWalkerStepInfo* segment; + int result; + + /* First step */ + cloudsSetStepSize(walker, 0.3); + result = cloudsWalkerPerformStep(walker); + segment = cloudsWalkerGetLastSegment(walker); + ck_assert_int_eq(result, 1); + ck_assert_double_eq(segment->walked_distance, 0.0); + ck_assert_vector_values(segment->start, -0.4, 0.0, 0.0); + ck_assert_vector_values(segment->end, -0.1, 0.0, 0.0); + ck_assert_double_eq(segment->length, 0.3); + + /* Second step */ + result = cloudsWalkerPerformStep(walker); + segment = cloudsWalkerGetLastSegment(walker); + ck_assert_int_eq(result, 1); + ck_assert_double_eq(segment->walked_distance, 0.3); + ck_assert_vector_values(segment->start, -0.1, 0.0, 0.0); + ck_assert_vector_values(segment->end, 0.2, 0.0, 0.0); + ck_assert_double_eq(segment->length, 0.3); + + /* Order to refine second step around the entry point */ + cloudsWalkerOrderRefine(walker, 0.01); + /* TODO */ + + /* Clean up */ + cloudsDeleteWalker(walker); cloudsGetLayerType().callback_delete(layer); rendererDelete(renderer); From 1c0c93479ec5f8d66d0f747146cf2370e81a1c73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Fri, 31 May 2013 21:36:59 +0200 Subject: [PATCH 05/19] clouds_walking: Added entry refinement --- src/rendering/clouds/clo_walking.c | 77 ++++++++++++++++++++++++++++-- src/rendering/clouds/clo_walking.h | 15 ++++-- src/testing/test_clouds.c | 29 ++++++++--- 3 files changed, 107 insertions(+), 14 deletions(-) diff --git a/src/rendering/clouds/clo_walking.c b/src/rendering/clouds/clo_walking.c index 5dd6672..42846c5 100644 --- a/src/rendering/clouds/clo_walking.c +++ b/src/rendering/clouds/clo_walking.c @@ -36,6 +36,7 @@ struct CloudsWalker double max_length; double step_size; + int started; CloudWalkerStepInfo last_segment; CloudWalkingNextAction next_action; @@ -107,10 +108,9 @@ CloudsWalker* cloudsCreateWalker(Renderer* renderer, CloudsLayerDefinition* laye result->cursor = 0.0; result->step_size = 1.0; + result->started = 0; result->last_segment.renderer = renderer; result->last_segment.layer = layer; - result->last_segment.walked_distance = 0.0; - result->last_segment.end = start; result->next_action.order = CLOUD_WALKING_CONTINUE; @@ -128,8 +128,64 @@ void cloudsSetStepSize(CloudsWalker* walker, double step) walker->step_size = step; } +static void _getPoint(CloudsWalker* walker, double cursor, CloudWalkerPoint* out_point) +{ + out_point->distance_from_start = cursor; + out_point->location = v3Add(walker->start, v3Scale(walker->diff, out_point->distance_from_start / walker->max_length)); + + Renderer* renderer = walker->last_segment.renderer; + CloudsLayerDefinition* layer = walker->last_segment.layer; + out_point->global_density = renderer->clouds->getLayerDensity(renderer, layer, out_point->location); +} + +static void _refineSegment(CloudsWalker* walker, double start_cursor, double start_density, double end_cursor, double end_density, double precision, CloudWalkerPoint* result) +{ + CloudWalkerPoint middle; + + _getPoint(walker, (start_cursor + end_cursor) / 2.0, &middle); + + if (start_density == 0.0) + { + /* Looking for entry */ + if (middle.global_density == 0.0) + { + _refineSegment(walker, middle.distance_from_start, middle.global_density, end_cursor, end_density, precision, result); + } + else if (middle.distance_from_start - start_cursor > precision) + { + _refineSegment(walker, start_cursor, start_density, middle.distance_from_start, middle.global_density, precision, result); + } + else + { + *result = middle; + } + } + else + { + /* Looking for exit */ + if (middle.global_density == 0.0) + { + _refineSegment(walker, start_cursor, start_density, middle.distance_from_start, middle.global_density, precision, result); + } + else if (end_cursor - middle.distance_from_start > precision) + { + _refineSegment(walker, middle.distance_from_start, middle.global_density, end_cursor, end_density, precision, result); + } + else + { + *result = middle; + } + } +} + int cloudsWalkerPerformStep(CloudsWalker* walker) { + if (!walker->started) + { + _getPoint(walker, 0.0, &walker->last_segment.end); + walker->started = 1; + } + if (walker->next_action.order == CLOUD_WALKING_STOP || walker->cursor >= walker->max_length) { walker->next_action.order = CLOUD_WALKING_STOP; @@ -139,15 +195,28 @@ int cloudsWalkerPerformStep(CloudsWalker* walker) { /* TODO Limit to end */ walker->last_segment.start = walker->last_segment.end; - walker->last_segment.walked_distance = walker->cursor; walker->cursor += walker->step_size; - walker->last_segment.end = v3Add(walker->start, v3Scale(walker->diff, walker->cursor / walker->max_length)); + _getPoint(walker, walker->cursor, &walker->last_segment.end); walker->last_segment.length = walker->step_size; return 1; } + else if (walker->next_action.order == CLOUD_WALKING_REFINE) + { + /* Refine segment with dichotomy */ + _refineSegment(walker, + walker->last_segment.start.distance_from_start, + walker->last_segment.start.global_density, + walker->last_segment.end.distance_from_start, + walker->last_segment.end.global_density, + walker->next_action.precision, + &walker->last_segment.start); + walker->last_segment.length = walker->last_segment.end.distance_from_start - walker->last_segment.start.distance_from_start; + walker->next_action.order = CLOUD_WALKING_CONTINUE; + return 1; + } else { /* TODO */ diff --git a/src/rendering/clouds/clo_walking.h b/src/rendering/clouds/clo_walking.h index 49366da..5aaa812 100644 --- a/src/rendering/clouds/clo_walking.h +++ b/src/rendering/clouds/clo_walking.h @@ -13,6 +13,13 @@ extern "C" { #endif +typedef struct +{ + double distance_from_start; + Vector3 location; + double global_density; +} CloudWalkerPoint; + /** * Information on a segment yielded by walking. */ @@ -21,9 +28,8 @@ typedef struct Renderer* renderer; CloudsLayerDefinition* layer; - double walked_distance; - Vector3 start; - Vector3 end; + CloudWalkerPoint start; + CloudWalkerPoint end; double length; /*int refined; @@ -91,6 +97,9 @@ void cloudsWalkerOrderStop(CloudsWalker* walker); /** * Order the walker to refine the search for cloud entry or exit. * + * The refinement will next yield a shorter version of the segment, containing only the cloud-inside portion, with a + * tolerance fixed by precision. For an entry point, this will discard the part before cloud entry. For en exit point, + * the portion after this point will be part of the next step, as normal walking resumes. * @param walker The walker to use * @param precision Precision wanted for the refinement */ diff --git a/src/testing/test_clouds.c b/src/testing/test_clouds.c index add42e7..d00de74 100644 --- a/src/testing/test_clouds.c +++ b/src/testing/test_clouds.c @@ -224,23 +224,38 @@ START_TEST(test_clouds_walking) result = cloudsWalkerPerformStep(walker); segment = cloudsWalkerGetLastSegment(walker); ck_assert_int_eq(result, 1); - ck_assert_double_eq(segment->walked_distance, 0.0); - ck_assert_vector_values(segment->start, -0.4, 0.0, 0.0); - ck_assert_vector_values(segment->end, -0.1, 0.0, 0.0); ck_assert_double_eq(segment->length, 0.3); + ck_assert_double_eq(segment->start.distance_from_start, 0.0); + ck_assert_vector_values(segment->start.location, -0.4, 0.0, 0.0); + ck_assert_double_eq(segment->start.global_density, 0.0); + ck_assert_double_eq(segment->end.distance_from_start, 0.3); + ck_assert_vector_values(segment->end.location, -0.1, 0.0, 0.0); + ck_assert_double_eq(segment->end.global_density, 0.0); /* Second step */ result = cloudsWalkerPerformStep(walker); segment = cloudsWalkerGetLastSegment(walker); ck_assert_int_eq(result, 1); - ck_assert_double_eq(segment->walked_distance, 0.3); - ck_assert_vector_values(segment->start, -0.1, 0.0, 0.0); - ck_assert_vector_values(segment->end, 0.2, 0.0, 0.0); ck_assert_double_eq(segment->length, 0.3); + ck_assert_double_eq(segment->start.distance_from_start, 0.3); + ck_assert_vector_values(segment->start.location, -0.1, 0.0, 0.0); + ck_assert_double_eq(segment->start.global_density, 0.0); + ck_assert_double_eq(segment->end.distance_from_start, 0.6); + ck_assert_vector_values(segment->end.location, 0.2, 0.0, 0.0); + ck_assert_double_gt(segment->end.global_density, 0.9); /* Order to refine second step around the entry point */ cloudsWalkerOrderRefine(walker, 0.01); - /* TODO */ + result = cloudsWalkerPerformStep(walker); + segment = cloudsWalkerGetLastSegment(walker); + ck_assert_int_eq(result, 1); + ck_assert_double_in_range(segment->length, 0.19, 0.21); + ck_assert_double_in_range(segment->start.distance_from_start, 0.39, 0.41); + ck_assert_double_in_range(segment->start.location.x, -0.01, 0.01); + /* TODO Check segment->start.global_density */ + ck_assert_double_eq(segment->end.distance_from_start, 0.6); + ck_assert_vector_values(segment->end.location, 0.2, 0.0, 0.0); + ck_assert_double_gt(segment->end.global_density, 0.9); /* Clean up */ cloudsDeleteWalker(walker); From d2874207f8daa7043b3682e8eed26b927d28972d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Sat, 1 Jun 2013 15:56:20 +0200 Subject: [PATCH 06/19] Fixed some unit tests check functions --- src/testing/common.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/testing/common.h b/src/testing/common.h index daf3b82..c399315 100644 --- a/src/testing/common.h +++ b/src/testing/common.h @@ -37,7 +37,7 @@ static inline int _double_not_equals(double x, double y) } static inline int _double_greater(double x, double y) { - return _double_not_equals(x, y) || (x > y); + return _double_not_equals(x, y) && (x > y); } static inline int _double_greater_or_equal(double x, double y) { @@ -45,7 +45,7 @@ static inline int _double_greater_or_equal(double x, double y) } static inline int _double_less(double x, double y) { - return _double_not_equals(x, y) || (x < y); + return _double_not_equals(x, y) && (x < y); } static inline int _double_less_or_equal(double x, double y) { @@ -56,8 +56,8 @@ static inline int _double_less_or_equal(double x, double y) #define ck_assert_double_eq(X, Y) _ck_assert_double(_double_equals, X, ==, Y) #define ck_assert_double_ne(X, Y) _ck_assert_double(_double_not_equals, X, !=, Y) #define ck_assert_double_gt(X, Y) _ck_assert_double(_double_greater, X, >, Y) -#define ck_assert_double_lt(X, Y) _ck_assert_double(_double_greater_or_equal, X, >=, Y) -#define ck_assert_double_gte(X, Y) _ck_assert_double(_double_less, X, <, Y) +#define ck_assert_double_lt(X, Y) _ck_assert_double(_double_less, X, >=, Y) +#define ck_assert_double_gte(X, Y) _ck_assert_double(_double_greater_or_equal, X, <, Y) #define ck_assert_double_lte(X, Y) _ck_assert_double(_double_less_or_equal, X, <=, Y) From 07e3f4a17544ac8be9239aa7daa51e6d6b4f6500 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Sat, 1 Jun 2013 16:14:34 +0200 Subject: [PATCH 07/19] Fixed some unit tests check functions --- src/testing/common.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/testing/common.h b/src/testing/common.h index c399315..0a7a39f 100644 --- a/src/testing/common.h +++ b/src/testing/common.h @@ -56,8 +56,8 @@ static inline int _double_less_or_equal(double x, double y) #define ck_assert_double_eq(X, Y) _ck_assert_double(_double_equals, X, ==, Y) #define ck_assert_double_ne(X, Y) _ck_assert_double(_double_not_equals, X, !=, Y) #define ck_assert_double_gt(X, Y) _ck_assert_double(_double_greater, X, >, Y) -#define ck_assert_double_lt(X, Y) _ck_assert_double(_double_less, X, >=, Y) -#define ck_assert_double_gte(X, Y) _ck_assert_double(_double_greater_or_equal, X, <, Y) +#define ck_assert_double_lt(X, Y) _ck_assert_double(_double_less, X, <, Y) +#define ck_assert_double_gte(X, Y) _ck_assert_double(_double_greater_or_equal, X, >=, Y) #define ck_assert_double_lte(X, Y) _ck_assert_double(_double_less_or_equal, X, <=, Y) From 20dbe142f53f30348a5d7c83211e75c8c37c365e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Sat, 1 Jun 2013 17:10:00 +0200 Subject: [PATCH 08/19] Fixed issues on rendering dialog --- src/editing/dialogrender.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/editing/dialogrender.cpp b/src/editing/dialogrender.cpp index 09844b9..d8fe4fa 100644 --- a/src/editing/dialogrender.cpp +++ b/src/editing/dialogrender.cpp @@ -133,7 +133,7 @@ DialogRender::DialogRender(QWidget *parent, Renderer* renderer): _actions->layout()->addWidget(_save_button); // Connections - connect(this, SIGNAL(renderSizeChanged(int, int)), this, SLOT(applyRenderSize(int, int))); + //connect(this, SIGNAL(renderSizeChanged(int, int)), this, SLOT(applyRenderSize(int, int))); connect(this, SIGNAL(progressChanged(double)), this, SLOT(applyProgress(double))); connect(this, SIGNAL(renderEnded()), this, SLOT(applyRenderEnded())); connect(_save_button, SIGNAL(clicked()), this, SLOT(saveRender())); @@ -173,7 +173,7 @@ void DialogRender::startRender(RenderParams params) { _started = time(NULL); - //applyRenderSize(params.width, params.height); + applyRenderSize(params.width, params.height); rendererSetPreviewCallbacks(_renderer, _renderStart, _renderDraw, _renderUpdate); _render_thread = new RenderThread(this, _renderer, params); @@ -217,9 +217,10 @@ void DialogRender::toneMappingChanged() void DialogRender::loadLastRender() { - //applyRenderSize(_renderer->render_width, _renderer->render_height); + applyRenderSize(_renderer->render_width, _renderer->render_height); rendererSetPreviewCallbacks(_renderer, _renderStart, _renderDraw, _renderUpdate); renderEnded(); + toneMappingChanged(); exec(); } From 1ede3de8d520219b5ef7b35162547425b38830a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Sat, 1 Jun 2013 16:57:23 +0200 Subject: [PATCH 09/19] clouds_walking: Started using walker in rendering --- TODO | 2 + src/rendering/clouds/clo_rendering.c | 120 ++++++++++++++++++++++++--- src/rendering/clouds/clo_walking.c | 44 ++++++---- src/rendering/clouds/clo_walking.h | 6 +- src/testing/common.h | 5 ++ src/testing/test_clouds.c | 41 +++++++-- 6 files changed, 183 insertions(+), 35 deletions(-) diff --git a/TODO b/TODO index 038debc..04ff7e9 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,5 @@ Technology Preview 2 : +- Implement perspective correction for coordinate mapping of rasterized polygons. - Finalize terrain editor. => Add a generation dialog for base noise (overwriting changes). - Get rid of noise dialogs, for simpler settings. @@ -15,6 +16,7 @@ Technology Preview 2 : Technlogy Preview 3 : - Start an undo/redo system ? +- Alter aerial perspective using estimation of the amount of light left after cloud layers traversal. - Add a map preview to terrain editor. - Better time selection widget for atmosphere. - Clouds should keep distance to ground. diff --git a/src/rendering/clouds/clo_rendering.c b/src/rendering/clouds/clo_rendering.c index e0e827a..62a7984 100644 --- a/src/rendering/clouds/clo_rendering.c +++ b/src/rendering/clouds/clo_rendering.c @@ -1,5 +1,6 @@ #include "private.h" +#include #include #include "../tools.h" #include "../renderer.h" @@ -26,32 +27,117 @@ static Color _fakeGetColor(Renderer* renderer, Color base, Vector3 start, Vector } /******************** Real ********************/ +typedef struct +{ + double light_power; + double out_scattering; /* Amount of light scattered away by heavy particles */ +} AccumulatedLightData; + +static void _walkerFilterCallback(CloudsWalker* walker) +{ + CloudWalkerStepInfo* segment = cloudsWalkerGetLastSegment(walker); + AccumulatedLightData* data = (AccumulatedLightData*)segment->data; + + assert(data != NULL); + + double density_integral = segment->length * (segment->start.global_density + segment->end.global_density) / 2.0; + + data->out_scattering += 0.3 * density_integral; + + if (data->out_scattering > data->light_power) + { + cloudsWalkerOrderStop(walker); + } +} + static int _alterLight(Renderer* renderer, LightDefinition* light, Vector3 location) { -#if 0 CloudsDefinition* definition = renderer->clouds->definition; int i, n; + AccumulatedLightData data; + data.out_scattering = 0.0; + data.light_power = colorGetPower(&light->color); + /* TODO Iter layers in sorted order */ n = layersCount(definition->layers); for (i = 0; i < n; i++) { - light->color = cloudsLayerFilterLight(layersGetLayer(definition->layers, i), renderer, light->color, location, v3Add(location, v3Scale(light->direction, -10000.0)), v3Scale(light->direction, -1.0)); - /* TODO Reduce light->reflection too */ + CloudsLayerDefinition* layer = (CloudsLayerDefinition*)layersGetLayer(renderer->clouds->definition->layers, i); + Vector3 ostart, oend; + + ostart = location; + oend = v3Add(location, v3Scale(light->direction, -10000.0)); + if (!cloudsOptimizeWalkingBounds(layer, &ostart, &oend)) + { + continue; + } + else + { + CloudsWalker* walker; + + walker = cloudsCreateWalker(renderer, layer, ostart, oend); + cloudsWalkerSetStepSize(walker, -1.0); + cloudsStartWalking(walker, _walkerFilterCallback, &data); + cloudsDeleteWalker(walker); + } } - return n > 0; -#endif - return 0; + + double max_power = colorGetPower(&light->color) - data.out_scattering; + if (max_power < 0.0) + { + light->color = COLOR_BLACK; + } + else + { + colorLimitPower(&light->color, max_power); + } + + return data.out_scattering > 0.0; } typedef struct { - Color result; + double out_scattering; /* Amount of light scattered away by heavy particles */ + Color in_scattering; /* Amount of light redirected toward the viewer */ } AccumulatedMaterialData; +static inline void _applyOutScattering(Color* col, double out_scattering) +{ + if (out_scattering >= 1.0) + { + col->r = col->g = col->b = 0.0; + } + else + { + col->r *= (1.0 - out_scattering); + col->g *= (1.0 - out_scattering); + col->b *= (1.0 - out_scattering); + } +} + static void _walkerMaterialCallback(CloudsWalker* walker) { - /*AccumulatedMaterialData* data = (AccumulatedMaterialData*)segment->data;*/ + CloudWalkerStepInfo* segment = cloudsWalkerGetLastSegment(walker); + AccumulatedMaterialData* data = (AccumulatedMaterialData*)segment->data; + Renderer* renderer = segment->renderer; + CloudsLayerDefinition* layer = segment->layer; + + assert(data != NULL); + + double density_integral = segment->length * (segment->start.global_density + segment->end.global_density) / 2.0; + + data->out_scattering += 0.5 * density_integral; + + Color in_scattering = renderer->applyLightingToSurface(renderer, segment->start.location, VECTOR_UP, &layer->material); + in_scattering.r *= density_integral * 5.0; + in_scattering.g *= density_integral * 5.0; + in_scattering.b *= density_integral * 5.0; + _applyOutScattering(&in_scattering, data->out_scattering); + + data->in_scattering.r += in_scattering.r; + data->in_scattering.g += in_scattering.g; + data->in_scattering.b += in_scattering.b; } static Color _getColor(Renderer* renderer, Color base, Vector3 start, Vector3 end) @@ -81,13 +167,25 @@ static Color _getColor(Renderer* renderer, Color base, Vector3 start, Vector3 en { CloudsWalker* walker; AccumulatedMaterialData data; - data.result = COLOR_TRANSPARENT; + data.out_scattering = 0.0; + data.in_scattering = COLOR_BLACK; - walker = cloudsCreateWalker(renderer, layer, start, end); + walker = cloudsCreateWalker(renderer, layer, ostart, oend); + cloudsWalkerSetStepSize(walker, -1.0); cloudsStartWalking(walker, _walkerMaterialCallback, &data); cloudsDeleteWalker(walker); - colorMask(&base, &data.result); + /* Apply final out_scattering to base */ + _applyOutScattering(&base, data.out_scattering); + + /* Apply in_scattering */ + base.r += data.in_scattering.r; + base.g += data.in_scattering.g; + base.b += data.in_scattering.b; + + /* Apply aerial perspective approximation */ + /* TODO This should be done at cloud entry */ + base = renderer->applyMediumTraversal(renderer, ostart, base); } } diff --git a/src/rendering/clouds/clo_walking.c b/src/rendering/clouds/clo_walking.c index 42846c5..5a84b4c 100644 --- a/src/rendering/clouds/clo_walking.c +++ b/src/rendering/clouds/clo_walking.c @@ -122,10 +122,17 @@ void cloudsDeleteWalker(CloudsWalker* walker) free(walker); } -void cloudsSetStepSize(CloudsWalker* walker, double step) +void cloudsWalkerSetStepSize(CloudsWalker* walker, double step) { - /* TODO Negative step => automatic */ - walker->step_size = step; + if (step > 0.0) + { + walker->step_size = step; + } + else + { + /* TODO Automatic settings (using rendering quality and cloud feature size) */ + walker->step_size = 1.0; + } } static void _getPoint(CloudsWalker* walker, double cursor, CloudWalkerPoint* out_point) @@ -147,33 +154,33 @@ static void _refineSegment(CloudsWalker* walker, double start_cursor, double sta if (start_density == 0.0) { /* Looking for entry */ - if (middle.global_density == 0.0) + if (middle.distance_from_start - start_cursor < precision) + { + *result = middle; + } + else if (middle.global_density == 0.0) { _refineSegment(walker, middle.distance_from_start, middle.global_density, end_cursor, end_density, precision, result); } - else if (middle.distance_from_start - start_cursor > precision) - { - _refineSegment(walker, start_cursor, start_density, middle.distance_from_start, middle.global_density, precision, result); - } else { - *result = middle; + _refineSegment(walker, start_cursor, start_density, middle.distance_from_start, middle.global_density, precision, result); } } else { /* Looking for exit */ - if (middle.global_density == 0.0) + if (end_cursor - middle.distance_from_start < precision) + { + *result = middle; + } + else if (middle.global_density == 0.0) { _refineSegment(walker, start_cursor, start_density, middle.distance_from_start, middle.global_density, precision, result); } - else if (end_cursor - middle.distance_from_start > precision) - { - _refineSegment(walker, middle.distance_from_start, middle.global_density, end_cursor, end_density, precision, result); - } else { - *result = middle; + _refineSegment(walker, middle.distance_from_start, middle.global_density, end_cursor, end_density, precision, result); } } } @@ -200,6 +207,7 @@ int cloudsWalkerPerformStep(CloudsWalker* walker) _getPoint(walker, walker->cursor, &walker->last_segment.end); walker->last_segment.length = walker->step_size; + walker->last_segment.refined = 0; return 1; } @@ -212,9 +220,12 @@ int cloudsWalkerPerformStep(CloudsWalker* walker) walker->last_segment.end.distance_from_start, walker->last_segment.end.global_density, walker->next_action.precision, - &walker->last_segment.start); + (walker->last_segment.start.global_density == 0.0) ? (&walker->last_segment.start) : (&walker->last_segment.end)); walker->last_segment.length = walker->last_segment.end.distance_from_start - walker->last_segment.start.distance_from_start; + walker->last_segment.refined = 1; + walker->next_action.order = CLOUD_WALKING_CONTINUE; + return 1; } else @@ -248,6 +259,7 @@ CloudWalkerStepInfo* cloudsWalkerGetLastSegment(CloudsWalker* walker) void cloudsStartWalking(CloudsWalker* walker, FuncCloudsWalkingCallback callback, void* data) { + walker->last_segment.data = data; while (cloudsWalkerPerformStep(walker)) { callback(walker); diff --git a/src/rendering/clouds/clo_walking.h b/src/rendering/clouds/clo_walking.h index 5aaa812..1bd31fc 100644 --- a/src/rendering/clouds/clo_walking.h +++ b/src/rendering/clouds/clo_walking.h @@ -32,8 +32,8 @@ typedef struct CloudWalkerPoint end; double length; - /*int refined; - int subdivision_level; + int refined; + /*int subdivision_level; double precision_asked;*/ void* data; @@ -77,7 +77,7 @@ void cloudsDeleteWalker(CloudsWalker* walker); * @param walker The walker to configure * @param step The step length, negative for automatic */ -void cloudsSetStepSize(CloudsWalker* walker, double step); +void cloudsWalkerSetStepSize(CloudsWalker* walker, double step); /** * Perform a single step. diff --git a/src/testing/common.h b/src/testing/common.h index 0a7a39f..27a5655 100644 --- a/src/testing/common.h +++ b/src/testing/common.h @@ -27,6 +27,11 @@ static inline void _add_methods_to_case(TCase* tc, ...) suite_add_tcase(s, tc); \ } +/***** Boolean assertions *****/ +#define ck_assert_true(_X_) ck_assert_int_ne((_X_), 0) +#define ck_assert_false(_X_) ck_assert_int_eq((_X_), 0) + +/***** Floating point assertions *****/ static inline int _double_equals(double x, double y) { return fabs(x - y) < 0.00000000001; diff --git a/src/testing/test_clouds.c b/src/testing/test_clouds.c index d00de74..4d255c3 100644 --- a/src/testing/test_clouds.c +++ b/src/testing/test_clouds.c @@ -220,10 +220,11 @@ START_TEST(test_clouds_walking) int result; /* First step */ - cloudsSetStepSize(walker, 0.3); + cloudsWalkerSetStepSize(walker, 0.3); result = cloudsWalkerPerformStep(walker); segment = cloudsWalkerGetLastSegment(walker); ck_assert_int_eq(result, 1); + ck_assert_false(segment->refined); ck_assert_double_eq(segment->length, 0.3); ck_assert_double_eq(segment->start.distance_from_start, 0.0); ck_assert_vector_values(segment->start.location, -0.4, 0.0, 0.0); @@ -236,6 +237,7 @@ START_TEST(test_clouds_walking) result = cloudsWalkerPerformStep(walker); segment = cloudsWalkerGetLastSegment(walker); ck_assert_int_eq(result, 1); + ck_assert_false(segment->refined); ck_assert_double_eq(segment->length, 0.3); ck_assert_double_eq(segment->start.distance_from_start, 0.3); ck_assert_vector_values(segment->start.location, -0.1, 0.0, 0.0); @@ -249,14 +251,43 @@ START_TEST(test_clouds_walking) result = cloudsWalkerPerformStep(walker); segment = cloudsWalkerGetLastSegment(walker); ck_assert_int_eq(result, 1); - ck_assert_double_in_range(segment->length, 0.19, 0.21); - ck_assert_double_in_range(segment->start.distance_from_start, 0.39, 0.41); - ck_assert_double_in_range(segment->start.location.x, -0.01, 0.01); - /* TODO Check segment->start.global_density */ + ck_assert_true(segment->refined); + ck_assert_double_in_range(segment->length, 0.19, 0.20); + ck_assert_double_in_range(segment->start.distance_from_start, 0.40, 0.41); + ck_assert_double_in_range(segment->start.location.x, 0.0, 0.01); + ck_assert_double_gt(segment->start.global_density, 0.0); ck_assert_double_eq(segment->end.distance_from_start, 0.6); ck_assert_vector_values(segment->end.location, 0.2, 0.0, 0.0); ck_assert_double_gt(segment->end.global_density, 0.9); + /* Third step, change step size */ + cloudsWalkerSetStepSize(walker, 0.4); + result = cloudsWalkerPerformStep(walker); + segment = cloudsWalkerGetLastSegment(walker); + ck_assert_int_eq(result, 1); + ck_assert_false(segment->refined); + ck_assert_double_eq(segment->length, 0.4); + ck_assert_double_eq(segment->start.distance_from_start, 0.6); + ck_assert_vector_values(segment->start.location, 0.2, 0.0, 0.0); + ck_assert_double_gt(segment->start.global_density, 0.9); + ck_assert_double_eq(segment->end.distance_from_start, 1.0); + ck_assert_vector_values(segment->end.location, 0.6, 0.0, 0.0); + ck_assert_double_eq(segment->end.global_density, 0.0); + + /* Refine exit point */ + cloudsWalkerOrderRefine(walker, 0.001); + result = cloudsWalkerPerformStep(walker); + segment = cloudsWalkerGetLastSegment(walker); + ck_assert_int_eq(result, 1); + ck_assert_true(segment->refined); + ck_assert_double_in_range(segment->length, 0.3, 0.301); + ck_assert_double_eq(segment->start.distance_from_start, 0.6); + ck_assert_vector_values(segment->start.location, 0.2, 0.0, 0.0); + ck_assert_double_gt(segment->start.global_density, 0.9); + ck_assert_double_in_range(segment->end.distance_from_start, 0.9, 0.901); + ck_assert_double_in_range(segment->end.location.x, 0.5, 0.501); + ck_assert_double_lt(segment->end.global_density, 0.1); + /* Clean up */ cloudsDeleteWalker(walker); From 632ed58c717c9ffc540374377e3e7ba71f00407d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Sun, 2 Jun 2013 19:24:26 +0200 Subject: [PATCH 10/19] Added auto resize on previews Currently only available on previews handled by FreeFormHelper --- src/editing/common/freeformhelper.cpp | 40 +++++++++++++++++++++++++++ src/editing/common/freeformhelper.h | 8 ++++-- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/editing/common/freeformhelper.cpp b/src/editing/common/freeformhelper.cpp index 9ab7c67..36967fd 100644 --- a/src/editing/common/freeformhelper.cpp +++ b/src/editing/common/freeformhelper.cpp @@ -2,11 +2,16 @@ #include #include +#include +#include +#include #include +#include #include "dialogrender.h" #include "dialogexplorer.h" #include "rendering/scenery.h" #include "rendering/renderer.h" +#include "tools.h" Q_DECLARE_METATYPE(double*) @@ -24,8 +29,43 @@ FreeFormHelper::~FreeFormHelper() { } +bool FreeFormHelper::eventFilter(QObject* object, QEvent* event) +{ + if (event->type() == QEvent::Resize && object == _form_widget) + { + QSize form_size = ((QResizeEvent*) event)->size(); + QSize preview_size; + + if (form_size.width() > 1400 && form_size.height() > 900) + { + preview_size = QSize(300, 300); + } + else if (form_size.width() < 1000 || form_size.height() < 700) + { + preview_size = QSize(160, 160); + } + else + { + preview_size = QSize(220, 220); + } + + for (int i = 0; i < _previews.size(); i++) + { + if (_previews[i]->size() != preview_size) + { + _previews[i]->setMinimumSize(preview_size); + _previews[i]->setMaximumSize(preview_size); + _previews[i]->resize(preview_size); + } + } + } + return false; +} + void FreeFormHelper::startManaging() { + _form_widget->installEventFilter(this); + connect(this, SIGNAL(needLocalRefreshing()), _form_widget, SLOT(refreshFromLocalData())); connect(this, SIGNAL(needGlobalRefreshing()), _form_widget, SLOT(refreshFromFellowData())); connect(this, SIGNAL(needReverting()), _form_widget, SLOT(updateLocalDataFromScenery())); diff --git a/src/editing/common/freeformhelper.h b/src/editing/common/freeformhelper.h index c245fcb..5592d3b 100644 --- a/src/editing/common/freeformhelper.h +++ b/src/editing/common/freeformhelper.h @@ -1,11 +1,12 @@ #ifndef FREEFORMHELPER_H #define FREEFORMHELPER_H -#include -#include #include "widgetsliderdecimal.h" #include "../basepreview.h" +class QSlider; +class QPushButton; + class FreeFormHelper:public QObject { Q_OBJECT @@ -57,6 +58,9 @@ public slots: void processRenderClicked(); void processDecimalChange(double value); +protected: + bool eventFilter(QObject* object, QEvent* event); + private: QWidget* _form_widget; From b6376deecacebb4fa5d4c49cd14c48d0acd5b66c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Sun, 2 Jun 2013 21:49:48 +0200 Subject: [PATCH 11/19] clouds_walking: Restored cloud previews --- src/editing/formclouds.cpp | 27 ++++---- src/rendering/clouds/clo_lighting.c | 2 - src/rendering/clouds/clo_lighting.h | 30 --------- src/rendering/clouds/clo_preview.c | 92 +++++++++++++++++++++++++--- src/rendering/clouds/clo_preview.h | 28 +++++++++ src/rendering/clouds/clo_rendering.c | 2 +- src/rendering/clouds/public.h | 6 -- 7 files changed, 124 insertions(+), 63 deletions(-) delete mode 100644 src/rendering/clouds/clo_lighting.c delete mode 100644 src/rendering/clouds/clo_lighting.h create mode 100644 src/rendering/clouds/clo_preview.h diff --git a/src/editing/formclouds.cpp b/src/editing/formclouds.cpp index 885e73b..4a47163 100644 --- a/src/editing/formclouds.cpp +++ b/src/editing/formclouds.cpp @@ -1,5 +1,6 @@ #include "formclouds.h" +#include "rendering/clouds/clo_preview.h" #include "rendering/tools/color.h" #include "rendering/tools/euclid.h" #include "rendering/scenery.h" @@ -12,24 +13,22 @@ class PreviewCloudsCoverage:public BasePreview public: PreviewCloudsCoverage(QWidget* parent, CloudsLayerDefinition* layer):BasePreview(parent) { - _renderer = cloudsCreatePreviewCoverageRenderer(); + _renderer = cloudsPreviewCoverageCreateRenderer(); _3d = true; _original_layer = layer; - _preview_definition = (CloudsDefinition*)CloudsDefinitionClass.create(); addToggle("3d", tr("Perspective"), true); configScaling(100.0, 1000.0, 20.0, 200.0); } ~PreviewCloudsCoverage() { - CloudsDefinitionClass.destroy(_preview_definition); rendererDelete(_renderer); } protected: Color getColor(double x, double y) { - return cloudsGetPreviewCoverage(_renderer, x, y, scaling, _3d); + return cloudsPreviewCoverageGetPixel(_renderer, x, y, scaling, _3d); } virtual void toggleChangeEvent(QString key, bool value) { @@ -41,15 +40,12 @@ protected: } void updateData() { - layersDeleteLayer(_preview_definition->layers, 0); - layersAddLayer(_preview_definition->layers, _original_layer); - CloudsRendererClass.bind(_renderer, _preview_definition); + cloudsPreviewCoverageBindLayer(_renderer, _original_layer); } private: Renderer* _renderer; CloudsLayerDefinition* _original_layer; - CloudsDefinition* _preview_definition; bool _3d; }; @@ -59,27 +55,28 @@ public: PreviewCloudsColor(QWidget* parent, CloudsLayerDefinition* layer):BasePreview(parent) { _original_layer = layer; - _preview_definition = (CloudsDefinition*)CloudsDefinitionClass.create(); - _renderer = cloudsCreatePreviewColorRenderer(); + _renderer = cloudsPreviewMaterialCreateRenderer(); configScaling(0.5, 2.0, 0.1, 2.0); } + + ~PreviewCloudsColor() + { + rendererDelete(_renderer); + } protected: Color getColor(double x, double y) { - return cloudsGetPreviewColor(_renderer, x, y); + return cloudsPreviewMaterialGetPixel(_renderer, x, y); } void updateData() { - layersDeleteLayer(_preview_definition->layers, 0); - layersAddLayer(_preview_definition->layers, _original_layer); - CloudsRendererClass.bind(_renderer, _preview_definition); + cloudsPreviewMaterialBindLayer(_renderer, _original_layer); } private: Renderer* _renderer; CloudsLayerDefinition* _original_layer; - CloudsDefinition* _preview_definition; }; /**************** Form ****************/ diff --git a/src/rendering/clouds/clo_lighting.c b/src/rendering/clouds/clo_lighting.c deleted file mode 100644 index 3576b55..0000000 --- a/src/rendering/clouds/clo_lighting.c +++ /dev/null @@ -1,2 +0,0 @@ -#include "clo_lighting.h" - diff --git a/src/rendering/clouds/clo_lighting.h b/src/rendering/clouds/clo_lighting.h deleted file mode 100644 index 6c5cd1c..0000000 --- a/src/rendering/clouds/clo_lighting.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef _PAYSAGES_CLOUDS_LIGHTING_H_ -#define _PAYSAGES_CLOUDS_LIGHTING_H_ - -#include "public.h" -#include "../tools/euclid.h" - -/** - * Cloud lighting helpers. - */ - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* - * Bind fake lighting functions to a renderer. - */ -void cloudsBindFakeLightingToRenderer(CloudsRenderer* renderer); - -/* - * Bind real lighting functions to a renderer. - */ -void cloudsBindRealLightingToRenderer(CloudsRenderer* renderer); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/rendering/clouds/clo_preview.c b/src/rendering/clouds/clo_preview.c index df39f87..5a0afa6 100644 --- a/src/rendering/clouds/clo_preview.c +++ b/src/rendering/clouds/clo_preview.c @@ -18,7 +18,7 @@ Color _fakeApplyLightingToSurface(Renderer* renderer, Vector3 location, Vector3 return COLOR_WHITE; } -Renderer* cloudsCreatePreviewCoverageRenderer() +Renderer* cloudsPreviewCoverageCreateRenderer() { Renderer* result = rendererCreate(); result->render_quality = 5; @@ -26,7 +26,15 @@ Renderer* cloudsCreatePreviewCoverageRenderer() return result; } -Color cloudsGetPreviewCoverage(Renderer* renderer, double x, double y, double scaling, int perspective) +void cloudsPreviewCoverageBindLayer(Renderer* renderer, CloudsLayerDefinition* layer) +{ + CloudsDefinition* definition = (CloudsDefinition*)CloudsDefinitionClass.create(); + layersAddLayer(definition->layers, layer); + CloudsRendererClass.bind(renderer, definition); + CloudsDefinitionClass.destroy(definition); +} + +Color cloudsPreviewCoverageGetPixel(Renderer* renderer, double x, double y, double scaling, int perspective) { if (perspective) { @@ -55,25 +63,91 @@ Color cloudsGetPreviewCoverage(Renderer* renderer, double x, double y, double sc } } -Renderer* cloudsCreatePreviewColorRenderer() +static void _getLightingStatus(Renderer* renderer, LightStatus* status, Vector3 normal, int opaque) +{ + LightDefinition light; + + UNUSED(renderer); + UNUSED(normal); + UNUSED(opaque); + + light.color.r = 1.0; + light.color.g = 1.0; + light.color.b = 1.0; + light.direction.x = -1.0; + light.direction.y = -0.5; + light.direction.z = 1.0; + light.direction = v3Normalize(light.direction); + light.altered = 1; + light.reflection = 0.0; + lightingPushLight(status, &light); + + light.color.r = 0.2; + light.color.g = 0.2; + light.color.b = 0.2; + light.direction.x = 1.0; + light.direction.y = -0.5; + light.direction.z = -1.0; + light.direction = v3Normalize(light.direction); + light.altered = 0; + light.reflection = 0.0; + lightingPushLight(status, &light); +} + +Renderer* cloudsPreviewMaterialCreateRenderer() { Renderer* result = rendererCreate(); result->render_quality = 8; + result->atmosphere->getLightingStatus = _getLightingStatus; return result; } -Color cloudsGetPreviewColor(Renderer* renderer, double x, double y) +static double _getDensity(Renderer* renderer, CloudsLayerDefinition* layer, Vector3 location) +{ + UNUSED(renderer); + UNUSED(layer); + + double distance = v3Norm(location); + if (distance > 1.0) + { + return 0.0; + } + else if (distance < 0.8) + { + return 1.0; + } + else + { + return (1.0 - distance) / 0.2; + } +} + +void cloudsPreviewMaterialBindLayer(Renderer* renderer, CloudsLayerDefinition* layer) +{ + CloudsDefinition* definition = (CloudsDefinition*)CloudsDefinitionClass.create(); + layersAddLayer(definition->layers, layer); + CloudsRendererClass.bind(renderer, definition); + CloudsDefinitionClass.destroy(definition); + + layer = layersGetLayer(renderer->clouds->definition->layers, 0); + layer->lower_altitude = -1.0; + layer->thickness = 2.0; + + renderer->clouds->getLayerDensity = _getDensity; +} + +Color cloudsPreviewMaterialGetPixel(Renderer* renderer, double x, double y) { Vector3 start, end; - double thickness = 0.5; + double thickness = 2.0; start.x = x * thickness * 0.5; - start.y = -y * thickness * 0.5; - start.z = thickness * 0.5; + start.z = y * thickness * 0.5; + start.y = thickness * 0.5; end.x = start.x; - end.y = start.y; - end.z = -start.z; + end.z = start.z; + end.y = -start.y; return renderer->clouds->getColor(renderer, COLOR_BLUE, start, end); } diff --git a/src/rendering/clouds/clo_preview.h b/src/rendering/clouds/clo_preview.h new file mode 100644 index 0000000..c1bfe35 --- /dev/null +++ b/src/rendering/clouds/clo_preview.h @@ -0,0 +1,28 @@ +#ifndef _PAYSAGES_CLOUDS_PREVIEW_H_ +#define _PAYSAGES_CLOUDS_PREVIEW_H_ + +#include "public.h" +#include "../tools/euclid.h" + +/** + * Cloud preview helpers. + */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +Renderer* cloudsPreviewCoverageCreateRenderer(); +void cloudsPreviewCoverageBindLayer(Renderer* renderer, CloudsLayerDefinition* layer); +Color cloudsPreviewCoverageGetPixel(Renderer* renderer, double x, double y, double scaling, int perspective); + +Renderer* cloudsPreviewMaterialCreateRenderer(); +void cloudsPreviewMaterialBindLayer(Renderer* renderer, CloudsLayerDefinition* layer); +Color cloudsPreviewMaterialGetPixel(Renderer* renderer, double x, double y); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/rendering/clouds/clo_rendering.c b/src/rendering/clouds/clo_rendering.c index 62a7984..1d6abd4 100644 --- a/src/rendering/clouds/clo_rendering.c +++ b/src/rendering/clouds/clo_rendering.c @@ -185,7 +185,7 @@ static Color _getColor(Renderer* renderer, Color base, Vector3 start, Vector3 en /* Apply aerial perspective approximation */ /* TODO This should be done at cloud entry */ - base = renderer->applyMediumTraversal(renderer, ostart, base); + base = renderer->atmosphere->applyAerialPerspective(renderer, ostart, base).final; } } diff --git a/src/rendering/clouds/public.h b/src/rendering/clouds/public.h index beded50..283ac27 100644 --- a/src/rendering/clouds/public.h +++ b/src/rendering/clouds/public.h @@ -80,12 +80,6 @@ LayerType cloudsGetLayerType(); void cloudsAutoPreset(CloudsDefinition* definition, CloudsPreset preset); void cloudsLayerAutoPreset(CloudsLayerDefinition* definition, CloudsLayerPreset preset); -Renderer* cloudsCreatePreviewCoverageRenderer(); -Color cloudsGetPreviewCoverage(Renderer* renderer, double x, double y, double scaling, int perspective); - -Renderer* cloudsCreatePreviewColorRenderer(); -Color cloudsGetPreviewColor(Renderer* renderer, double x, double y); - #ifdef __cplusplus } #endif From 41cc8787ac4e30ca072192b7388bf3ba2a4ec79a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Mon, 3 Jun 2013 21:51:01 +0200 Subject: [PATCH 12/19] Added sun inflation near horizon --- src/rendering/atmosphere/atm_bruneton.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/rendering/atmosphere/atm_bruneton.c b/src/rendering/atmosphere/atm_bruneton.c index 64f93ab..1549948 100644 --- a/src/rendering/atmosphere/atm_bruneton.c +++ b/src/rendering/atmosphere/atm_bruneton.c @@ -922,6 +922,8 @@ static Color _getInscatterColor(Vector3* _x, double* _t, Vector3 v, Vector3 s, d static Color _sunColor(Vector3 v, Vector3 s, double r, double mu, double radius) { Color transmittance = r <= Rt ? _transmittanceWithShadow(r, mu) : COLOR_WHITE; /* T(x,xo) */ + double d = _limit(r, mu); + radius *= (1.0 + 10.0 * d / Rt); /* Inflating due to lens effect near horizon */ double isun = step(cos(radius * M_PI / 180.0), v3Dot(v, s)) * ISun; /* Lsun */ transmittance.r *= isun; transmittance.g *= isun; From eb837ef3bd2e7460e6f2f4e6b42a526bb67a2ba3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Mon, 3 Jun 2013 22:03:52 +0200 Subject: [PATCH 13/19] Fixed terrain painting unwanted scrolling on show --- src/editing/paysages-qt.pro | 4 ++-- src/editing/terrain/dialogterrainpainting.ui | 2 +- src/editing/{ => terrain}/widgetheightmap.cpp | 4 ++-- src/editing/{ => terrain}/widgetheightmap.h | 0 4 files changed, 5 insertions(+), 5 deletions(-) rename src/editing/{ => terrain}/widgetheightmap.cpp (99%) rename src/editing/{ => terrain}/widgetheightmap.h (100%) diff --git a/src/editing/paysages-qt.pro b/src/editing/paysages-qt.pro index 290b851..454542f 100644 --- a/src/editing/paysages-qt.pro +++ b/src/editing/paysages-qt.pro @@ -24,7 +24,7 @@ win32:LIBS += ../libpaysages.a ../libpaysages_exploring.a -lDevIL -lILU -lILUT - TRANSLATIONS = $$PROJECT_PATH/data/i18n/paysages_fr.ts HEADERS += \ - widgetheightmap.h \ + terrain/widgetheightmap.h \ widgetexplorer.h \ widgetcurveeditor.h \ tools.h \ @@ -73,7 +73,7 @@ HEADERS += \ common/previewrenderer.h SOURCES += \ - widgetheightmap.cpp \ + terrain/widgetheightmap.cpp \ widgetexplorer.cpp \ widgetcurveeditor.cpp \ tools.cpp \ diff --git a/src/editing/terrain/dialogterrainpainting.ui b/src/editing/terrain/dialogterrainpainting.ui index 72d405f..fb7a98c 100644 --- a/src/editing/terrain/dialogterrainpainting.ui +++ b/src/editing/terrain/dialogterrainpainting.ui @@ -789,7 +789,7 @@ WidgetHeightMap QWidget -
widgetheightmap.h
+
terrain/widgetheightmap.h
1 heightmapChanged() diff --git a/src/editing/widgetheightmap.cpp b/src/editing/terrain/widgetheightmap.cpp similarity index 99% rename from src/editing/widgetheightmap.cpp rename to src/editing/terrain/widgetheightmap.cpp index cd13d71..f6cde1e 100644 --- a/src/editing/widgetheightmap.cpp +++ b/src/editing/terrain/widgetheightmap.cpp @@ -35,8 +35,8 @@ QGLWidget(parent) _average_frame_time = 0.0; _last_brush_action = 0; - _last_mouse_x = 0; - _last_mouse_y = 0; + _last_mouse_x = 250; + _last_mouse_y = 250; _last_time = QDateTime::currentDateTime(); _mouse_moved = false; diff --git a/src/editing/widgetheightmap.h b/src/editing/terrain/widgetheightmap.h similarity index 100% rename from src/editing/widgetheightmap.h rename to src/editing/terrain/widgetheightmap.h From f3ddf1917f97b484b137a9f91bc8363d1a459784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Sun, 9 Jun 2013 14:07:45 +0200 Subject: [PATCH 14/19] Added data system to detect if run in good path --- src/rendering/main.c | 7 +++++++ src/rendering/tools/data.c | 34 ++++++++++++++++++++++++++++++++++ src/rendering/tools/data.h | 10 ++++++++++ 3 files changed, 51 insertions(+) create mode 100644 src/rendering/tools/data.c create mode 100644 src/rendering/tools/data.h diff --git a/src/rendering/main.c b/src/rendering/main.c index 970e351..3006430 100644 --- a/src/rendering/main.c +++ b/src/rendering/main.c @@ -2,6 +2,7 @@ #include #include "auto.h" +#include "tools/data.h" #include "system.h" #include "scenery.h" #include "render.h" @@ -13,6 +14,12 @@ void paysagesInit() { systemInit(); + if (!dataInit()) + { + /* TODO Add error callback (for interface) */ + fprintf(stderr, "ERROR : Can't locate data files.\n"); + exit(1); + } openclInit(); sceneryInit(); diff --git a/src/rendering/tools/data.c b/src/rendering/tools/data.c new file mode 100644 index 0000000..859abe7 --- /dev/null +++ b/src/rendering/tools/data.c @@ -0,0 +1,34 @@ +#include "data.h" + +#include +#include +#include + +static const char* _datapath = NULL; + +static int _tryDataPath(const char* path) +{ + char* buffer; + + buffer = malloc(sizeof (char) * (strlen(path) + 30)); + strcpy(buffer, path); + strcat(buffer, "/.paysages_data"); + + FILE* f = fopen(buffer, "r"); + free(buffer); + if (f) + { + _datapath = path; + fclose(f); + return 1; + } + else + { + return 0; + } +} + +int dataInit() +{ + return _tryDataPath("./data"); +} diff --git a/src/rendering/tools/data.h b/src/rendering/tools/data.h new file mode 100644 index 0000000..f5c77b1 --- /dev/null +++ b/src/rendering/tools/data.h @@ -0,0 +1,10 @@ +#ifndef _PAYSAGES_TOOLS_DATA_H_ +#define _PAYSAGES_TOOLS_DATA_H_ + +/* + * Data directory management. + */ + +int dataInit(); + +#endif From 701faf6ece43ca24934e2b3ea8d8f591ea0cd746 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Sun, 9 Jun 2013 14:56:45 +0200 Subject: [PATCH 15/19] Fixed noise range and normalization (with unit testing) --- src/rendering/noise.c | 17 +++------ src/testing/main.c | 2 ++ src/testing/test_noise.c | 78 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 13 deletions(-) create mode 100644 src/testing/test_noise.c diff --git a/src/rendering/noise.c b/src/rendering/noise.c index 5525cc9..60b652f 100644 --- a/src/rendering/noise.c +++ b/src/rendering/noise.c @@ -202,17 +202,8 @@ void noiseValidate(NoiseGenerator* generator) generator->_max_value = generator->height_offset; for (x = 0; x < generator->level_count; x++) { - double min_value = generator->levels[x].minvalue; - double max_value = min_value + generator->levels[x].amplitude; - - if (min_value < generator->_min_value) - { - generator->_min_value = min_value; - } - if (max_value > generator->_max_value) - { - generator->_max_value = max_value; - } + generator->_min_value += generator->levels[x].minvalue; + generator->_max_value += generator->levels[x].minvalue + generator->levels[x].amplitude; } } @@ -394,14 +385,14 @@ void noiseNormalizeAmplitude(NoiseGenerator* generator, double minvalue, double for (level = 0; level < generator->level_count; level++) { - generator->levels[level].minvalue = minvalue + (generator->levels[level].minvalue - current_minvalue) * factor; + generator->levels[level].minvalue *= factor; generator->levels[level].amplitude *= factor; if (adjust_scaling) { generator->levels[level].wavelength *= factor; } } - /*generator->height_offset = minvalue + (generator->height_offset - current_minvalue) * factor;*/ + generator->height_offset = minvalue + (generator->height_offset - current_minvalue) * factor; noiseValidate(generator); } diff --git a/src/testing/main.c b/src/testing/main.c index d66edc4..78b74d9 100644 --- a/src/testing/main.c +++ b/src/testing/main.c @@ -6,6 +6,7 @@ extern void test_euclid_case(Suite* s); extern void test_camera_case(Suite* s); extern void test_clouds_case(Suite* s); +extern void test_noise_case(Suite* s); int main(int argc, char** argv) { @@ -18,6 +19,7 @@ int main(int argc, char** argv) test_euclid_case(s); test_camera_case(s); test_clouds_case(s); + test_noise_case(s); SRunner *sr = srunner_create(s); srunner_run_all(sr, CK_NORMAL); diff --git a/src/testing/test_noise.c b/src/testing/test_noise.c new file mode 100644 index 0000000..5ab413e --- /dev/null +++ b/src/testing/test_noise.c @@ -0,0 +1,78 @@ +#include "testing/common.h" + +#include "rendering/noise.h" + +START_TEST(test_noise_range) +{ + NoiseGenerator* noise; + double minvalue, maxvalue; + + noise = noiseCreateGenerator(); + + noiseAddLevelSimple(noise, 0.1, -1.0, 1.0); + noiseAddLevelSimple(noise, 0.2, -0.5, 0.2); + noiseAddLevelSimple(noise, 0.4, -0.3, 1.2); + noiseValidate(noise); + noiseGetRange(noise, &minvalue, &maxvalue); + + ck_assert_double_eq(minvalue, -1.8); + ck_assert_double_eq(maxvalue, 2.4); +} +END_TEST + +START_TEST(test_noise_normalize) +{ + int x; + NoiseGenerator* noise; + + noise = noiseCreateGenerator(); + + /* Symmetric case */ + noiseAddLevelsSimple(noise, 10, 1.0, -4.0, 4.0, 0.5); + noiseValidate(noise); + noiseNormalizeAmplitude(noise, -1.0, 1.0, 0); + for (x = 0; x < 1000; x++) + { + double value = noiseGet1DTotal(noise, 0.01 * (double)x); + ck_assert_double_in_range(value, -1.0, 1.0); + } + + /* Target center differs from current center */ + noiseClearLevels(noise); + noiseAddLevelsSimple(noise, 10, 1.0, -5.0, 5.0, 0.5); + noiseValidate(noise); + noiseNormalizeAmplitude(noise, 0.0, 1.0, 0); + for (x = 0; x < 1000; x++) + { + double value = noiseGet1DTotal(noise, 0.01 * (double)x); + ck_assert_double_in_range(value, 0.0, 1.0); + } + + /* Asymmetric range */ + noiseClearLevels(noise); + noiseAddLevelsSimple(noise, 10, 1.0, 0.0, 10.0, 0.0); + noiseValidate(noise); + noiseNormalizeAmplitude(noise, 0.0, 1.0, 0); + for (x = 0; x < 1000; x++) + { + double value = noiseGet1DTotal(noise, 0.01 * (double)x); + ck_assert_double_in_range(value, 0.0, 1.0); + } + + /* Complex asymmetric case */ + noiseClearLevels(noise); + noiseAddLevelsSimple(noise, 3, 1.0, -2.0, 8.0, 0.3); + noiseValidate(noise); + noiseNormalizeAmplitude(noise, -2.0, 4.0, 0.0); + for (x = 0; x < 1000; x++) + { + double value = noiseGet1DTotal(noise, 0.01 * (double)x); + ck_assert_double_in_range(value, -2.0, 4.0); + } + + noiseDeleteGenerator(noise); +} +END_TEST + +TEST_CASE(noise, test_noise_range, test_noise_normalize) + From 06764427a64b4f28a3f584fd03f14ce326821ab2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Sun, 9 Jun 2013 15:11:03 +0200 Subject: [PATCH 16/19] Adapt to previous noise normalization fix --- src/editing/terrain/mainterrainform.cpp | 2 +- src/rendering/clouds/clo_definition.c | 2 +- src/rendering/terrain/ter_definition.c | 4 ++-- src/rendering/terrain/ter_presets.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/editing/terrain/mainterrainform.cpp b/src/editing/terrain/mainterrainform.cpp index 04ad6c7..71c3c08 100644 --- a/src/editing/terrain/mainterrainform.cpp +++ b/src/editing/terrain/mainterrainform.cpp @@ -20,7 +20,7 @@ MainTerrainForm::MainTerrainForm(QWidget *parent) : _form_helper->addPreview(ui->preview_shape, _renderer_shape); _form_helper->addDoubleInputSlider(ui->input_scaling, &_terrain->scaling, 0.1, 3.0, 0.03, 0.3); - _form_helper->addDoubleInputSlider(ui->input_height, &_terrain->height, 1.0, 45.0, 0.3, 3.0); + _form_helper->addDoubleInputSlider(ui->input_height, &_terrain->height, 1.0, 90.0, 0.5, 5.0); _form_helper->addDoubleInputSlider(ui->input_shadow_smoothing, &_terrain->shadow_smoothing, 0.0, 0.3, 0.003, 0.03); _form_helper->addDoubleInputSlider(ui->input_water_height, &_terrain->water_height, -2.0, 2.0, 0.01, 0.1); diff --git a/src/rendering/clouds/clo_definition.c b/src/rendering/clouds/clo_definition.c index 1bdf822..845c3d9 100644 --- a/src/rendering/clouds/clo_definition.c +++ b/src/rendering/clouds/clo_definition.c @@ -112,7 +112,7 @@ void cloudsLayerValidateDefinition(CloudsLayerDefinition* definition) break; } - noiseNormalizeAmplitude(definition->_coverage_noise, 0.0, 1.0, 0); + noiseNormalizeAmplitude(definition->_coverage_noise, -1.0, 3.0, 0); noiseNormalizeAmplitude(definition->_shape_noise, -0.5, 0.5, 0); } diff --git a/src/rendering/terrain/ter_definition.c b/src/rendering/terrain/ter_definition.c index b61c74a..be387c2 100644 --- a/src/rendering/terrain/ter_definition.c +++ b/src/rendering/terrain/ter_definition.c @@ -27,13 +27,13 @@ static TerrainDefinition* _createDefinition() { TerrainDefinition* definition = malloc(sizeof(TerrainDefinition)); - definition->height = 0.0; + definition->height = 1.0; definition->scaling = 1.0; definition->shadow_smoothing = 0.0; definition->height_map = terrainHeightMapCreate(definition); - definition->water_height = -0.8; + definition->water_height = -0.3; definition->_height_noise = noiseCreateGenerator(); diff --git a/src/rendering/terrain/ter_presets.c b/src/rendering/terrain/ter_presets.c index e7236c0..4fd52e0 100644 --- a/src/rendering/terrain/ter_presets.c +++ b/src/rendering/terrain/ter_presets.c @@ -19,7 +19,7 @@ void terrainAutoPreset(TerrainDefinition* definition, TerrainPreset preset) noiseNormalizeAmplitude(definition->_height_noise, -1.0, 1.0, 0); noiseSetFunctionParams(definition->_height_noise, NOISE_FUNCTION_SIMPLEX, 0.0, 0.0); definition->scaling = 1.0; - definition->height = 15.0; + definition->height = 30.0; definition->shadow_smoothing = 0.03; break; default: From d60a169751da1ea435c842ea338c6ad0e2942ee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Sun, 9 Jun 2013 18:08:01 +0200 Subject: [PATCH 17/19] Added terrain base noise preview + main window refactoring --- data/ui_pictures.qrc | 9 + src/editing/{ => common}/mainwindow.cpp | 82 +-- src/editing/{ => common}/mainwindow.h | 24 +- src/editing/common/mainwindow.ui | 557 ++++++++++++++++++ src/editing/formrender.h | 6 +- src/editing/paysages-qt.pro | 13 +- src/editing/terrain/mainterrainform.cpp | 4 +- src/editing/terrain/mainterrainform.ui | 8 +- src/editing/terrain/previewterrainshape.cpp | 12 +- src/editing/terrain/previewterrainshape.h | 3 + .../terrain/widgetterrainbasenoisepreview.cpp | 45 ++ .../terrain/widgetterrainbasenoisepreview.h | 26 + 12 files changed, 732 insertions(+), 57 deletions(-) rename src/editing/{ => common}/mainwindow.cpp (76%) rename src/editing/{ => common}/mainwindow.h (72%) create mode 100644 src/editing/common/mainwindow.ui create mode 100644 src/editing/terrain/widgetterrainbasenoisepreview.cpp create mode 100644 src/editing/terrain/widgetterrainbasenoisepreview.h diff --git a/data/ui_pictures.qrc b/data/ui_pictures.qrc index b16e299..a3fa8d0 100644 --- a/data/ui_pictures.qrc +++ b/data/ui_pictures.qrc @@ -6,6 +6,9 @@ images/explore.png images/render.png images/about.png + images/load.png + images/new.png + images/save.png images/tab_atmosphere.png @@ -15,4 +18,10 @@ images/tab_textures.png images/tab_water.png + + images/logo_16.png + images/logo_32.png + images/logo_64.png + images/logo_256.png + diff --git a/src/editing/mainwindow.cpp b/src/editing/common/mainwindow.cpp similarity index 76% rename from src/editing/mainwindow.cpp rename to src/editing/common/mainwindow.cpp index b568c73..f80e078 100644 --- a/src/editing/mainwindow.cpp +++ b/src/editing/common/mainwindow.cpp @@ -1,10 +1,10 @@ #include "mainwindow.h" +#include "ui_mainwindow.h" #include #include #include #include -#include #include #include #include @@ -63,7 +63,7 @@ int main(int argc, char** argv) BasePreview::initDrawers(); window = new MainWindow(); - window->show(); + window->showMaximized(); splash->finish(window); delete splash; @@ -79,68 +79,59 @@ int main(int argc, char** argv) } MainWindow::MainWindow(QWidget *parent) : -QMainWindow(parent) + QMainWindow(parent), + ui(new Ui::MainWindow) { + ui->setupUi(this); + BaseForm* form; - QTabWidget* tabs; - QToolBar* toolbar; - tabs = new QTabWidget(this); - tabs->setIconSize(QSize(32, 32)); + connect(ui->action_explore, SIGNAL(triggered()), this, SLOT(explore3D())); + connect(ui->action_quick_render, SIGNAL(triggered()), this, SLOT(quickPreview())); + connect(ui->action_final_render, SIGNAL(triggered()), this, SLOT(finalRender())); + connect(ui->action_file_new, SIGNAL(triggered()), this, SLOT(fileNew())); + connect(ui->action_file_save, SIGNAL(triggered()), this, SLOT(fileSave())); + connect(ui->action_file_load, SIGNAL(triggered()), this, SLOT(fileLoad())); + connect(ui->action_about, SIGNAL(triggered()), this, SLOT(showAboutDialog())); - tabs->addTab(new MainTerrainForm(tabs), QIcon(getDataPath("images/tab_terrain.png")), tr("Landscape shape")); - - form = new FormTextures(tabs); - tabs->addTab(form, QIcon(getDataPath("images/tab_textures.png")), tr("Textures")); + form = new FormTextures(ui->tabs); + ui->tabs->addTab(form, QIcon(getDataPath("images/tab_textures.png")), tr("Textures")); QObject::connect(form, SIGNAL(configApplied()), this, SLOT(refreshAll()), Qt::QueuedConnection); _forms.append(form); - form = new FormWater(tabs); - tabs->addTab(form, QIcon(getDataPath("images/tab_water.png")), tr("Water")); + form = new FormWater(ui->tabs); + ui->tabs->addTab(form, QIcon(getDataPath("images/tab_water.png")), tr("Water")); QObject::connect(form, SIGNAL(configApplied()), this, SLOT(refreshAll()), Qt::QueuedConnection); _forms.append(form); - form = new FormAtmosphere(tabs); - tabs->addTab(form, QIcon(getDataPath("images/tab_atmosphere.png")), tr("Atmosphere")); + form = new FormAtmosphere(ui->tabs); + ui->tabs->addTab(form, QIcon(getDataPath("images/tab_atmosphere.png")), tr("Atmosphere")); QObject::connect(form, SIGNAL(configApplied()), this, SLOT(refreshAll()), Qt::QueuedConnection); _forms.append(form); - form = new FormClouds(tabs); - tabs->addTab(form, QIcon(getDataPath("images/tab_clouds.png")), tr("Clouds")); + form = new FormClouds(ui->tabs); + ui->tabs->addTab(form, QIcon(getDataPath("images/tab_clouds.png")), tr("Clouds")); QObject::connect(form, SIGNAL(configApplied()), this, SLOT(refreshAll()), Qt::QueuedConnection); _forms.append(form); - _form_render = new FormRender(tabs); - tabs->addTab(_form_render, QIcon(getDataPath("images/tab_render.png")), tr("Render")); + _form_render = new FormRender(ui->tabs); + ui->tabs->addTab(_form_render, QIcon(getDataPath("images/tab_render.png")), tr("Render")); _forms.append(_form_render); - toolbar = new QToolBar(this); - toolbar->setOrientation(Qt::Vertical); - toolbar->setAllowedAreas(Qt::LeftToolBarArea); - toolbar->setMovable(false); - toolbar->setFloatable(false); - toolbar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); - toolbar->toggleViewAction()->setEnabled(false); - toolbar->setIconSize(QSize(32, 32)); - addToolBar(Qt::LeftToolBarArea, toolbar); - - toolbar->addAction(QIcon(getDataPath("images/new.png")), tr("&New"), this, SLOT(fileNew()))->setShortcut(QKeySequence(tr("Crtl+N"))); - toolbar->addAction(QIcon(getDataPath("images/save.png")), tr("&Save"), this, SLOT(fileSave()))->setShortcut(QKeySequence(tr("Crtl+S"))); - toolbar->addAction(QIcon(getDataPath("images/load.png")), tr("&Load"), this, SLOT(fileLoad()))->setShortcut(QKeySequence(tr("Crtl+L"))); - toolbar->addAction(QIcon(getDataPath("images/explore.png")), tr("&Explore (F2)"), this, SLOT(explore3D()))->setShortcut(QKeySequence(tr("F2"))); - toolbar->addAction(QIcon(getDataPath("images/render.png")), tr("&Quick\nrender (F5)"), this, SLOT(quickPreview()))->setShortcut(QKeySequence(tr("F5"))); - toolbar->addAction(QIcon(getDataPath("images/about.png")), tr("&About"), this, SLOT(showAboutDialog())); - - setCentralWidget(tabs); - - setWindowTitle("Paysages 3D"); - setWindowIcon(QIcon(getDataPath("images/logo_32.png"))); + // TODO Decide this according to platform / screen size + ui->toolBar->hide(); + ui->menuBar->hide(); scenerySetCustomDataCallback(MainWindow::guiSaveCallback, MainWindow::guiLoadCallback, this); refreshAll(); } +MainWindow::~MainWindow() +{ + delete ui; +} + bool MainWindow::event(QEvent* event) { if (event->type() == QEvent::WindowActivate) @@ -160,6 +151,7 @@ void MainWindow::refreshAll() { _forms[i]->revertConfig(); } + // TODO Refresh free forms // Refresh preview OSD CameraDefinition* camera = cameraCreateDefinition(); @@ -244,6 +236,16 @@ void MainWindow::quickPreview() _form_render->startQuickRender(); } +void MainWindow::finalRender() +{ + _form_render->startRender(); +} + +void MainWindow::showLastRender() +{ + _form_render->showRender(); +} + void MainWindow::explore3D() { CameraDefinition* camera; diff --git a/src/editing/mainwindow.h b/src/editing/common/mainwindow.h similarity index 72% rename from src/editing/mainwindow.h rename to src/editing/common/mainwindow.h index 0a00ae8..64b73de 100644 --- a/src/editing/mainwindow.h +++ b/src/editing/common/mainwindow.h @@ -1,16 +1,25 @@ -#ifndef _PAYSAGES_QT_MAINWINDOW_H_ -#define _PAYSAGES_QT_MAINWINDOW_H_ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H #include -#include "formrender.h" +#include #include "rendering/tools/pack.h" +class BaseForm; +class FormRender; + +namespace Ui { +class MainWindow; +} + class MainWindow : public QMainWindow { Q_OBJECT - + public: explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + virtual bool event(QEvent* event); static void guiSaveCallback(PackStream* stream, void* data); @@ -26,9 +35,14 @@ public slots: void showAboutDialog(); void quickPreview(); + void finalRender(); + void showLastRender(); + void explore3D(); private: + Ui::MainWindow *ui; + void guiSave(PackStream* stream); void guiLoad(PackStream* stream); @@ -36,4 +50,4 @@ private: FormRender* _form_render; }; -#endif +#endif // MAINWINDOW_H diff --git a/src/editing/common/mainwindow.ui b/src/editing/common/mainwindow.ui new file mode 100644 index 0000000..720f880 --- /dev/null +++ b/src/editing/common/mainwindow.ui @@ -0,0 +1,557 @@ + + + MainWindow + + + + 0 + 0 + 946 + 651 + + + + Paysages 3D + + + + :/logo/images/logo_32.png:/logo/images/logo_32.png + + + + + + + + + + <html><head/><body><p><span style=" font-size:14pt; font-weight:600;">Paysages 3D</span></p><p><img src=":/logo/images/logo_32.png"/></p></body></html> + + + Qt::RichText + + + Qt::AlignCenter + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Preview + + + true + + + + + + + 3D + + + + + + + Top + + + + + + + + + QFrame::Panel + + + QFrame::Raised + + + 3 + + + + 0 + + + QLayout::SetMinimumSize + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 200 + 150 + + + + + 400 + 300 + + + + + + widget + widget + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Actions + + + + + + Explore in 3D + + + + :/buttons/logo/images/explore.png:/buttons/logo/images/explore.png + + + F2 + + + + + + + Render + + + + :/buttons/logo/images/render.png:/buttons/logo/images/render.png + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + File + + + + + + New + + + + :/buttons/logo/images/new.png:/buttons/logo/images/new.png + + + + + + + Save + + + + :/buttons/logo/images/save.png:/buttons/logo/images/save.png + + + + + + + Load + + + + :/buttons/logo/images/load.png:/buttons/logo/images/load.png + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + 0 + + + + 32 + 32 + + + + + + :/tabs/images/tab_terrain.png:/tabs/images/tab_terrain.png + + + Lanscape shape + + + + + + + + + toolBar + + + false + + + Qt::LeftToolBarArea + + + + 32 + 32 + + + + Qt::ToolButtonTextUnderIcon + + + false + + + LeftToolBarArea + + + false + + + + + + + + + + + + 0 + 0 + 946 + 25 + + + + + File + + + + + + + + Actions + + + + + + + + + Help + + + + + + + + + + + :/buttons/logo/images/explore.png:/buttons/logo/images/explore.png + + + Explore in 3D + + + Start exploring your scenery in real-time 3D + + + F2 + + + + + + :/buttons/logo/images/new.png:/buttons/logo/images/new.png + + + New scene + + + Create a virgin scene + + + Ctrl+N + + + + + + :/buttons/logo/images/load.png:/buttons/logo/images/load.png + + + Load scene + + + Load a scenery from a file + + + Ctrl+O + + + + + + :/buttons/logo/images/save.png:/buttons/logo/images/save.png + + + Save scene + + + Save a scenery to a file + + + Ctrl+S + + + + + + :/buttons/logo/images/render.png:/buttons/logo/images/render.png + + + Quick render + + + Start a quick render + + + F5 + + + + + + :/buttons/logo/images/render.png:/buttons/logo/images/render.png + + + Final render + + + Start the final rendering processs + + + Ctrl+F5 + + + + + + :/buttons/logo/images/about.png:/buttons/logo/images/about.png + + + About + + + Display information on this software + + + F1 + + + + + + :/buttons/logo/images/render.png:/buttons/logo/images/render.png + + + Show last render + + + Display the last render done + + + F6 + + + + + + MainTerrainForm + QWidget +
terrain/mainterrainform.h
+ 1 +
+
+ + + + + + button_explore + clicked() + action_explore + trigger() + + + 127 + 380 + + + -1 + -1 + + + + + button_render + clicked() + action_final_render + trigger() + + + 213 + 425 + + + 213 + 425 + + + + + button_file_new + clicked() + action_file_new + trigger() + + + 213 + 522 + + + -1 + -1 + + + + + button_file_load + clicked() + action_file_load + trigger() + + + 213 + 588 + + + -1 + -1 + + + + + button_file_save + clicked() + action_file_save + trigger() + + + 213 + 555 + + + -1 + -1 + + + + +
diff --git a/src/editing/formrender.h b/src/editing/formrender.h index c7629ea..d0b18e6 100644 --- a/src/editing/formrender.h +++ b/src/editing/formrender.h @@ -21,14 +21,12 @@ public slots: virtual void revertConfig(); virtual void applyConfig(); void startQuickRender(); + void startRender(); + void showRender(); protected slots: virtual void configChangeEvent(); -private slots: - void startRender(); - void showRender(); - private: RenderParams _params; CameraDefinition* _camera; diff --git a/src/editing/paysages-qt.pro b/src/editing/paysages-qt.pro index 454542f..86093c6 100644 --- a/src/editing/paysages-qt.pro +++ b/src/editing/paysages-qt.pro @@ -31,7 +31,6 @@ HEADERS += \ previewosd.h \ previewmaterial.h \ previewcolorgradation.h \ - mainwindow.h \ inputnoise.h \ inputmaterial.h \ inputlayers.h \ @@ -70,7 +69,9 @@ HEADERS += \ common/freeformhelper.h \ terrain/previewterrainshape.h \ common/widgetsliderdecimal.h \ - common/previewrenderer.h + common/previewrenderer.h \ + terrain/widgetterrainbasenoisepreview.h \ + common/mainwindow.h SOURCES += \ terrain/widgetheightmap.cpp \ @@ -80,7 +81,6 @@ SOURCES += \ previewosd.cpp \ previewmaterial.cpp \ previewcolorgradation.cpp \ - mainwindow.cpp \ inputnoise.cpp \ inputmaterial.cpp \ inputlayers.cpp \ @@ -119,12 +119,15 @@ SOURCES += \ common/freeformhelper.cpp \ terrain/previewterrainshape.cpp \ common/widgetsliderdecimal.cpp \ - common/previewrenderer.cpp + common/previewrenderer.cpp \ + terrain/widgetterrainbasenoisepreview.cpp \ + common/mainwindow.cpp FORMS += \ terrain/dialogterrainpainting.ui \ common/widgetglobalformbuttons.ui \ - terrain/mainterrainform.ui + terrain/mainterrainform.ui \ + common/mainwindow.ui RESOURCES += \ ../../data/ui_pictures.qrc diff --git a/src/editing/terrain/mainterrainform.cpp b/src/editing/terrain/mainterrainform.cpp index 71c3c08..c383327 100644 --- a/src/editing/terrain/mainterrainform.cpp +++ b/src/editing/terrain/mainterrainform.cpp @@ -22,7 +22,7 @@ MainTerrainForm::MainTerrainForm(QWidget *parent) : _form_helper->addDoubleInputSlider(ui->input_scaling, &_terrain->scaling, 0.1, 3.0, 0.03, 0.3); _form_helper->addDoubleInputSlider(ui->input_height, &_terrain->height, 1.0, 90.0, 0.5, 5.0); _form_helper->addDoubleInputSlider(ui->input_shadow_smoothing, &_terrain->shadow_smoothing, 0.0, 0.3, 0.003, 0.03); - _form_helper->addDoubleInputSlider(ui->input_water_height, &_terrain->water_height, -2.0, 2.0, 0.01, 0.1); + _form_helper->addDoubleInputSlider(ui->input_water_height, &_terrain->water_height, -1.0, 1.0, 0.01, 0.1); _form_helper->setApplyButton(ui->button_apply); _form_helper->setRevertButton(ui->button_revert); @@ -55,6 +55,8 @@ void MainTerrainForm::refreshFromLocalData() { _form_helper->setLabelText("label_painting_info", tr("No manual scuplting done")); } + + ui->widget_base_noise_preview->setNoise(_terrain->_height_noise); } void MainTerrainForm::refreshFromFellowData() diff --git a/src/editing/terrain/mainterrainform.ui b/src/editing/terrain/mainterrainform.ui index 3e08c61..12fbb1b 100644 --- a/src/editing/terrain/mainterrainform.ui +++ b/src/editing/terrain/mainterrainform.ui @@ -54,7 +54,7 @@ - + 1 @@ -447,6 +447,12 @@ QSlider
common/widgetsliderdecimal.h
+ + WidgetTerrainBaseNoisePreview + QWidget +
terrain/widgetterrainbasenoisepreview.h
+ 1 +
diff --git a/src/editing/terrain/previewterrainshape.cpp b/src/editing/terrain/previewterrainshape.cpp index 5582f9d..0919370 100644 --- a/src/editing/terrain/previewterrainshape.cpp +++ b/src/editing/terrain/previewterrainshape.cpp @@ -5,6 +5,7 @@ PreviewTerrainShape::PreviewTerrainShape(TerrainDefinition* terrain) { _terrain = terrain; + _highlight_enabled = true; // TODO Don't delete the base renderer, just alter it rendererDelete(renderer); @@ -14,6 +15,7 @@ PreviewTerrainShape::PreviewTerrainShape(TerrainDefinition* terrain) void PreviewTerrainShape::bindEvent(BasePreview* preview) { preview->addOsd(QString("geolocation")); + //preview->addToggle("highlight", tr("Coverage highlight"), true); preview->configScaling(20.0, 1000.0, 20.0, 50.0); preview->configScrolling(-1000.0, 1000.0, 0.0, -1000.0, 1000.0, 0.0); @@ -26,5 +28,13 @@ void PreviewTerrainShape::updateEvent() Color PreviewTerrainShape::getColor2D(double x, double y, double scaling) { - return terrainGetPreviewColor(renderer, x, y, scaling); + return waterGetPreviewCoverage(renderer, x, y, scaling, _highlight_enabled ? 1 : 0); +} + +void PreviewTerrainShape::toggleChangeEvent(QString key, bool value) +{ + if (key == "highlight") + { + _highlight_enabled = value; + } } diff --git a/src/editing/terrain/previewterrainshape.h b/src/editing/terrain/previewterrainshape.h index ae54091..c99141e 100644 --- a/src/editing/terrain/previewterrainshape.h +++ b/src/editing/terrain/previewterrainshape.h @@ -15,9 +15,12 @@ protected: virtual void bindEvent(BasePreview* preview); virtual void updateEvent(); virtual Color getColor2D(double x, double y, double scaling); + virtual void toggleChangeEvent(QString key, bool value); private: TerrainDefinition* _terrain; + bool _highlight_enabled; + double _water_height; }; #endif // PREVIEWTERRAINSHAPE_H diff --git a/src/editing/terrain/widgetterrainbasenoisepreview.cpp b/src/editing/terrain/widgetterrainbasenoisepreview.cpp new file mode 100644 index 0000000..aacdc99 --- /dev/null +++ b/src/editing/terrain/widgetterrainbasenoisepreview.cpp @@ -0,0 +1,45 @@ +#include "widgetterrainbasenoisepreview.h" + +#include +#include +#include "tools.h" + +WidgetTerrainBaseNoisePreview::WidgetTerrainBaseNoisePreview(QWidget* parent) : + QWidget(parent) +{ + _noise = NULL; +} + +void WidgetTerrainBaseNoisePreview::setNoise(NoiseGenerator* noise) +{ + _noise = noise; + update(); +} + +void WidgetTerrainBaseNoisePreview::paintEvent(QPaintEvent* event) +{ + QPainter painter(this); + + painter.setBrush(Qt::SolidPattern); + painter.drawRect(rect()); + + int height = this->height(); + + if (_noise) + { + QRect boundaries = event->region().boundingRect(); + double value, factor; + double minvalue, maxvalue; + + noiseGetRange(_noise, &minvalue, &maxvalue); + factor = ((double)height) / (maxvalue - minvalue); + + for (int x = boundaries.left(); x <= boundaries.right(); x++) + { + value = noiseGet1DTotal(_noise, 100.0 * ((double)x) / factor); + + painter.setPen(Qt::white); + painter.drawLine(x, height - 1 - (value - minvalue) * factor, x, height - 1); + } + } +} diff --git a/src/editing/terrain/widgetterrainbasenoisepreview.h b/src/editing/terrain/widgetterrainbasenoisepreview.h new file mode 100644 index 0000000..f3e12a5 --- /dev/null +++ b/src/editing/terrain/widgetterrainbasenoisepreview.h @@ -0,0 +1,26 @@ +#ifndef _PAYSAGES_EDITING_TERRAIN_WIDGETTERRAINBASENOISEPREVIEW_H_ +#define _PAYSAGES_EDITING_TERRAIN_WIDGETTERRAINBASENOISEPREVIEW_H_ + +#include +#include "rendering/noise.h" + +class WidgetTerrainBaseNoisePreview : public QWidget +{ + Q_OBJECT +public: + explicit WidgetTerrainBaseNoisePreview(QWidget* parent = 0); + + void setNoise(NoiseGenerator* noise); + +protected: + virtual void paintEvent(QPaintEvent* event); + +signals: + +public slots: + +private: + NoiseGenerator* _noise; +}; + +#endif From 6707998a768159f0c32c0df95c354e0a9c4ae8fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Sun, 9 Jun 2013 18:20:25 +0200 Subject: [PATCH 18/19] Hidden previous tool panel (delayed for future release) --- src/editing/common/mainwindow.cpp | 6 ++++-- src/editing/common/mainwindow.ui | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/editing/common/mainwindow.cpp b/src/editing/common/mainwindow.cpp index f80e078..6597607 100644 --- a/src/editing/common/mainwindow.cpp +++ b/src/editing/common/mainwindow.cpp @@ -63,7 +63,8 @@ int main(int argc, char** argv) BasePreview::initDrawers(); window = new MainWindow(); - window->showMaximized(); + window->show(); + //window->showMaximized(); splash->finish(window); delete splash; @@ -119,7 +120,8 @@ MainWindow::MainWindow(QWidget *parent) : _forms.append(_form_render); // TODO Decide this according to platform / screen size - ui->toolBar->hide(); + //ui->toolBar->hide(); + ui->tool_panel->hide(); ui->menuBar->hide(); scenerySetCustomDataCallback(MainWindow::guiSaveCallback, MainWindow::guiLoadCallback, this); diff --git a/src/editing/common/mainwindow.ui b/src/editing/common/mainwindow.ui index 720f880..b6744c8 100644 --- a/src/editing/common/mainwindow.ui +++ b/src/editing/common/mainwindow.ui @@ -19,6 +19,18 @@ + + 0 + + + 0 + + + 0 + + + 0 + @@ -302,7 +314,10 @@ + + + From b15ea439d2495ebfeaaed35f58c9ad6b87520ece Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Sun, 9 Jun 2013 19:36:30 +0200 Subject: [PATCH 19/19] Started terrain base noise edition dialog --- src/editing/paysages-qt.pro | 9 ++-- .../terrain/dialogbaseterrainnoise.cpp | 31 +++++++++++++ src/editing/terrain/dialogbaseterrainnoise.h | 29 +++++++++++++ src/editing/terrain/dialogbaseterrainnoise.ui | 43 +++++++++++++++++++ src/editing/terrain/mainterrainform.cpp | 24 +++++++++++ src/editing/terrain/mainterrainform.h | 1 + src/editing/terrain/mainterrainform.ui | 2 +- src/rendering/terrain/public.h | 1 + src/rendering/terrain/ter_painting.c | 6 +++ 9 files changed, 142 insertions(+), 4 deletions(-) create mode 100644 src/editing/terrain/dialogbaseterrainnoise.cpp create mode 100644 src/editing/terrain/dialogbaseterrainnoise.h create mode 100644 src/editing/terrain/dialogbaseterrainnoise.ui diff --git a/src/editing/paysages-qt.pro b/src/editing/paysages-qt.pro index 86093c6..1169b91 100644 --- a/src/editing/paysages-qt.pro +++ b/src/editing/paysages-qt.pro @@ -71,7 +71,8 @@ HEADERS += \ common/widgetsliderdecimal.h \ common/previewrenderer.h \ terrain/widgetterrainbasenoisepreview.h \ - common/mainwindow.h + common/mainwindow.h \ + terrain/dialogbaseterrainnoise.h SOURCES += \ terrain/widgetheightmap.cpp \ @@ -121,13 +122,15 @@ SOURCES += \ common/widgetsliderdecimal.cpp \ common/previewrenderer.cpp \ terrain/widgetterrainbasenoisepreview.cpp \ - common/mainwindow.cpp + common/mainwindow.cpp \ + terrain/dialogbaseterrainnoise.cpp FORMS += \ terrain/dialogterrainpainting.ui \ common/widgetglobalformbuttons.ui \ terrain/mainterrainform.ui \ - common/mainwindow.ui + common/mainwindow.ui \ + terrain/dialogbaseterrainnoise.ui RESOURCES += \ ../../data/ui_pictures.qrc diff --git a/src/editing/terrain/dialogbaseterrainnoise.cpp b/src/editing/terrain/dialogbaseterrainnoise.cpp new file mode 100644 index 0000000..5b139c8 --- /dev/null +++ b/src/editing/terrain/dialogbaseterrainnoise.cpp @@ -0,0 +1,31 @@ +#include "dialogbaseterrainnoise.h" +#include "ui_dialogbaseterrainnoise.h" + +DialogBaseTerrainNoise::DialogBaseTerrainNoise(QWidget *parent) : + QDialog(parent), + ui(new Ui::DialogBaseTerrainNoise) +{ + ui->setupUi(this); + + _original = 0; + _modified = noiseCreateGenerator(); +} + +DialogBaseTerrainNoise::~DialogBaseTerrainNoise() +{ + delete ui; + noiseDeleteGenerator(_modified); +} + +void DialogBaseTerrainNoise::setNoise(NoiseGenerator* noise) +{ + _original = noise; + noiseCopy(noise, _modified); +} + +int DialogBaseTerrainNoise::editNoise(QWidget* parent, NoiseGenerator* noise) +{ + DialogBaseTerrainNoise dialog(parent); + dialog.setNoise(noise); + return dialog.exec(); +} diff --git a/src/editing/terrain/dialogbaseterrainnoise.h b/src/editing/terrain/dialogbaseterrainnoise.h new file mode 100644 index 0000000..a38292c --- /dev/null +++ b/src/editing/terrain/dialogbaseterrainnoise.h @@ -0,0 +1,29 @@ +#ifndef DIALOGBASETERRAINNOISE_H +#define DIALOGBASETERRAINNOISE_H + +#include +#include "rendering/noise.h" + +namespace Ui { +class DialogBaseTerrainNoise; +} + +class DialogBaseTerrainNoise : public QDialog +{ + Q_OBJECT + +public: + explicit DialogBaseTerrainNoise(QWidget *parent = 0); + ~DialogBaseTerrainNoise(); + + void setNoise(NoiseGenerator* noise); + + static int editNoise(QWidget* parent, NoiseGenerator* noise); + +private: + Ui::DialogBaseTerrainNoise *ui; + NoiseGenerator* _original; + NoiseGenerator* _modified; +}; + +#endif // DIALOGBASETERRAINNOISE_H diff --git a/src/editing/terrain/dialogbaseterrainnoise.ui b/src/editing/terrain/dialogbaseterrainnoise.ui new file mode 100644 index 0000000..57b1add --- /dev/null +++ b/src/editing/terrain/dialogbaseterrainnoise.ui @@ -0,0 +1,43 @@ + + + DialogBaseTerrainNoise + + + Qt::ApplicationModal + + + + 0 + 0 + 400 + 300 + + + + Paysages 3D - Base terrain noise + + + true + + + + + + + + + + WidgetGlobalFormButtons + QWidget +
common/widgetglobalformbuttons.h
+ 1 + + okClicked() + revertClicked() + cancelClicked() + +
+
+ + +
diff --git a/src/editing/terrain/mainterrainform.cpp b/src/editing/terrain/mainterrainform.cpp index c383327..0c659ed 100644 --- a/src/editing/terrain/mainterrainform.cpp +++ b/src/editing/terrain/mainterrainform.cpp @@ -1,6 +1,8 @@ #include "mainterrainform.h" #include "ui_mainterrainform.h" +#include +#include "dialogbaseterrainnoise.h" #include "dialogterrainpainting.h" #include "previewterrainshape.h" #include "tools.h" @@ -29,6 +31,7 @@ MainTerrainForm::MainTerrainForm(QWidget *parent) : _form_helper->setExploreButton(ui->button_explore); _form_helper->setRenderButton(ui->button_render); + connect(ui->button_dialog_basenoise, SIGNAL(clicked()), this, SLOT(buttonBaseNoisePressed())); connect(ui->button_dialog_painting, SIGNAL(clicked()), this, SLOT(buttonPaintingPressed())); connect(ui->button_goto_textures, SIGNAL(clicked()), this, SLOT(buttonTexturesPressed())); @@ -79,6 +82,27 @@ void MainTerrainForm::alterRenderer(Renderer* renderer) TerrainRendererClass.bind(renderer, _terrain); } +void MainTerrainForm::buttonBaseNoisePressed() +{ + int erase; + if (terrainGetMemoryStats(_terrain) > 0) + { + erase = QMessageBox::question(this, tr("Paysages 3D - Base noise edition"), tr("You have manual modifications on this terrain, regenerating base noise may produce weird results."), tr("Keep my changes anyway"), tr("Erase my changes")); + } + else + { + erase = 0; + } + + if (DialogBaseTerrainNoise::editNoise(this, _terrain->_height_noise)) + { + if (erase) + { + terrainClearPainting(_terrain->height_map); + } + } +} + void MainTerrainForm::buttonPaintingPressed() { DialogTerrainPainting dialog(this, _terrain); diff --git a/src/editing/terrain/mainterrainform.h b/src/editing/terrain/mainterrainform.h index 712197a..5cf5bb9 100644 --- a/src/editing/terrain/mainterrainform.h +++ b/src/editing/terrain/mainterrainform.h @@ -26,6 +26,7 @@ public slots: void commitLocalDataToScenery(); void alterRenderer(Renderer* renderer); + void buttonBaseNoisePressed(); void buttonPaintingPressed(); void buttonTexturesPressed(); diff --git a/src/editing/terrain/mainterrainform.ui b/src/editing/terrain/mainterrainform.ui index 12fbb1b..dac4f2f 100644 --- a/src/editing/terrain/mainterrainform.ui +++ b/src/editing/terrain/mainterrainform.ui @@ -44,7 +44,7 @@ - + Generate base noise diff --git a/src/rendering/terrain/public.h b/src/rendering/terrain/public.h index ca83821..905e626 100644 --- a/src/rendering/terrain/public.h +++ b/src/rendering/terrain/public.h @@ -81,6 +81,7 @@ typedef struct /* Heightmap manipulation */ int terrainIsPainted(TerrainHeightMap* heightmap, int x, int z); +void terrainClearPainting(TerrainHeightMap* heightmap); void terrainBrushElevation(TerrainHeightMap* heightmap, TerrainBrush* brush, double value); void terrainBrushSmooth(TerrainHeightMap* heightmap, TerrainBrush* brush, double value); void terrainBrushAddNoise(TerrainHeightMap* heightmap, TerrainBrush* brush, NoiseGenerator* generator, double value); diff --git a/src/rendering/terrain/ter_painting.c b/src/rendering/terrain/ter_painting.c index 3d60890..b94ab59 100644 --- a/src/rendering/terrain/ter_painting.c +++ b/src/rendering/terrain/ter_painting.c @@ -454,6 +454,12 @@ int terrainIsPainted(TerrainHeightMap* heightmap, int x, int z) return _getDataPointer(&heightmap->brush_data, x, z, NULL, NULL, 0) || _getDataPointer(&heightmap->merged_data, x, z, NULL, NULL, 0); } +void terrainClearPainting(TerrainHeightMap* heightmap) +{ + _clearData(&heightmap->merged_data); + _clearData(&heightmap->brush_data); +} + typedef double (*BrushCallback)(TerrainHeightMap* heightmap, TerrainBrush* brush, double x, double z, double basevalue, double influence, double force, void* data); static inline void _applyBrush(TerrainHeightMap* heightmap, TerrainBrush* brush, double force, void* data, BrushCallback callback)