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)
|
||||
{
|
||||
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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue