Draft for new cloud walking algorithm

This commit is contained in:
Michaël Lemaire 2013-05-26 20:28:44 +02:00 committed by Michael Lemaire
parent 5e4b4e59a9
commit af3e0c2fe6
4 changed files with 58 additions and 167 deletions

View file

@ -89,22 +89,16 @@ static Color _applyLayerLighting(CloudsLayerDefinition* definition, Renderer* re
Color cloudsApplyLayer(CloudsLayerDefinition* definition, Color base, Renderer* renderer, Vector3 start, Vector3 end) Color cloudsApplyLayer(CloudsLayerDefinition* definition, Color base, Renderer* renderer, Vector3 start, Vector3 end)
{ {
int segment_count; Color col = COLOR_TRANSPARENT;
Color col;
CloudPrimarySegment segments[MAX_SEGMENT_COUNT];
segment_count = cloudsGetLayerPrimarySegments(renderer, definition, start, end, MAX_SEGMENT_COUNT, segments); if (!cloudsOptimizeWalkingBounds(definition, &start, &end))
/* TODO Crawl in segments for render */
col = definition->material.base;
/*if (definition->transparencydepth == 0 || inside_length >= definition->transparencydepth)
{ {
col.a = 1.0; return base;
} }
else
{ /* TODO Walk through the cloud */
col.a = inside_length / definition->transparencydepth;
}*/ /*segment_count = cloudsGetLayerPrimarySegments(renderer, definition, start, end, MAX_SEGMENT_COUNT, segments);*/
col = renderer->atmosphere->applyAerialPerspective(renderer, start, col).final; col = renderer->atmosphere->applyAerialPerspective(renderer, start, col).final;
col.a = 0.0; col.a = 0.0;

View file

@ -2,6 +2,7 @@
#include "../renderer.h" #include "../renderer.h"
int cloudsOptimizeWalkingBounds(CloudsLayerDefinition* layer, Vector3* start, Vector3* end) int cloudsOptimizeWalkingBounds(CloudsLayerDefinition* layer, Vector3* start, Vector3* end)
{ {
Vector3 diff; Vector3 diff;
@ -51,111 +52,5 @@ int cloudsOptimizeWalkingBounds(CloudsLayerDefinition* layer, Vector3* start, Ve
} }
} }
/* TODO Limit the search length */
return 1; 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)
{
}

View file

@ -5,7 +5,7 @@
#include "../tools/euclid.h" #include "../tools/euclid.h"
/** /**
* Functions to walk through a cloud layer (sampling). * Functions to walk through a cloud layer.
*/ */
#ifdef __cplusplus #ifdef __cplusplus
@ -13,26 +13,47 @@ extern "C"
{ {
#endif #endif
/**
* Information on a segment yielded by walking.
*/
typedef struct typedef struct
{ {
Vector3 entry_point; Renderer* renderer;
Vector3 exit_point; CloudsLayerDefinition* layer;
double length;
} CloudPrimarySegment;
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 typedef struct
{ {
/** Distance factor of the control point from the segment start */ double precision;
double distance; int max_segments;
/** Location of the control point */ } CloudWalkingOrderInfo;
Vector3 location;
/** Global density at the control point (no edge noise applied) */ typedef CloudWalkingOrder(*FuncCloudSegmentCallback)(CloudWalkingInfo* segment, CloudWalkingOrderInfo* order);
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. * Optimize the search limits in a layer.
@ -45,29 +66,18 @@ typedef struct
int cloudsOptimizeWalkingBounds(CloudsLayerDefinition* layer, Vector3* start, Vector3* end); 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 renderer The renderer environment
* @param layer The cloud layer * @param layer The cloud layer
* @param start Start position of the lookup * @param start Start position of the lookup, already optimized
* @param end End position of the lookup * @param end End position of the lookup, already optimized
* @param max_segments Maximum number of segments to collect * @param callback Callback to be called with each found segment
* @param out_segments Allocated space to fill found segments (must be at least 'max_segments' long) * @param data User data that will be passed back in the callback
* @return Number of segments found
*/ */
int cloudsGetLayerPrimarySegments(Renderer* renderer, CloudsLayerDefinition* layer, Vector3 start, Vector3 end, int max_segments, CloudPrimarySegment* out_segments); void cloudsStartWalking(Renderer* renderer, CloudsLayerDefinition* layer, Vector3 start, Vector3 end, FuncCloudSegmentCallback callback, void* data);
/**
* 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 #ifdef __cplusplus
} }

View file

@ -200,7 +200,7 @@ static double _getLayerDensitySinX(Renderer* renderer, CloudsLayerDefinition* la
return (density > 0.0) ? density : 0.0; return (density > 0.0) ? density : 0.0;
} }
START_TEST(test_clouds_primary_segments) /*START_TEST(test_clouds_primary_segments)
{ {
int segment_count, i; int segment_count, i;
CloudPrimarySegment segments[10]; CloudPrimarySegment segments[10];
@ -237,16 +237,8 @@ START_TEST(test_clouds_primary_segments)
cloudsGetLayerType().callback_delete(layer); cloudsGetLayerType().callback_delete(layer);
rendererDelete(renderer); rendererDelete(renderer);
} }
END_TEST END_TEST*/
START_TEST(test_clouds_preview_color) TEST_CASE(clouds,
{ test_clouds_density,
Renderer* renderer = cloudsCreatePreviewColorRenderer(); test_clouds_walking_boundaries)
/* 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)