From 517d21b487fddd9000734a686cda04714a07e43b Mon Sep 17 00:00:00 2001 From: Luke Benstead Date: Mon, 3 Sep 2018 21:48:42 +0100 Subject: [PATCH 1/3] Begin implementing a new clipping algorithm --- GL/clip.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++++- GL/clip.h | 1 + GL/draw.c | 17 +++++- 3 files changed, 182 insertions(+), 2 deletions(-) diff --git a/GL/clip.c b/GL/clip.c index 6928cc8..6a18525 100644 --- a/GL/clip.c +++ b/GL/clip.c @@ -72,8 +72,172 @@ 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 clipTriangleStrip2(const ClipVertex* vertices, const unsigned int count, AlignedVector* outBuffer) { +void clipTriangleStrip2(AlignedVector* vertices, uint32_t offset) { + /* Room for clipping 16 triangles */ + typedef struct { + ClipVertex vertex[3]; + uint8_t visible; + } Triangle; + static Triangle TO_CLIP[256]; + static uint8_t CLIP_COUNT = 0; + + CLIP_COUNT = 0; + + uint32_t i = 0; + /* Skip the header */ + ClipVertex* header = (ClipVertex*) aligned_vector_at(vertices, offset); + ClipVertex* vertex = header + 1; + + uint32_t count = vertices->size - offset; + + int32_t triangle = 0; + + /* Start at 3 due to the header */ + for(i = 3; i < count; ++i, ++triangle) { + vertex = aligned_vector_at(vertices, offset + i); + + uint8_t even = (triangle % 2) == 0; + ClipVertex* v1 = (even) ? vertex - 2 : vertex - 1; + ClipVertex* v2 = (even) ? vertex - 1 : vertex - 2; + ClipVertex* v3 = vertex; + + uint8_t visible = ((v1->w > 0) ? 4 : 0) | ((v2->w > 0) ? 2 : 0) | ((v3->w > 0) ? 1 : 0); + + switch(visible) { + case 0b111: + /* All visible? Do nothing */ + continue; + break; + case 0b000: + /* + It is not possible that this is any trangle except the first + in a strip. That's because: + - It's either the first triangle submitted + - A previous triangle must have been clipped and the strip + restarted behind the plane + + So, we effectively reboot the strip. We mark the first vertex + as the end (so it's ignored) then mark the next two as the + start of a new strip. Then if the next triangle crosses + back into view, we clip correctly. This will potentially + result in a bunch of pointlessly submitted vertices. + + FIXME: Skip submitting those verts + */ + + /* Even though this is always the first in the strip, it can also + * be the last */ + if(v3->flags == VERTEX_CMD_EOL) { + /* Wipe out the triangle */ + *v1 = *v2 = *v3 = *header; + // fprintf(stderr, "A\n"); + } else { + *v1 = *header; + ClipVertex tmp = *v2; + *v2 = *v3; + *v3 = tmp; + + triangle = -1; + v2->flags = VERTEX_CMD; + v3->flags = VERTEX_CMD; + // fprintf(stderr, "B\n"); + } + break; + case 0b100: + case 0b010: + case 0b001: + case 0b101: + case 0b011: + case 0b110: + /* Store the triangle for clipping */ + TO_CLIP[CLIP_COUNT].vertex[0] = *v1; + TO_CLIP[CLIP_COUNT].vertex[1] = *v2; + TO_CLIP[CLIP_COUNT].vertex[2] = *v3; + TO_CLIP[CLIP_COUNT].visible = visible; + ++CLIP_COUNT; + + /* + OK so here's the clever bit. If any triangle except + the first or last needs clipping, then the next one does aswell + (you can't draw a plane through a single triangle in the middle of a + strip, only 2+). This means we can clip in pairs which frees up two + vertices in the middle of the strip, which is exactly the space + we need to restart the triangle strip after the next triangle + */ + if(v3->flags == VERTEX_CMD_EOL) { + /* Last triangle in strip so end a vertex early */ + if(triangle == 0) { + // Wipe out the triangle completely + *v1 = *v2 = *header; + } else { + // End the strip + (vertex - 1)->flags = VERTEX_CMD_EOL; + } + + /* Reapply the header so a subsequent strip works */ + *vertex = *header; + // fprintf(stderr, "C\n"); + } else if(triangle == 0) { + /* First triangle in strip, remove first vertex and swap latter two + to restart the strip */ + ClipVertex tmp = *v2; + *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; + + triangle = -1; + // fprintf(stderr, "D\n"); + } else { + ClipVertex* v4 = vertex + 1; + + TO_CLIP[CLIP_COUNT].vertex[0] = *v3; + TO_CLIP[CLIP_COUNT].vertex[1] = *v2; + TO_CLIP[CLIP_COUNT].vertex[2] = *v4; + + visible = ((v3->w > 0) ? 4 : 0) | ((v2->w > 0) ? 2 : 0) | ((v4->w > 0) ? 1 : 0); + + TO_CLIP[CLIP_COUNT].visible = visible; + ++CLIP_COUNT; + + /* Restart strip */ + triangle = -1; + + /* Mark the second vertex as the end of the strip */ + (vertex - 1)->flags = VERTEX_CMD_EOL; + + if(v4->flags == VERTEX_CMD_EOL) { + *vertex = *header; + *v4 = *header; + // fprintf(stderr, "E\n"); + + } else { + /* Swap the next vertices to start a new strip */ + ClipVertex tmp = *vertex; + *vertex = *v4; + *v4 = tmp; + + vertex->flags = VERTEX_CMD; + v4->flags = VERTEX_CMD; + // fprintf(stderr, "F\n"); + } + + i += 1; + } + break; + default: + break; + } + } + + /* Now, clip all the triangles and append them to the output */ + for(i = 0; i < CLIP_COUNT; ++i) { + + } } void clipTriangleStrip(const ClipVertex* vertices, const unsigned int count, AlignedVector* outBuffer) __attribute__((optimize("fast-math"))); diff --git a/GL/clip.h b/GL/clip.h index 44a3357..152e709 100644 --- a/GL/clip.h +++ b/GL/clip.h @@ -41,6 +41,7 @@ typedef struct { void clipLineToNearZ(const ClipVertex* v1, const ClipVertex* v2, ClipVertex* vout, float* t); void clipTriangleStrip(const ClipVertex* vertices, const unsigned int count, AlignedVector* outBuffer); +void clipTriangleStrip2(AlignedVector* vertices, uint32_t offset); #ifdef __cplusplus } diff --git a/GL/draw.c b/GL/draw.c index 6abf615..5383922 100644 --- a/GL/draw.c +++ b/GL/draw.c @@ -626,6 +626,9 @@ static void transform(ClipVertex* output, const GLsizei count) { static GLsizei clip(AlignedVector* polylist, ClipVertex* output, const GLsizei count) { /* Perform clipping, generating new vertices as necessary */ + clipTriangleStrip2(polylist, (output - (ClipVertex*) polylist->data) - 1); + return polylist->size; + static AlignedVector* CLIP_BUFFER = NULL; @@ -833,6 +836,18 @@ static void submitVertices(GLenum mode, GLsizei first, GLsizei count, GLenum typ if(isClippingEnabled()) { spaceNeeded = clip(&activeList->vector, start, spaceNeeded); + + /* + fprintf(stderr, "--------\n"); + uint32_t i = 0; + for(i = 0; 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"); @@ -880,7 +895,7 @@ static void submitVertices(GLenum mode, GLsizei first, GLsizei count, GLenum typ GLsizei i = spaceNeeded; while(i--) { vertex->uv[0] = vertex->st[0]; - vertex->uv[1] = vertex->st[1]; + vertex->uv[1] = vertex->st[1]; ++vertex; } From af54c96ff4627aa99dc1b25b6632a2781a17bc39 Mon Sep 17 00:00:00 2001 From: Luke Benstead Date: Thu, 6 Sep 2018 19:19:00 +0100 Subject: [PATCH 2/3] Implement new culling algorithm, still some issues when GL_CULL_FACE is enabled --- GL/clip.c | 103 ++++++++++++++++++++++++++++++++++++++++++++---------- GL/draw.c | 66 ++++++++++++---------------------- 2 files changed, 106 insertions(+), 63 deletions(-) diff --git a/GL/clip.c b/GL/clip.c index 6a18525..d6368c9 100644 --- a/GL/clip.c +++ b/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); } } diff --git a/GL/draw.c b/GL/draw.c index 5383922..6926eb7 100644 --- a/GL/draw.c +++ b/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"); From e82646faff241bb8e3fb823d96e9389137ae7021 Mon Sep 17 00:00:00 2001 From: Luke Benstead Date: Thu, 6 Sep 2018 19:22:25 +0100 Subject: [PATCH 3/3] Remove old clipping code --- GL/clip.c | 275 +----------------------------------------------------- 1 file changed, 1 insertion(+), 274 deletions(-) diff --git a/GL/clip.c b/GL/clip.c index d6368c9..20be872 100644 --- a/GL/clip.c +++ b/GL/clip.c @@ -72,6 +72,7 @@ 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) __attribute__((optimize("fast-math"))); void clipTriangle(const ClipVertex* vertices, const uint8_t visible, AlignedVector* output) { uint8_t i, c = 0; @@ -304,277 +305,3 @@ void clipTriangleStrip2(AlignedVector* vertices, uint32_t offset) { clipTriangle(TO_CLIP[i].vertex, TO_CLIP[i].visible, vertices); } } - -void clipTriangleStrip(const ClipVertex* vertices, const unsigned int count, AlignedVector* outBuffer) __attribute__((optimize("fast-math"))); -void clipTriangleStrip(const ClipVertex* vertices, const unsigned int count, AlignedVector* outBuffer) { - - /* Clipping triangle strips is *hard* this is the algorithm we follow: - * - * - Treat each triangle in the strip individually. - * - If we find a triangle that needs clipping, treat it in isolation. - * - End the strip at the triangle - * - Generate a new single-triangle strip for it - * - Begin a new strip for the remainder of the strip - * - * There is probably more efficient way but there are so many different cases to handle that it's - * difficult to even write them down! - */ - - uint32_t i; - uint32_t stripCount = 2; /* The number of vertices in the source strip so far */ - - ClipVertex* thisVertex = vertices + 1; - - for(i = 2; i < count; ++i) { - ++thisVertex; - - if(stripCount < 2) { - stripCount++; - continue; - } - - const ClipVertex* sourceTriangle[3] = { - thisVertex - 2, - thisVertex - 1, - thisVertex - }; - - /* If we're on an odd vertex, we need to swap the order of the first two vertices, as that's what - * triangle strips do */ - uint32_t swap = stripCount > 2 && (stripCount % 2 != 0); - const ClipVertex* v1 = swap ? sourceTriangle[1] : sourceTriangle[0]; - const ClipVertex* v2 = swap ? sourceTriangle[0] : sourceTriangle[1]; - const ClipVertex* v3 = sourceTriangle[2]; - - uint32_t visible = ((v1->w > 0) ? 4 : 0) | ((v2->w > 0) ? 2 : 0) | ((v3->w > 0) ? 1 : 0); - uint32_t startOfStrip = (i == 2) || (outBuffer->size > 2 && ((ClipVertex*) aligned_vector_back(outBuffer))->flags == VERTEX_CMD_EOL); - - /* All visible, we're fine! */ - if(visible == 0b111) { - if(startOfStrip) { - aligned_vector_push_back(outBuffer, v1, 1); - aligned_vector_push_back(outBuffer, v2, 1); - } - - aligned_vector_push_back(outBuffer, v3, 1); - } else if(visible == 0b000) { - /* Do nothing */ - continue; - } else if(visible == 0b100) { - /* Only the first vertex is visible */ - float t1 = 0, t2 = 0; - - ClipVertex output[3]; - - clipLineToNearZ(v1, v2, &output[1], &t1); - clipLineToNearZ(v1, v3, &output[2], &t2); - - interpolateFloat(v1->w, v2->w, t1, &output[1].w); - interpolateFloat(v1->w, v3->w, t2, &output[2].w); - - output[0] = *v1; - - /* Interpolate normals */ - interpolateVec3(v1->nxyz, v2->nxyz, t1, output[1].nxyz); - interpolateVec3(v1->nxyz, v3->nxyz, t2, output[2].nxyz); - - /* Interpolate texcoords */ - interpolateVec2(v1->uv, v2->uv, t1, output[1].uv); - interpolateVec2(v1->uv, v3->uv, t2, output[2].uv); - - interpolateVec2(v1->st, v2->st, t1, output[1].st); - interpolateVec2(v1->st, v3->st, t2, output[2].st); - - interpolateColour(v1->bgra, v2->bgra, t1, output[1].bgra); - interpolateColour(v1->bgra, v3->bgra, t2, output[2].bgra); - - output[0].flags = VERTEX_CMD; - output[1].flags = VERTEX_CMD; - output[2].flags = VERTEX_CMD_EOL; - - aligned_vector_push_back(outBuffer, output, 3); - } else if(visible == 0b010) { - /* Only the second vertex is visible */ - - float t1 = 0, t2 = 0; - - ClipVertex output[3]; - - clipLineToNearZ(v2, v1, &output[0], &t1); - clipLineToNearZ(v2, v3, &output[2], &t2); - - interpolateFloat(v2->w, v1->w, t1, &output[0].w); - interpolateFloat(v2->w, v3->w, t2, &output[2].w); - - output[1] = *v2; - - /* Interpolate normals */ - interpolateVec3(v2->nxyz, v1->nxyz, t1, output[0].nxyz); - interpolateVec3(v2->nxyz, v3->nxyz, t2, output[2].nxyz); - - /* Interpolate texcoords */ - interpolateVec2(v2->uv, v1->uv, t1, output[0].uv); - interpolateVec2(v2->uv, v3->uv, t2, output[2].uv); - - interpolateVec2(v2->st, v1->st, t1, output[0].st); - interpolateVec2(v2->st, v3->st, t2, output[2].st); - - interpolateColour(v2->bgra, v1->bgra, t1, output[0].bgra); - interpolateColour(v2->bgra, v3->bgra, t2, output[2].bgra); - - output[0].flags = VERTEX_CMD; - output[1].flags = VERTEX_CMD; - output[2].flags = VERTEX_CMD_EOL; - - aligned_vector_push_back(outBuffer, output, 3); - } else if(visible == 0b001) { - /* Only the third vertex is visible */ - - float t1 = 0, t2 = 0; - - ClipVertex output[3]; - - clipLineToNearZ(v3, v1, &output[0], &t1); - clipLineToNearZ(v3, v2, &output[1], &t2); - - interpolateFloat(v3->w, v1->w, t1, &output[0].w); - interpolateFloat(v3->w, v2->w, t2, &output[1].w); - - output[2] = *v3; - - /* Interpolate normals */ - interpolateVec3(v3->nxyz, v1->nxyz, t1, output[0].nxyz); - interpolateVec3(v3->nxyz, v2->nxyz, t2, output[1].nxyz); - - /* Interpolate texcoords */ - interpolateVec2(v3->uv, v1->uv, t1, output[0].uv); - interpolateVec2(v3->uv, v2->uv, t2, output[1].uv); - - interpolateVec2(v3->st, v1->st, t1, output[0].st); - interpolateVec2(v3->st, v2->st, t2, output[1].st); - - interpolateColour(v3->bgra, v1->bgra, t1, output[0].bgra); - interpolateColour(v3->bgra, v2->bgra, t2, output[1].bgra); - - output[0].flags = VERTEX_CMD; - output[1].flags = VERTEX_CMD; - output[2].flags = VERTEX_CMD_EOL; - - aligned_vector_push_back(outBuffer, output, 3); - } else if(visible == 0b110) { - /* Third vertex isn't visible */ - - float t1 = 0, t2 = 0; - - ClipVertex output[4]; - - clipLineToNearZ(v2, v3, &output[2], &t1); - clipLineToNearZ(v1, v3, &output[3], &t2); - - interpolateFloat(v2->w, v3->w, t1, &output[2].w); - interpolateFloat(v1->w, v3->w, t2, &output[3].w); - - output[0] = *v1; - output[1] = *v2; - - /* Interpolate normals */ - interpolateVec3(v2->nxyz, v3->nxyz, t1, output[2].nxyz); - interpolateVec3(v1->nxyz, v3->nxyz, t2, output[3].nxyz); - - /* Interpolate texcoords */ - interpolateVec2(v2->uv, v3->uv, t1, output[2].uv); - interpolateVec2(v1->uv, v3->uv, t2, output[3].uv); - - interpolateVec2(v2->st, v3->st, t1, output[2].st); - interpolateVec2(v1->st, v3->st, t2, output[3].st); - - interpolateColour(v2->bgra, v3->bgra, t1, output[2].bgra); - interpolateColour(v1->bgra, v3->bgra, t2, output[3].bgra); - - output[0].flags = VERTEX_CMD; - output[1].flags = VERTEX_CMD; - output[2].flags = VERTEX_CMD; - output[3].flags = VERTEX_CMD_EOL; - - aligned_vector_push_back(outBuffer, output, 4); - } else if(visible == 0b011) { - /* First vertex isn't visible, so let's clip along the lines to the second and third */ - float t1 = 0, t2 = 0; - - ClipVertex output[4]; - - clipLineToNearZ(v1, v2, &output[0], &t1); - clipLineToNearZ(v1, v3, &output[2], &t2); - - interpolateFloat(v1->w, v2->w, t1, &output[0].w); - interpolateFloat(v1->w, v3->w, t2, &output[2].w); - - output[1] = *v2; - output[3] = *v3; - - /* Interpolate normals */ - interpolateVec3(v1->nxyz, v2->nxyz, t1, output[0].nxyz); - interpolateVec3(v1->nxyz, v3->nxyz, t2, output[2].nxyz); - - /* Interpolate texcoords */ - interpolateVec2(v1->uv, v2->uv, t1, output[0].uv); - interpolateVec2(v1->uv, v3->uv, t2, output[2].uv); - - interpolateVec2(v1->st, v2->st, t1, output[0].st); - interpolateVec2(v1->st, v3->st, t2, output[2].st); - - interpolateColour(v1->bgra, v2->bgra, t1, output[0].bgra); - interpolateColour(v1->bgra, v3->bgra, t2, output[2].bgra); - - output[0].flags = VERTEX_CMD; - output[1].flags = VERTEX_CMD; - output[2].flags = VERTEX_CMD; - output[3].flags = VERTEX_CMD_EOL; - - aligned_vector_push_back(outBuffer, output, 4); - } else if(visible == 0b101) { - /* Second vertex isn't visible */ - float t1 = 0, t2 = 0; - - ClipVertex output[4]; - - clipLineToNearZ(v1, v2, &output[1], &t1); - clipLineToNearZ(v3, v2, &output[3], &t2); - - interpolateFloat(v1->w, v2->w, t1, &output[1].w); - interpolateFloat(v3->w, v2->w, t2, &output[3].w); - - output[0] = *v1; - output[2] = *v3; - - /* Interpolate normals */ - interpolateVec3(v1->nxyz, v2->nxyz, t1, output[1].nxyz); - interpolateVec3(v3->nxyz, v2->nxyz, t2, output[3].nxyz); - - /* Interpolate texcoords */ - interpolateVec2(v1->uv, v2->uv, t1, output[1].uv); - interpolateVec2(v3->uv, v2->uv, t2, output[3].uv); - - interpolateVec2(v1->st, v2->st, t1, output[1].st); - interpolateVec2(v3->st, v2->st, t2, output[3].st); - - interpolateColour(v1->bgra, v2->bgra, t1, output[1].bgra); - interpolateColour(v3->bgra, v2->bgra, t2, output[3].bgra); - - output[0].flags = VERTEX_CMD; - output[1].flags = VERTEX_CMD; - output[2].flags = VERTEX_CMD; - output[3].flags = VERTEX_CMD_EOL; - - aligned_vector_push_back(outBuffer, output, 4); - } - - /* If this vertex was the last in the list, reset the stripCount */ - if(thisVertex->flags == VERTEX_CMD_EOL) { - stripCount = 0; - } else { - stripCount++; - } - - } -}