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++; - } - - } -}