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)
{
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;

View file

@ -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)
{
}

View file

@ -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
}

View file

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