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_EOL = 0xf0000000;
|
||||||
const uint32_t VERTEX_CMD = 0xe0000000;
|
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) {
|
void clipTriangleStrip2(AlignedVector* vertices, uint32_t offset) {
|
||||||
/* Room for clipping 16 triangles */
|
/* Room for clipping 16 triangles */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -130,10 +200,11 @@ void clipTriangleStrip2(AlignedVector* vertices, uint32_t offset) {
|
||||||
* be the last */
|
* be the last */
|
||||||
if(v3->flags == VERTEX_CMD_EOL) {
|
if(v3->flags == VERTEX_CMD_EOL) {
|
||||||
/* Wipe out the triangle */
|
/* Wipe out the triangle */
|
||||||
*v1 = *v2 = *v3 = *header;
|
markDead(v1);
|
||||||
// fprintf(stderr, "A\n");
|
markDead(v2);
|
||||||
|
markDead(v3);
|
||||||
} else {
|
} else {
|
||||||
*v1 = *header;
|
markDead(v1);
|
||||||
ClipVertex tmp = *v2;
|
ClipVertex tmp = *v2;
|
||||||
*v2 = *v3;
|
*v2 = *v3;
|
||||||
*v3 = tmp;
|
*v3 = tmp;
|
||||||
|
@ -141,7 +212,6 @@ void clipTriangleStrip2(AlignedVector* vertices, uint32_t offset) {
|
||||||
triangle = -1;
|
triangle = -1;
|
||||||
v2->flags = VERTEX_CMD;
|
v2->flags = VERTEX_CMD;
|
||||||
v3->flags = VERTEX_CMD;
|
v3->flags = VERTEX_CMD;
|
||||||
// fprintf(stderr, "B\n");
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0b100:
|
case 0b100:
|
||||||
|
@ -169,15 +239,14 @@ void clipTriangleStrip2(AlignedVector* vertices, uint32_t offset) {
|
||||||
/* Last triangle in strip so end a vertex early */
|
/* Last triangle in strip so end a vertex early */
|
||||||
if(triangle == 0) {
|
if(triangle == 0) {
|
||||||
// Wipe out the triangle completely
|
// Wipe out the triangle completely
|
||||||
*v1 = *v2 = *header;
|
markDead(vertex - 2);
|
||||||
|
markDead(vertex - 1);
|
||||||
} else {
|
} else {
|
||||||
// End the strip
|
// End the strip
|
||||||
(vertex - 1)->flags = VERTEX_CMD_EOL;
|
(vertex - 1)->flags = VERTEX_CMD_EOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reapply the header so a subsequent strip works */
|
markDead(vertex);
|
||||||
*vertex = *header;
|
|
||||||
// fprintf(stderr, "C\n");
|
|
||||||
} else if(triangle == 0) {
|
} else if(triangle == 0) {
|
||||||
/* First triangle in strip, remove first vertex and swap latter two
|
/* First triangle in strip, remove first vertex and swap latter two
|
||||||
to restart the strip */
|
to restart the strip */
|
||||||
|
@ -185,13 +254,12 @@ void clipTriangleStrip2(AlignedVector* vertices, uint32_t offset) {
|
||||||
*v2 = *v3;
|
*v2 = *v3;
|
||||||
*v3 = tmp;
|
*v3 = tmp;
|
||||||
|
|
||||||
/* We simulate removing the vertex by duplicating the header in v1 */
|
markDead(vertex - 2);
|
||||||
*v1 = *header;
|
|
||||||
v2->flags = VERTEX_CMD;
|
(vertex - 1)->flags = VERTEX_CMD;
|
||||||
v3->flags = VERTEX_CMD;
|
vertex->flags = VERTEX_CMD;
|
||||||
|
|
||||||
triangle = -1;
|
triangle = -1;
|
||||||
// fprintf(stderr, "D\n");
|
|
||||||
} else {
|
} else {
|
||||||
ClipVertex* v4 = vertex + 1;
|
ClipVertex* v4 = vertex + 1;
|
||||||
|
|
||||||
|
@ -211,10 +279,8 @@ void clipTriangleStrip2(AlignedVector* vertices, uint32_t offset) {
|
||||||
(vertex - 1)->flags = VERTEX_CMD_EOL;
|
(vertex - 1)->flags = VERTEX_CMD_EOL;
|
||||||
|
|
||||||
if(v4->flags == VERTEX_CMD_EOL) {
|
if(v4->flags == VERTEX_CMD_EOL) {
|
||||||
*vertex = *header;
|
markDead(vertex);
|
||||||
*v4 = *header;
|
markDead(v4);
|
||||||
// fprintf(stderr, "E\n");
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* Swap the next vertices to start a new strip */
|
/* Swap the next vertices to start a new strip */
|
||||||
ClipVertex tmp = *vertex;
|
ClipVertex tmp = *vertex;
|
||||||
|
@ -223,7 +289,6 @@ void clipTriangleStrip2(AlignedVector* vertices, uint32_t offset) {
|
||||||
|
|
||||||
vertex->flags = VERTEX_CMD;
|
vertex->flags = VERTEX_CMD;
|
||||||
v4->flags = VERTEX_CMD;
|
v4->flags = VERTEX_CMD;
|
||||||
// fprintf(stderr, "F\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
i += 1;
|
i += 1;
|
||||||
|
@ -236,7 +301,7 @@ void clipTriangleStrip2(AlignedVector* vertices, uint32_t offset) {
|
||||||
|
|
||||||
/* Now, clip all the triangles and append them to the output */
|
/* Now, clip all the triangles and append them to the output */
|
||||||
for(i = 0; i < CLIP_COUNT; ++i) {
|
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 */
|
/* Perform clipping, generating new vertices as necessary */
|
||||||
clipTriangleStrip2(polylist, (output - (ClipVertex*) polylist->data) - 1);
|
clipTriangleStrip2(polylist, offset);
|
||||||
return polylist->size;
|
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) {
|
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");
|
profiler_checkpoint("transform");
|
||||||
|
|
||||||
if(isClippingEnabled()) {
|
if(isClippingEnabled()) {
|
||||||
spaceNeeded = clip(&activeList->vector, start, spaceNeeded);
|
|
||||||
|
|
||||||
/*
|
uint32_t offset = ((start - 1) - (ClipVertex*) activeList->vector.data);
|
||||||
fprintf(stderr, "--------\n");
|
|
||||||
|
/* Uncomment when debugging clipping
|
||||||
uint32_t i = 0;
|
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);
|
ClipVertex* v = aligned_vector_at(&activeList->vector, i);
|
||||||
if(v->flags == 0xe0000000 || v->flags == 0xf0000000) {
|
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);
|
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));
|
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");
|
profiler_checkpoint("clip");
|
||||||
|
|
Loading…
Reference in New Issue
Block a user