From 9d9a502e96a57b543235f1bd3b6a0ac8fad4f1f6 Mon Sep 17 00:00:00 2001 From: Luke Benstead Date: Mon, 13 Jun 2022 20:16:46 +0100 Subject: [PATCH] Remove old clipping --- CMakeLists.txt | 1 - GL/clip.c | 405 ------------------------------------------------- 2 files changed, 406 deletions(-) delete mode 100644 GL/clip.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 32a7d8d..b613495 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,7 +33,6 @@ set( containers/aligned_vector.c containers/named_array.c containers/stack.c - GL/clip.c GL/draw.c GL/error.c GL/flush.c diff --git a/GL/clip.c b/GL/clip.c deleted file mode 100644 index ed051d8..0000000 --- a/GL/clip.c +++ /dev/null @@ -1,405 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#ifdef _arch_dreamcast -#include -#else -#define PVR_PACK_COLOR(a, r, g, b) {} -#endif - -#include "private.h" -#include "../containers/aligned_vector.h" - -static unsigned char ZCLIP_ENABLED = 1; - -unsigned char _glIsClippingEnabled() { - return ZCLIP_ENABLED; -} - -void _glEnableClipping(unsigned char v) { - ZCLIP_ENABLED = v; -} - -inline float _glClipLineToNearZ(const Vertex* v1, const Vertex* v2, Vertex* vout) { - const float d0 = v1->w + v1->xyz[2]; - const float d1 = v2->w + v2->xyz[2]; - - /* We need to shift 't' a little, to avoid the possibility that a - * rounding error leaves the new vertex behind the near plane. We shift - * according to the direction we're clipping across the plane */ - const float epsilon = (d0 < d1) ? -0.000001 : 0.000001; - - float t = MATH_Fast_Divide(d0, (d0 - d1)) + epsilon; - - vout->xyz[0] = MATH_fmac(v2->xyz[0] - v1->xyz[0], t, v1->xyz[0]); - vout->xyz[1] = MATH_fmac(v2->xyz[1] - v1->xyz[1], t, v1->xyz[1]); - vout->xyz[2] = MATH_fmac(v2->xyz[2] - v1->xyz[2], t, v1->xyz[2]); - - /* - printf( - "(%f, %f, %f, %f) -> %f -> (%f, %f, %f, %f) = (%f, %f, %f)\n", - v1->xyz[0], v1->xyz[1], v1->xyz[2], v1->w, t, - v2->xyz[0], v2->xyz[1], v2->xyz[2], v2->w, - vout->xyz[0], vout->xyz[1], vout->xyz[2] - );*/ - - return t; -} - -GL_FORCE_INLINE void interpolateFloat(const float v1, const float v2, const float t, float* out) { - *out = MATH_fmac(v2 - v1,t, v1); -} - -GL_FORCE_INLINE void interpolateVec2(const float* v1, const float* v2, const float t, float* out) { - interpolateFloat(v1[0], v2[0], t, &out[0]); - interpolateFloat(v1[1], v2[1], t, &out[1]); -} - -GL_FORCE_INLINE void interpolateVec3(const float* v1, const float* v2, const float t, float* out) { - interpolateFloat(v1[0], v2[0], t, &out[0]); - interpolateFloat(v1[1], v2[1], t, &out[1]); - interpolateFloat(v1[2], v2[2], t, &out[2]); -} - -GL_FORCE_INLINE void interpolateVec4(const float* v1, const float* v2, const float t, float* out) { - interpolateFloat(v1[0], v2[0], t, &out[0]); - interpolateFloat(v1[1], v2[1], t, &out[1]); - interpolateFloat(v1[2], v2[2], t, &out[2]); - interpolateFloat(v1[3], v2[3], t, &out[3]); -} - -GL_FORCE_INLINE void interpolateColour(const uint8_t* v1, const uint8_t* v2, const float t, uint8_t* out) { - out[0] = v1[0] + (uint32_t) (((float) (v2[0] - v1[0])) * t); - out[1] = v1[1] + (uint32_t) (((float) (v2[1] - v1[1])) * t); - out[2] = v1[2] + (uint32_t) (((float) (v2[2] - v1[2])) * t); - out[3] = v1[3] + (uint32_t) (((float) (v2[3] - v1[3])) * t); -} - -const uint32_t VERTEX_CMD_EOL = 0xf0000000; -const uint32_t VERTEX_CMD = 0xe0000000; - -typedef struct { - Vertex vertex[3]; - VertexExtra extra[3]; - uint8_t visible; -} Triangle; - -void _glClipTriangle(const Triangle* triangle, const uint8_t visible, SubmissionTarget* target, const uint8_t flatShade) { - Vertex* last = NULL; - VertexExtra* veLast = NULL; - - const Vertex* vertices = triangle->vertex; - const VertexExtra* extras = triangle->extra; - - char* bgra = (char*) vertices[2].bgra; - - /* Used when flat shading is enabled */ - uint32_t finalColour = *((uint32_t*) bgra); - - Vertex tmp; - VertexExtra veTmp; - - uint8_t pushedCount = 0; - -#define IS_VISIBLE(x) (visible & (1 << (2 - (x)))) > 0 - -#define PUSH_VERT(vert, ve) \ - last = aligned_vector_push_back(&target->output->vector, vert, 1); \ - last->flags = VERTEX_CMD; \ - veLast = aligned_vector_push_back(target->extras, ve, 1); \ - ++pushedCount; - -#define CLIP_TO_PLANE(vert1, ve1, vert2, ve2) \ - do { \ - float t = _glClipLineToNearZ((vert1), (vert2), &tmp); \ - interpolateFloat((vert1)->w, (vert2)->w, t, &tmp.w); \ - interpolateVec2((vert1)->uv, (vert2)->uv, t, tmp.uv); \ - interpolateVec3((ve1)->nxyz, (ve2)->nxyz, t, veTmp.nxyz); \ - interpolateVec2((ve1)->st, (ve2)->st, t, veTmp.st); \ - if(flatShade) { \ - interpolateColour((const uint8_t*) &finalColour, (const uint8_t*) &finalColour, t, tmp.bgra); \ - } else { interpolateColour((vert1)->bgra, (vert2)->bgra, t, tmp.bgra); } \ - } while(0); \ - - uint8_t v0 = IS_VISIBLE(0); - uint8_t v1 = IS_VISIBLE(1); - uint8_t v2 = IS_VISIBLE(2); - if(v0) { - PUSH_VERT(&vertices[0], &extras[0]); - } - - if(v0 != v1) { - CLIP_TO_PLANE(&vertices[0], &extras[0], &vertices[1], &extras[1]); - PUSH_VERT(&tmp, &veTmp); - } - - if(v1) { - PUSH_VERT(&vertices[1], &extras[1]); - } - - if(v1 != v2) { - CLIP_TO_PLANE(&vertices[1], &extras[1], &vertices[2], &extras[2]); - PUSH_VERT(&tmp, &veTmp); - } - - if(v2) { - PUSH_VERT(&vertices[2], &extras[2]); - } - - if(v2 != v0) { - CLIP_TO_PLANE(&vertices[2], &extras[2], &vertices[0], &extras[0]); - PUSH_VERT(&tmp, &veTmp); - } - - if(pushedCount == 4) { - Vertex* prev = last - 1; - VertexExtra* prevVe = veLast - 1; - - tmp = *prev; - veTmp = *prevVe; - - *prev = *last; - *prevVe = *veLast; - - *last = tmp; - *veLast = veTmp; - - prev->flags = VERTEX_CMD; - last->flags = VERTEX_CMD_EOL; - } else { - /* Set the last flag to the end of the new strip */ - last->flags = VERTEX_CMD_EOL; - } -} - -static inline void markDead(Vertex* vert) { - vert->flags = VERTEX_CMD_EOL; - - // If we're debugging, wipe out the xyz -#ifndef NDEBUG - typedef union { - float* f; - int* i; - } cast; - - cast v1, v2, v3; - v1.f = &vert->xyz[0]; - v2.f = &vert->xyz[1]; - v3.f = &vert->xyz[2]; - - *v1.i = 0xDEADBEEF; - *v2.i = 0xDEADBEEF; - *v3.i = 0xDEADBEEF; -#endif -} - -#define B000 0 -#define B111 7 -#define B100 4 -#define B010 2 -#define B001 1 -#define B101 5 -#define B011 3 -#define B110 6 - -#define MAX_CLIP_TRIANGLES 255 - -void _glClipTriangleStrip(SubmissionTarget* target, uint8_t fladeShade) { - static Triangle TO_CLIP[MAX_CLIP_TRIANGLES]; - static uint8_t CLIP_COUNT = 0; - - CLIP_COUNT = 0; - - Vertex* vertex = _glSubmissionTargetStart(target); - const Vertex* end = _glSubmissionTargetEnd(target); - const Vertex* start = vertex; - - int32_t triangle = -1; - - /* Go to the (potential) end of the first triangle */ - vertex++; - - uint32_t vi1, vi2, vi3; - - while(vertex < end) { - vertex++; - triangle++; - - uint8_t even = (triangle % 2) == 0; - Vertex* v1 = (even) ? vertex - 2 : vertex - 1; - Vertex* v2 = (even) ? vertex - 1 : vertex - 2; - Vertex* v3 = vertex; - - /* Skip ahead if we don't have a complete triangle yet */ - if(v1->flags != VERTEX_CMD || v2->flags != VERTEX_CMD) { - triangle = -1; - continue; - } - - /* Indexes into extras array */ - vi1 = v1 - start; - vi2 = v2 - start; - vi3 = v3 - start; - - /* - * A vertex is visible if it's in front of the camera (W > 0) - * and it's in front of the near plane (Z > -W) - */ - -#define _VERT_VISIBLE(v) \ - (v->xyz[2] > -v->w) \ - - uint8_t visible = ( - (_VERT_VISIBLE(v1) ? 4 : 0) | - (_VERT_VISIBLE(v2) ? 2 : 0) | - (_VERT_VISIBLE(v3) ? 1 : 0) - ); - - switch(visible) { - case B111: - /* All visible? Do nothing */ - continue; - break; - case B000: - /* - 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 */ - markDead(v1); - markDead(v2); - markDead(v3); - } else { - markDead(v1); - swapVertex(v2, v3); - triangle = -1; - v2->flags = VERTEX_CMD; - v3->flags = VERTEX_CMD; - } - break; - case B100: - case B010: - case B001: - case B101: - case B011: - case B110: - assert(CLIP_COUNT < MAX_CLIP_TRIANGLES); - - /* 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; - - VertexExtra* ve1 = (VertexExtra*) aligned_vector_at(target->extras, vi1); - VertexExtra* ve2 = (VertexExtra*) aligned_vector_at(target->extras, vi2); - VertexExtra* ve3 = (VertexExtra*) aligned_vector_at(target->extras, vi3); - - TO_CLIP[CLIP_COUNT].extra[0] = *ve1; - TO_CLIP[CLIP_COUNT].extra[1] = *ve2; - TO_CLIP[CLIP_COUNT].extra[2] = *ve3; - - 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 - markDead(v1); - markDead(v2); - } else { - // End the strip - (vertex - 1)->flags = VERTEX_CMD_EOL; - } - - markDead(vertex); - - triangle = -1; - } else if(triangle == 0) { - /* First triangle in strip, remove first vertex */ - markDead(v1); - - v2->flags = VERTEX_CMD; - v3->flags = VERTEX_CMD; - - triangle = -1; - } else { - Vertex* v4 = v3 + 1; - uint32_t vi4 = v4 - start; - - TO_CLIP[CLIP_COUNT].vertex[0] = *v3; - TO_CLIP[CLIP_COUNT].vertex[1] = *v2; - TO_CLIP[CLIP_COUNT].vertex[2] = *v4; - - VertexExtra* ve4 = (VertexExtra*) aligned_vector_at(target->extras, vi4); - TO_CLIP[CLIP_COUNT].extra[0] = *(VertexExtra*) aligned_vector_at(target->extras, vi3); - TO_CLIP[CLIP_COUNT].extra[1] = *(VertexExtra*) aligned_vector_at(target->extras, vi2); - TO_CLIP[CLIP_COUNT].extra[2] = *ve4; - - visible = (_VERT_VISIBLE(v3) ? 4 : 0) | - (_VERT_VISIBLE(v2) ? 2 : 0) | - (_VERT_VISIBLE(v4) ? 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) { - markDead(v3); - markDead(v4); - } else { - // Swap the next vertices to start a new strip - swapVertex(v3, v4); - v3->flags = VERTEX_CMD; - v4->flags = VERTEX_CMD; - - /* Swap the extra data too */ - VertexExtra t = *ve4; - *ve3 = *ve4; - *ve4 = t; - } - } - break; - default: - break; - } - } - - /* Now, clip all the triangles and append them to the output */ - GLushort i; - for(i = 0; i < CLIP_COUNT; ++i) { - _glClipTriangle(&TO_CLIP[i], TO_CLIP[i].visible, target, fladeShade); - } -}