WIP on clouds walking
This commit is contained in:
parent
af3e0c2fe6
commit
6e8e1bc307
5 changed files with 153 additions and 198 deletions
|
@ -4,6 +4,7 @@
|
||||||
#include "../tools.h"
|
#include "../tools.h"
|
||||||
#include "../renderer.h"
|
#include "../renderer.h"
|
||||||
#include "clo_density.h"
|
#include "clo_density.h"
|
||||||
|
#include "clo_walking.h"
|
||||||
|
|
||||||
/******************** Fake ********************/
|
/******************** Fake ********************/
|
||||||
static int _fakeAlterLight(Renderer* renderer, LightDefinition* light, Vector3 location)
|
static int _fakeAlterLight(Renderer* renderer, LightDefinition* light, Vector3 location)
|
||||||
|
@ -25,13 +26,9 @@ static Color _fakeGetColor(Renderer* renderer, Color base, Vector3 start, Vector
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************** Real ********************/
|
/******************** 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)
|
static int _alterLight(Renderer* renderer, LightDefinition* light, Vector3 location)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
CloudsDefinition* definition = renderer->clouds->definition;
|
CloudsDefinition* definition = renderer->clouds->definition;
|
||||||
int i, n;
|
int i, n;
|
||||||
|
|
||||||
|
@ -43,6 +40,18 @@ static int _alterLight(Renderer* renderer, LightDefinition* light, Vector3 locat
|
||||||
/* TODO Reduce light->reflection too */
|
/* TODO Reduce light->reflection too */
|
||||||
}
|
}
|
||||||
return n > 0;
|
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)
|
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 */
|
/* TODO Iter layers in sorted order */
|
||||||
for (i = 0; i < n; i++)
|
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;
|
return base;
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -2,6 +2,27 @@
|
||||||
|
|
||||||
#include "../renderer.h"
|
#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)
|
int cloudsOptimizeWalkingBounds(CloudsLayerDefinition* layer, Vector3* start, Vector3* end)
|
||||||
{
|
{
|
||||||
|
@ -54,3 +75,35 @@ int cloudsOptimizeWalkingBounds(CloudsLayerDefinition* layer, Vector3* start, Ve
|
||||||
|
|
||||||
return 1;
|
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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
|
@ -31,29 +31,11 @@ typedef struct
|
||||||
double precision_asked;
|
double precision_asked;
|
||||||
|
|
||||||
void* data;
|
void* data;
|
||||||
} CloudWalkingInfo;
|
} CloudWalkerStepInfo;
|
||||||
|
|
||||||
/**
|
typedef struct CloudsWalker CloudsWalker;
|
||||||
* Control of the next walking order.
|
|
||||||
*/
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
CLOUD_WALKING_CONTINUE,
|
|
||||||
CLOUD_WALKING_STOP,
|
|
||||||
CLOUD_WALKING_REFINE,
|
|
||||||
CLOUD_WALKING_SUBDIVIDE
|
|
||||||
} CloudWalkingOrder;
|
|
||||||
|
|
||||||
/**
|
typedef void (*FuncCloudsWalkingCallback)(CloudsWalker* walker);
|
||||||
* Additional info for walking orders.
|
|
||||||
*/
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
double precision;
|
|
||||||
int max_segments;
|
|
||||||
} CloudWalkingOrderInfo;
|
|
||||||
|
|
||||||
typedef CloudWalkingOrder(*FuncCloudSegmentCallback)(CloudWalkingInfo* segment, CloudWalkingOrderInfo* order);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optimize the search limits in a layer.
|
* Optimize the search limits in a layer.
|
||||||
|
@ -66,18 +48,69 @@ typedef CloudWalkingOrder(*FuncCloudSegmentCallback)(CloudWalkingInfo* segment,
|
||||||
int cloudsOptimizeWalkingBounds(CloudsLayerDefinition* layer, Vector3* start, Vector3* end);
|
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.
|
* 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.
|
* The callback will be called with each segment found, giving info and asking for desired alteration on walking.
|
||||||
* @param renderer The renderer environment
|
* @param walker The walker to use
|
||||||
* @param layer The cloud layer
|
|
||||||
* @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 callback Callback to be called with each found segment
|
||||||
* @param data User data that will be passed back in the callback
|
* @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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -200,11 +200,8 @@ 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_walking)
|
||||||
{
|
{
|
||||||
int segment_count, i;
|
|
||||||
CloudPrimarySegment segments[10];
|
|
||||||
|
|
||||||
CloudsLayerDefinition* layer;
|
CloudsLayerDefinition* layer;
|
||||||
layer = cloudsGetLayerType().callback_create();
|
layer = cloudsGetLayerType().callback_create();
|
||||||
layer->lower_altitude = -1.0;
|
layer->lower_altitude = -1.0;
|
||||||
|
@ -217,28 +214,14 @@ static double _getLayerDensitySinX(Renderer* renderer, CloudsLayerDefinition* la
|
||||||
renderer->render_quality = 8;
|
renderer->render_quality = 8;
|
||||||
renderer->clouds->getLayerDensity = _getLayerDensitySinX;
|
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);
|
// TODO
|
||||||
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);
|
|
||||||
|
|
||||||
cloudsGetLayerType().callback_delete(layer);
|
cloudsGetLayerType().callback_delete(layer);
|
||||||
rendererDelete(renderer);
|
rendererDelete(renderer);
|
||||||
}
|
}
|
||||||
END_TEST*/
|
END_TEST
|
||||||
|
|
||||||
TEST_CASE(clouds,
|
TEST_CASE(clouds,
|
||||||
test_clouds_density,
|
test_clouds_density,
|
||||||
test_clouds_walking_boundaries)
|
test_clouds_walking_boundaries,
|
||||||
|
test_clouds_walking)
|
||||||
|
|
Loading…
Reference in a new issue