MuckyFoot-UrbanChaos/MuckyBasic/clip.cpp
2017-05-20 11:14:17 +10:00

156 lines
2.5 KiB
C++

//
// A general clipper.
//
#include "always.h"
//
// The buffer in which we create new points.
//
#define CLIP_BUFFER_SIZE 2048
UBYTE CLIP_buffer[CLIP_BUFFER_SIZE];
UBYTE *CLIP_buffer_upto = CLIP_buffer;
//
// Returns the address of a block of memory of the
// given size.
//
inline void *CLIP_malloc(ULONG size)
{
void *ans;
ASSERT(size < CLIP_BUFFER_SIZE);
if (CLIP_buffer_upto + size * 2 > &CLIP_buffer[CLIP_BUFFER_SIZE])
{
CLIP_buffer_upto = CLIP_buffer;
}
ans = CLIP_buffer_upto;
CLIP_buffer_upto += size * 2;
return ans;
}
void CLIP_do(
void ***polygon,
SLONG *polygon_num_points,
SLONG sizeof_polygon_point,
void (*interpolate)(void *new_point, void *point1, void *point2, float amount_along_from_1_to_2),
float (*signed_distance_from_edge)(void *point))
{
SLONG i;
SLONG i_p1;
SLONG i_p2;
void *p1;
void *p2;
float along;
//
// The output buffer.
//
void **output = (void **) CLIP_malloc(2 * sizeof(void *) * *polygon_num_points);
SLONG output_upto = 0;
//
// Work out the signed distance of each point from the edge.
//
float *distance = (float *) CLIP_malloc(sizeof(float) * *polygon_num_points);
for (i = 0; i < *polygon_num_points; i++)
{
distance[i] = signed_distance_from_edge((*polygon)[i]);
}
//
// Go through the lines of the poly and build up the output polygon.
//
for (i = 0; i < *polygon_num_points; i++)
{
//
// The two points of the line.
//
i_p1 = i + 0;
i_p2 = i + 1;
if (i_p2 == *polygon_num_points)
{
i_p2 = 0;
}
p1 = (*polygon)[i_p1];
p2 = (*polygon)[i_p2];
if (distance[i_p1] >= 0)
{
//
// This point is on the 'good' positive side of the line... add
// it to the output polygon.
//
output[output_upto++] = p1;
if (distance[i_p2] >= 0)
{
//
// The other end of the line is also on the right side of the line...
// no need to create a clipped point.
//
continue;
}
}
else
{
if (distance[i_p2] < 0)
{
//
// Both points are offscreen, so don't create a clipped point between them.
//
continue;
}
}
along = distance[i_p1] / (distance[i_p1] - distance[i_p2]);
//
// Create a clipped point 'along' the way from point 1 to point 2.
//
output[output_upto] = CLIP_malloc(sizeof_polygon_point);
interpolate(
output[output_upto],
p1,
p2,
along);
output_upto += 1;
}
//
// Return the new polygon.
//
*polygon = output;
*polygon_num_points = output_upto;
}