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] 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)