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 1/7] 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 2/7] 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 3/7] 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 4/7] 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 5/7] 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 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 6/7] 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 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 7/7] 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