clouds_walking: Added iterator system for walking
This commit is contained in:
parent
6e8e1bc307
commit
a484479fb7
3 changed files with 120 additions and 5 deletions
|
@ -23,6 +23,24 @@ typedef struct
|
|||
int max_segments;
|
||||
} CloudWalkingNextAction;
|
||||
|
||||
/*
|
||||
* Private structure for the walker.
|
||||
*/
|
||||
struct CloudsWalker
|
||||
{
|
||||
Vector3 start;
|
||||
Vector3 end;
|
||||
Vector3 diff;
|
||||
|
||||
double cursor;
|
||||
double max_length;
|
||||
double step_size;
|
||||
|
||||
CloudWalkerStepInfo last_segment;
|
||||
|
||||
CloudWalkingNextAction next_action;
|
||||
};
|
||||
|
||||
|
||||
int cloudsOptimizeWalkingBounds(CloudsLayerDefinition* layer, Vector3* start, Vector3* end)
|
||||
{
|
||||
|
@ -78,32 +96,91 @@ int cloudsOptimizeWalkingBounds(CloudsLayerDefinition* layer, Vector3* start, Ve
|
|||
|
||||
CloudsWalker* cloudsCreateWalker(Renderer* renderer, CloudsLayerDefinition* layer, Vector3 start, Vector3 end)
|
||||
{
|
||||
CloudsWalker* result;
|
||||
|
||||
result = (CloudsWalker*)malloc(sizeof (CloudsWalker));
|
||||
|
||||
result->start = start;
|
||||
result->end = end;
|
||||
result->diff = v3Sub(end, start);
|
||||
result->max_length = v3Norm(result->diff);
|
||||
result->cursor = 0.0;
|
||||
result->step_size = 1.0;
|
||||
|
||||
result->last_segment.renderer = renderer;
|
||||
result->last_segment.layer = layer;
|
||||
result->last_segment.walked_distance = 0.0;
|
||||
result->last_segment.end = start;
|
||||
|
||||
result->next_action.order = CLOUD_WALKING_CONTINUE;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void cloudsDeleteWalker(CloudsWalker* walker)
|
||||
{
|
||||
free(walker);
|
||||
}
|
||||
|
||||
void cloudsWalkerPerformStep(CloudsWalker* walker)
|
||||
void cloudsSetStepSize(CloudsWalker* walker, double step)
|
||||
{
|
||||
/* TODO Negative step => automatic */
|
||||
walker->step_size = step;
|
||||
}
|
||||
|
||||
int cloudsWalkerPerformStep(CloudsWalker* walker)
|
||||
{
|
||||
if (walker->next_action.order == CLOUD_WALKING_STOP || walker->cursor >= walker->max_length)
|
||||
{
|
||||
walker->next_action.order = CLOUD_WALKING_STOP;
|
||||
return 0;
|
||||
}
|
||||
else if (walker->next_action.order == CLOUD_WALKING_CONTINUE)
|
||||
{
|
||||
/* TODO Limit to end */
|
||||
walker->last_segment.start = walker->last_segment.end;
|
||||
walker->last_segment.walked_distance = walker->cursor;
|
||||
|
||||
walker->cursor += walker->step_size;
|
||||
|
||||
walker->last_segment.end = v3Add(walker->start, v3Scale(walker->diff, walker->cursor / walker->max_length));
|
||||
walker->last_segment.length = walker->step_size;
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* TODO */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void cloudsWalkerOrderStop(CloudsWalker* walker)
|
||||
{
|
||||
walker->next_action.order = CLOUD_WALKING_STOP;
|
||||
}
|
||||
|
||||
void cloudsWalkerOrderRefine(CloudsWalker* walker, double precision)
|
||||
{
|
||||
walker->next_action.order = CLOUD_WALKING_REFINE;
|
||||
walker->next_action.precision = precision;
|
||||
}
|
||||
|
||||
void cloudsWalkerOrderSubdivide(CloudsWalker* walker, double max_segments)
|
||||
{
|
||||
walker->next_action.order = CLOUD_WALKING_SUBDIVIDE;
|
||||
walker->next_action.max_segments = max_segments;
|
||||
}
|
||||
|
||||
CloudWalkerStepInfo* cloudsWalkerGetLastSegment(CloudsWalker* walker)
|
||||
{
|
||||
return &walker->last_segment;
|
||||
}
|
||||
|
||||
void cloudsStartWalking(CloudsWalker* walker, FuncCloudsWalkingCallback callback, void* data)
|
||||
{
|
||||
while (cloudsWalkerPerformStep(walker))
|
||||
{
|
||||
callback(walker);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,9 +26,9 @@ typedef struct
|
|||
Vector3 end;
|
||||
double length;
|
||||
|
||||
int refined;
|
||||
/*int refined;
|
||||
int subdivision_level;
|
||||
double precision_asked;
|
||||
double precision_asked;*/
|
||||
|
||||
void* data;
|
||||
} CloudWalkerStepInfo;
|
||||
|
@ -65,12 +65,21 @@ CloudsWalker* cloudsCreateWalker(Renderer* renderer, CloudsLayerDefinition* laye
|
|||
*/
|
||||
void cloudsDeleteWalker(CloudsWalker* walker);
|
||||
|
||||
/**
|
||||
* Define the segment size for next steps.
|
||||
*
|
||||
* @param walker The walker to configure
|
||||
* @param step The step length, negative for automatic
|
||||
*/
|
||||
void cloudsSetStepSize(CloudsWalker* walker, double step);
|
||||
|
||||
/**
|
||||
* Perform a single step.
|
||||
*
|
||||
* @param walker The walker to use
|
||||
* @return 1 to continue the loop, 0 to stop
|
||||
*/
|
||||
void cloudsWalkerPerformStep(CloudsWalker* walker);
|
||||
int cloudsWalkerPerformStep(CloudsWalker* walker);
|
||||
|
||||
/**
|
||||
* Order the walker to stop.
|
||||
|
|
|
@ -202,6 +202,7 @@ static double _getLayerDensitySinX(Renderer* renderer, CloudsLayerDefinition* la
|
|||
|
||||
START_TEST(test_clouds_walking)
|
||||
{
|
||||
/* Init */
|
||||
CloudsLayerDefinition* layer;
|
||||
layer = cloudsGetLayerType().callback_create();
|
||||
layer->lower_altitude = -1.0;
|
||||
|
@ -214,7 +215,35 @@ START_TEST(test_clouds_walking)
|
|||
renderer->render_quality = 8;
|
||||
renderer->clouds->getLayerDensity = _getLayerDensitySinX;
|
||||
|
||||
// TODO
|
||||
CloudsWalker* walker = cloudsCreateWalker(renderer, layer, v3(-0.4, 0.0, 0.0), v3(10.0, 0.0, 0.0));
|
||||
CloudWalkerStepInfo* segment;
|
||||
int result;
|
||||
|
||||
/* First step */
|
||||
cloudsSetStepSize(walker, 0.3);
|
||||
result = cloudsWalkerPerformStep(walker);
|
||||
segment = cloudsWalkerGetLastSegment(walker);
|
||||
ck_assert_int_eq(result, 1);
|
||||
ck_assert_double_eq(segment->walked_distance, 0.0);
|
||||
ck_assert_vector_values(segment->start, -0.4, 0.0, 0.0);
|
||||
ck_assert_vector_values(segment->end, -0.1, 0.0, 0.0);
|
||||
ck_assert_double_eq(segment->length, 0.3);
|
||||
|
||||
/* Second step */
|
||||
result = cloudsWalkerPerformStep(walker);
|
||||
segment = cloudsWalkerGetLastSegment(walker);
|
||||
ck_assert_int_eq(result, 1);
|
||||
ck_assert_double_eq(segment->walked_distance, 0.3);
|
||||
ck_assert_vector_values(segment->start, -0.1, 0.0, 0.0);
|
||||
ck_assert_vector_values(segment->end, 0.2, 0.0, 0.0);
|
||||
ck_assert_double_eq(segment->length, 0.3);
|
||||
|
||||
/* Order to refine second step around the entry point */
|
||||
cloudsWalkerOrderRefine(walker, 0.01);
|
||||
/* TODO */
|
||||
|
||||
/* Clean up */
|
||||
cloudsDeleteWalker(walker);
|
||||
|
||||
cloudsGetLayerType().callback_delete(layer);
|
||||
rendererDelete(renderer);
|
||||
|
|
Loading…
Reference in a new issue