Implement new culling algorithm, still some issues when GL_CULL_FACE is enabled
This commit is contained in:
parent
517d21b487
commit
af54c96ff4
103
GL/clip.c
103
GL/clip.c
|
@ -72,6 +72,76 @@ static inline void interpolateColour(const uint8_t* v1, const uint8_t* v2, const
|
|||
const uint32_t VERTEX_CMD_EOL = 0xf0000000;
|
||||
const uint32_t VERTEX_CMD = 0xe0000000;
|
||||
|
||||
void clipTriangle(const ClipVertex* vertices, const uint8_t visible, AlignedVector* output) {
|
||||
uint8_t i, c = 0;
|
||||
|
||||
|
||||
uint8_t lastVisible = 255;
|
||||
ClipVertex* last = NULL;
|
||||
|
||||
for(i = 0; i < 4; ++i) {
|
||||
uint8_t thisIndex = (i == 3) ? 0 : i;
|
||||
|
||||
ClipVertex next;
|
||||
next.flags = VERTEX_CMD;
|
||||
|
||||
uint8_t thisVisible = (visible & (1 << (2 - thisIndex))) > 0;
|
||||
if(i > 0) {
|
||||
uint8_t lastIndex = (i == 3) ? 2 : thisIndex - 1;
|
||||
|
||||
if(lastVisible < 255 && lastVisible != thisVisible) {
|
||||
const ClipVertex* v1 = &vertices[lastIndex];
|
||||
const ClipVertex* v2 = &vertices[thisIndex];
|
||||
float t;
|
||||
|
||||
clipLineToNearZ(v1, v2, &next, &t);
|
||||
interpolateFloat(v1->w, v2->w, t, &next.w);
|
||||
interpolateVec3(v1->nxyz, v2->nxyz, t, next.nxyz);
|
||||
interpolateVec2(v1->uv, v2->uv, t, next.uv);
|
||||
interpolateVec2(v1->st, v2->st, t, next.st);
|
||||
interpolateColour(v1->bgra, v2->bgra, t, next.bgra);
|
||||
|
||||
last = aligned_vector_push_back(output, &next, 1);
|
||||
last->flags = VERTEX_CMD;
|
||||
++c;
|
||||
}
|
||||
}
|
||||
|
||||
if(thisVisible && i != 3) {
|
||||
last = aligned_vector_push_back(output, &vertices[thisIndex], 1);
|
||||
last->flags = VERTEX_CMD;
|
||||
++c;
|
||||
}
|
||||
|
||||
lastVisible = thisVisible;
|
||||
}
|
||||
|
||||
if(last) {
|
||||
if(c == 4) {
|
||||
/* Convert to two triangles */
|
||||
ClipVertex newVerts[3];
|
||||
newVerts[0] = *(last - 3);
|
||||
newVerts[1] = *(last - 1);
|
||||
newVerts[2] = *(last);
|
||||
|
||||
(last - 1)->flags = VERTEX_CMD_EOL;
|
||||
newVerts[0].flags = VERTEX_CMD;
|
||||
newVerts[1].flags = VERTEX_CMD;
|
||||
newVerts[2].flags = VERTEX_CMD_EOL;
|
||||
|
||||
aligned_vector_resize(output, output->size - 1);
|
||||
aligned_vector_push_back(output, newVerts, 3);
|
||||
} else {
|
||||
last->flags = VERTEX_CMD_EOL;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static inline void markDead(ClipVertex* vert) {
|
||||
vert->flags = VERTEX_CMD_EOL;
|
||||
}
|
||||
|
||||
void clipTriangleStrip2(AlignedVector* vertices, uint32_t offset) {
|
||||
/* Room for clipping 16 triangles */
|
||||
typedef struct {
|
||||
|
@ -130,10 +200,11 @@ void clipTriangleStrip2(AlignedVector* vertices, uint32_t offset) {
|
|||
* be the last */
|
||||
if(v3->flags == VERTEX_CMD_EOL) {
|
||||
/* Wipe out the triangle */
|
||||
*v1 = *v2 = *v3 = *header;
|
||||
// fprintf(stderr, "A\n");
|
||||
markDead(v1);
|
||||
markDead(v2);
|
||||
markDead(v3);
|
||||
} else {
|
||||
*v1 = *header;
|
||||
markDead(v1);
|
||||
ClipVertex tmp = *v2;
|
||||
*v2 = *v3;
|
||||
*v3 = tmp;
|
||||
|
@ -141,7 +212,6 @@ void clipTriangleStrip2(AlignedVector* vertices, uint32_t offset) {
|
|||
triangle = -1;
|
||||
v2->flags = VERTEX_CMD;
|
||||
v3->flags = VERTEX_CMD;
|
||||
// fprintf(stderr, "B\n");
|
||||
}
|
||||
break;
|
||||
case 0b100:
|
||||
|
@ -169,15 +239,14 @@ void clipTriangleStrip2(AlignedVector* vertices, uint32_t offset) {
|
|||
/* Last triangle in strip so end a vertex early */
|
||||
if(triangle == 0) {
|
||||
// Wipe out the triangle completely
|
||||
*v1 = *v2 = *header;
|
||||
markDead(vertex - 2);
|
||||
markDead(vertex - 1);
|
||||
} else {
|
||||
// End the strip
|
||||
(vertex - 1)->flags = VERTEX_CMD_EOL;
|
||||
}
|
||||
|
||||
/* Reapply the header so a subsequent strip works */
|
||||
*vertex = *header;
|
||||
// fprintf(stderr, "C\n");
|
||||
markDead(vertex);
|
||||
} else if(triangle == 0) {
|
||||
/* First triangle in strip, remove first vertex and swap latter two
|
||||
to restart the strip */
|
||||
|
@ -185,13 +254,12 @@ void clipTriangleStrip2(AlignedVector* vertices, uint32_t offset) {
|
|||
*v2 = *v3;
|
||||
*v3 = tmp;
|
||||
|
||||
/* We simulate removing the vertex by duplicating the header in v1 */
|
||||
*v1 = *header;
|
||||
v2->flags = VERTEX_CMD;
|
||||
v3->flags = VERTEX_CMD;
|
||||
markDead(vertex - 2);
|
||||
|
||||
(vertex - 1)->flags = VERTEX_CMD;
|
||||
vertex->flags = VERTEX_CMD;
|
||||
|
||||
triangle = -1;
|
||||
// fprintf(stderr, "D\n");
|
||||
} else {
|
||||
ClipVertex* v4 = vertex + 1;
|
||||
|
||||
|
@ -211,10 +279,8 @@ void clipTriangleStrip2(AlignedVector* vertices, uint32_t offset) {
|
|||
(vertex - 1)->flags = VERTEX_CMD_EOL;
|
||||
|
||||
if(v4->flags == VERTEX_CMD_EOL) {
|
||||
*vertex = *header;
|
||||
*v4 = *header;
|
||||
// fprintf(stderr, "E\n");
|
||||
|
||||
markDead(vertex);
|
||||
markDead(v4);
|
||||
} else {
|
||||
/* Swap the next vertices to start a new strip */
|
||||
ClipVertex tmp = *vertex;
|
||||
|
@ -223,7 +289,6 @@ void clipTriangleStrip2(AlignedVector* vertices, uint32_t offset) {
|
|||
|
||||
vertex->flags = VERTEX_CMD;
|
||||
v4->flags = VERTEX_CMD;
|
||||
// fprintf(stderr, "F\n");
|
||||
}
|
||||
|
||||
i += 1;
|
||||
|
@ -236,7 +301,7 @@ void clipTriangleStrip2(AlignedVector* vertices, uint32_t offset) {
|
|||
|
||||
/* Now, clip all the triangles and append them to the output */
|
||||
for(i = 0; i < CLIP_COUNT; ++i) {
|
||||
|
||||
clipTriangle(TO_CLIP[i].vertex, TO_CLIP[i].visible, vertices);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
66
GL/draw.c
66
GL/draw.c
|
@ -624,48 +624,10 @@ static void transform(ClipVertex* output, const GLsizei count) {
|
|||
}
|
||||
}
|
||||
|
||||
static GLsizei clip(AlignedVector* polylist, ClipVertex* output, const GLsizei count) {
|
||||
static GLsizei clip(AlignedVector* polylist, uint32_t offset, const GLsizei count) {
|
||||
/* Perform clipping, generating new vertices as necessary */
|
||||
clipTriangleStrip2(polylist, (output - (ClipVertex*) polylist->data) - 1);
|
||||
clipTriangleStrip2(polylist, offset);
|
||||
return polylist->size;
|
||||
|
||||
|
||||
static AlignedVector* CLIP_BUFFER = NULL;
|
||||
|
||||
/* First entry into this, allocate the clip buffer */
|
||||
if(!CLIP_BUFFER) {
|
||||
CLIP_BUFFER = (AlignedVector*) malloc(sizeof(AlignedVector));
|
||||
aligned_vector_init(CLIP_BUFFER, sizeof(ClipVertex));
|
||||
}
|
||||
|
||||
/* Make sure we allocate roughly enough space */
|
||||
aligned_vector_reserve(CLIP_BUFFER, count * 1.5);
|
||||
|
||||
/* Start from empty */
|
||||
aligned_vector_resize(CLIP_BUFFER, 0);
|
||||
|
||||
/* Now perform clipping! */
|
||||
clipTriangleStrip(output, count, CLIP_BUFFER);
|
||||
|
||||
/* Calculate the new required size for the poly list. This is the original size
|
||||
* plus the difference in size between the original vertex count and the clip buffer
|
||||
* count */
|
||||
GLsizei newSize = polylist->size + (CLIP_BUFFER->size - count);
|
||||
|
||||
/* Copy the clip buffer over the vertices */
|
||||
aligned_vector_resize(polylist, newSize);
|
||||
|
||||
GLsizei i = CLIP_BUFFER->size;
|
||||
ClipVertex* dst = output;
|
||||
ClipVertex* src = (ClipVertex*) CLIP_BUFFER->data;
|
||||
while(i--) {
|
||||
*dst = *src;
|
||||
++dst;
|
||||
++src;
|
||||
}
|
||||
|
||||
/* Return the new vertex count */
|
||||
return CLIP_BUFFER->size;
|
||||
}
|
||||
|
||||
static void mat_transform3(const float* xyz, const float* xyzOut, const uint32_t count, const uint32_t inStride, const uint32_t outStride) {
|
||||
|
@ -835,12 +797,14 @@ static void submitVertices(GLenum mode, GLsizei first, GLsizei count, GLenum typ
|
|||
profiler_checkpoint("transform");
|
||||
|
||||
if(isClippingEnabled()) {
|
||||
spaceNeeded = clip(&activeList->vector, start, spaceNeeded);
|
||||
|
||||
/*
|
||||
fprintf(stderr, "--------\n");
|
||||
uint32_t offset = ((start - 1) - (ClipVertex*) activeList->vector.data);
|
||||
|
||||
/* Uncomment when debugging clipping
|
||||
uint32_t i = 0;
|
||||
for(i = 0; i < activeList->vector.size; ++i) {
|
||||
fprintf(stderr, "=========\n");
|
||||
|
||||
for(i = offset; i < activeList->vector.size; ++i) {
|
||||
ClipVertex* v = aligned_vector_at(&activeList->vector, i);
|
||||
if(v->flags == 0xe0000000 || v->flags == 0xf0000000) {
|
||||
fprintf(stderr, "(%f, %f, %f) -> %x\n", v->xyz[0], v->xyz[1], v->xyz[2], v->flags);
|
||||
|
@ -848,6 +812,20 @@ static void submitVertices(GLenum mode, GLsizei first, GLsizei count, GLenum typ
|
|||
fprintf(stderr, "%x\n", *((uint32_t*)v));
|
||||
}
|
||||
} */
|
||||
|
||||
spaceNeeded = clip(&activeList->vector, offset, spaceNeeded);
|
||||
|
||||
/* Uncomment when debugging clipping
|
||||
fprintf(stderr, "--------\n");
|
||||
for(i = offset; i < activeList->vector.size; ++i) {
|
||||
ClipVertex* v = aligned_vector_at(&activeList->vector, i);
|
||||
if(v->flags == 0xe0000000 || v->flags == 0xf0000000) {
|
||||
fprintf(stderr, "(%f, %f, %f) -> %x\n", v->xyz[0], v->xyz[1], v->xyz[2], v->flags);
|
||||
} else {
|
||||
fprintf(stderr, "%x\n", *((uint32_t*)v));
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
profiler_checkpoint("clip");
|
||||
|
|
Loading…
Reference in New Issue
Block a user