Draft for new cloud walking algorithm
This commit is contained in:
parent
5e4b4e59a9
commit
af3e0c2fe6
4 changed files with 58 additions and 167 deletions
|
@ -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;
|
||||||
|
|
|
@ -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)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
|
||||||
|
|
Loading…
Reference in a new issue