2018-05-31 08:38:34 +00:00
|
|
|
#include <float.h>
|
2018-07-14 20:54:43 +00:00
|
|
|
#include <stdio.h>
|
2019-03-06 08:31:06 +00:00
|
|
|
#include <assert.h>
|
2019-03-24 08:09:02 +00:00
|
|
|
#include <string.h>
|
2018-07-14 20:54:43 +00:00
|
|
|
|
2018-07-15 19:44:15 +00:00
|
|
|
#ifdef _arch_dreamcast
|
2018-07-14 20:54:43 +00:00
|
|
|
#include <dc/pvr.h>
|
2018-07-15 19:44:15 +00:00
|
|
|
#else
|
|
|
|
#define PVR_PACK_COLOR(a, r, g, b) {}
|
|
|
|
#endif
|
2018-07-14 20:54:43 +00:00
|
|
|
|
2018-08-16 16:51:15 +00:00
|
|
|
#include "profiler.h"
|
2019-03-24 08:09:02 +00:00
|
|
|
#include "private.h"
|
2018-07-10 18:48:25 +00:00
|
|
|
#include "../containers/aligned_vector.h"
|
2018-05-31 08:38:34 +00:00
|
|
|
|
2018-08-01 10:32:07 +00:00
|
|
|
static unsigned char ZCLIP_ENABLED = 1;
|
|
|
|
|
2019-03-03 19:06:01 +00:00
|
|
|
unsigned char _glIsClippingEnabled() {
|
2018-08-01 10:32:07 +00:00
|
|
|
return ZCLIP_ENABLED;
|
|
|
|
}
|
|
|
|
|
2019-03-03 19:06:01 +00:00
|
|
|
void _glEnableClipping(unsigned char v) {
|
2018-08-01 10:32:07 +00:00
|
|
|
ZCLIP_ENABLED = v;
|
|
|
|
}
|
|
|
|
|
2020-03-20 21:15:05 +00:00
|
|
|
void inline _glClipLineToNearZ(const Vertex* v1, const Vertex* v2, Vertex* vout, float* t) {
|
|
|
|
const float d0 = v1->w + v1->xyz[2];
|
|
|
|
const float d1 = v2->w + v2->xyz[2];
|
2020-03-17 20:32:14 +00:00
|
|
|
|
2020-03-20 21:15:05 +00:00
|
|
|
*t = d0 / (d0 - d1);
|
2018-07-16 08:01:11 +00:00
|
|
|
|
2020-03-20 21:15:05 +00:00
|
|
|
const float vec [] = {
|
|
|
|
v2->xyz[0] - v1->xyz[0],
|
|
|
|
v2->xyz[1] - v1->xyz[1],
|
|
|
|
v2->xyz[2] - v1->xyz[2]
|
|
|
|
};
|
2018-05-31 08:38:34 +00:00
|
|
|
|
2020-03-05 19:44:41 +00:00
|
|
|
vout->xyz[0] = MATH_fmac(vec[0], (*t), v1->xyz[0]);
|
|
|
|
vout->xyz[1] = MATH_fmac(vec[1], (*t), v1->xyz[1]);
|
|
|
|
vout->xyz[2] = MATH_fmac(vec[2], (*t), v1->xyz[2]);
|
2018-05-31 08:38:34 +00:00
|
|
|
}
|
2018-07-10 18:48:25 +00:00
|
|
|
|
2020-03-05 19:44:41 +00:00
|
|
|
GL_FORCE_INLINE void interpolateFloat(const float v1, const float v2, const float t, float* out) {
|
|
|
|
*out = MATH_fmac(v2 - v1,t, v1);
|
2018-07-14 20:54:43 +00:00
|
|
|
}
|
|
|
|
|
2020-03-05 19:44:41 +00:00
|
|
|
GL_FORCE_INLINE void interpolateVec2(const float* v1, const float* v2, const float t, float* out) {
|
2018-08-01 16:57:31 +00:00
|
|
|
interpolateFloat(v1[0], v2[0], t, &out[0]);
|
|
|
|
interpolateFloat(v1[1], v2[1], t, &out[1]);
|
2018-07-10 18:48:25 +00:00
|
|
|
}
|
|
|
|
|
2020-03-05 19:44:41 +00:00
|
|
|
GL_FORCE_INLINE void interpolateVec3(const float* v1, const float* v2, const float t, float* out) {
|
2018-08-01 16:57:31 +00:00
|
|
|
interpolateFloat(v1[0], v2[0], t, &out[0]);
|
|
|
|
interpolateFloat(v1[1], v2[1], t, &out[1]);
|
|
|
|
interpolateFloat(v1[2], v2[2], t, &out[2]);
|
2018-07-10 18:48:25 +00:00
|
|
|
}
|
|
|
|
|
2020-03-05 19:44:41 +00:00
|
|
|
GL_FORCE_INLINE void interpolateVec4(const float* v1, const float* v2, const float t, float* out) {
|
2018-08-01 16:57:31 +00:00
|
|
|
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]);
|
2018-07-10 18:48:25 +00:00
|
|
|
}
|
|
|
|
|
2020-03-05 19:44:41 +00:00
|
|
|
GL_FORCE_INLINE void interpolateColour(const uint8_t* v1, const uint8_t* v2, const float t, uint8_t* out) {
|
2018-08-20 08:28:30 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2018-07-10 18:48:25 +00:00
|
|
|
const uint32_t VERTEX_CMD_EOL = 0xf0000000;
|
|
|
|
const uint32_t VERTEX_CMD = 0xe0000000;
|
|
|
|
|
2019-03-24 08:09:02 +00:00
|
|
|
typedef struct {
|
2019-03-25 09:44:59 +00:00
|
|
|
Vertex vertex[3];
|
2019-03-24 08:09:02 +00:00
|
|
|
VertexExtra extra[3];
|
|
|
|
uint8_t visible;
|
|
|
|
} Triangle;
|
2018-09-06 18:19:00 +00:00
|
|
|
|
2019-03-24 08:09:02 +00:00
|
|
|
void _glClipTriangle(const Triangle* triangle, const uint8_t visible, SubmissionTarget* target, const uint8_t flatShade) __attribute__((optimize("fast-math")));
|
|
|
|
void _glClipTriangle(const Triangle* triangle, const uint8_t visible, SubmissionTarget* target, const uint8_t flatShade) {
|
|
|
|
uint8_t i, c = 0;
|
2018-09-06 18:19:00 +00:00
|
|
|
|
|
|
|
uint8_t lastVisible = 255;
|
2019-03-25 09:44:59 +00:00
|
|
|
Vertex* last = NULL;
|
2019-03-24 08:09:02 +00:00
|
|
|
VertexExtra* veLast = NULL;
|
|
|
|
|
2019-03-25 09:44:59 +00:00
|
|
|
const Vertex* vertices = triangle->vertex;
|
2019-03-24 08:09:02 +00:00
|
|
|
const VertexExtra* extras = triangle->extra;
|
2018-09-06 18:19:00 +00:00
|
|
|
|
2020-02-17 10:31:26 +00:00
|
|
|
char* bgra = (char*) vertices[2].bgra;
|
|
|
|
|
2018-09-08 19:53:28 +00:00
|
|
|
/* Used when flat shading is enabled */
|
2020-02-17 10:31:26 +00:00
|
|
|
uint32_t finalColour = *((uint32_t*) bgra);
|
2018-09-08 19:53:28 +00:00
|
|
|
|
2018-09-06 18:19:00 +00:00
|
|
|
for(i = 0; i < 4; ++i) {
|
|
|
|
uint8_t thisIndex = (i == 3) ? 0 : i;
|
|
|
|
|
2019-03-25 09:44:59 +00:00
|
|
|
Vertex next;
|
2019-03-24 08:09:02 +00:00
|
|
|
VertexExtra veNext;
|
|
|
|
|
2018-09-06 18:19:00 +00:00
|
|
|
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) {
|
2019-03-25 09:44:59 +00:00
|
|
|
const Vertex* v1 = &vertices[lastIndex];
|
|
|
|
const Vertex* v2 = &vertices[thisIndex];
|
2019-03-24 08:09:02 +00:00
|
|
|
|
|
|
|
const VertexExtra* ve1 = &extras[lastIndex];
|
|
|
|
const VertexExtra* ve2 = &extras[thisIndex];
|
|
|
|
|
2018-09-06 18:19:00 +00:00
|
|
|
float t;
|
|
|
|
|
2019-03-24 08:09:02 +00:00
|
|
|
_glClipLineToNearZ(v1, v2, &next, &t);
|
2018-09-06 18:19:00 +00:00
|
|
|
interpolateFloat(v1->w, v2->w, t, &next.w);
|
|
|
|
interpolateVec2(v1->uv, v2->uv, t, next.uv);
|
2019-03-24 08:09:02 +00:00
|
|
|
|
|
|
|
interpolateVec3(ve1->nxyz, ve2->nxyz, t, veNext.nxyz);
|
|
|
|
interpolateVec2(ve1->st, ve2->st, t, veNext.st);
|
2018-09-08 19:53:28 +00:00
|
|
|
|
|
|
|
if(flatShade) {
|
2020-02-17 10:31:26 +00:00
|
|
|
char* next_bgra = (char*) next.bgra;
|
|
|
|
*((uint32_t*) next_bgra) = finalColour;
|
2018-09-08 19:53:28 +00:00
|
|
|
} else {
|
|
|
|
interpolateColour(v1->bgra, v2->bgra, t, next.bgra);
|
|
|
|
}
|
2018-09-06 18:19:00 +00:00
|
|
|
|
2019-03-24 08:09:02 +00:00
|
|
|
/* Push back the new vertices to the end of both the ClipVertex and VertexExtra lists */
|
|
|
|
last = aligned_vector_push_back(&target->output->vector, &next, 1);
|
2018-09-06 18:19:00 +00:00
|
|
|
last->flags = VERTEX_CMD;
|
2019-03-24 08:09:02 +00:00
|
|
|
|
|
|
|
veLast = aligned_vector_push_back(target->extras, &veNext, 1);
|
|
|
|
|
2018-09-06 18:19:00 +00:00
|
|
|
++c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(thisVisible && i != 3) {
|
2019-03-24 08:09:02 +00:00
|
|
|
last = aligned_vector_push_back(&target->output->vector, &vertices[thisIndex], 1);
|
2018-09-06 18:19:00 +00:00
|
|
|
last->flags = VERTEX_CMD;
|
2019-03-24 08:09:02 +00:00
|
|
|
|
|
|
|
veLast = aligned_vector_push_back(target->extras, &extras[thisIndex], 1);
|
|
|
|
|
2018-09-06 18:19:00 +00:00
|
|
|
++c;
|
|
|
|
}
|
|
|
|
|
|
|
|
lastVisible = thisVisible;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(last) {
|
|
|
|
if(c == 4) {
|
|
|
|
/* Convert to two triangles */
|
2019-03-25 09:44:59 +00:00
|
|
|
Vertex newVerts[3];
|
2018-09-06 18:19:00 +00:00
|
|
|
newVerts[0] = *(last - 3);
|
|
|
|
newVerts[1] = *(last - 1);
|
|
|
|
newVerts[2] = *(last);
|
|
|
|
|
2019-03-24 08:09:02 +00:00
|
|
|
VertexExtra newExtras[3];
|
|
|
|
newExtras[0] = *(veLast - 3);
|
|
|
|
newExtras[1] = *(veLast - 1);
|
|
|
|
newExtras[2] = *(veLast);
|
|
|
|
|
2018-09-06 18:19:00 +00:00
|
|
|
(last - 1)->flags = VERTEX_CMD_EOL;
|
|
|
|
newVerts[0].flags = VERTEX_CMD;
|
|
|
|
newVerts[1].flags = VERTEX_CMD;
|
|
|
|
newVerts[2].flags = VERTEX_CMD_EOL;
|
|
|
|
|
2019-03-24 08:09:02 +00:00
|
|
|
aligned_vector_resize(&target->output->vector, target->output->vector.size - 1);
|
|
|
|
aligned_vector_push_back(&target->output->vector, newVerts, 3);
|
|
|
|
|
|
|
|
aligned_vector_resize(target->extras, target->extras->size - 1);
|
|
|
|
aligned_vector_push_back(target->extras, newExtras, 3);
|
2018-09-06 18:19:00 +00:00
|
|
|
} else {
|
|
|
|
last->flags = VERTEX_CMD_EOL;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-25 09:44:59 +00:00
|
|
|
static inline void markDead(Vertex* vert) {
|
2018-09-06 18:19:00 +00:00
|
|
|
vert->flags = VERTEX_CMD_EOL;
|
2019-09-14 19:51:47 +00:00
|
|
|
|
|
|
|
// If we're debugging, wipe out the xyz
|
|
|
|
#ifndef NDEBUG
|
2020-02-17 10:31:26 +00:00
|
|
|
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;
|
2019-09-14 19:51:47 +00:00
|
|
|
#endif
|
2018-09-06 18:19:00 +00:00
|
|
|
}
|
|
|
|
|
2019-03-08 21:36:23 +00:00
|
|
|
#define B000 0
|
|
|
|
#define B111 7
|
|
|
|
#define B100 4
|
|
|
|
#define B010 2
|
|
|
|
#define B001 1
|
|
|
|
#define B101 5
|
|
|
|
#define B011 3
|
|
|
|
#define B110 6
|
|
|
|
|
2019-03-24 08:09:02 +00:00
|
|
|
#define MAX_CLIP_TRIANGLES 255
|
2018-08-28 16:51:33 +00:00
|
|
|
|
2019-03-24 08:09:02 +00:00
|
|
|
void _glClipTriangleStrip(SubmissionTarget* target, uint8_t fladeShade) {
|
|
|
|
static Triangle TO_CLIP[MAX_CLIP_TRIANGLES];
|
2018-09-03 20:48:42 +00:00
|
|
|
static uint8_t CLIP_COUNT = 0;
|
|
|
|
|
|
|
|
CLIP_COUNT = 0;
|
|
|
|
|
2019-03-25 09:44:59 +00:00
|
|
|
Vertex* vertex = _glSubmissionTargetStart(target);
|
|
|
|
const Vertex* end = _glSubmissionTargetEnd(target);
|
|
|
|
const Vertex* start = vertex;
|
2019-03-06 08:31:06 +00:00
|
|
|
|
2019-03-24 08:09:02 +00:00
|
|
|
int32_t triangle = -1;
|
2018-09-03 20:48:42 +00:00
|
|
|
|
2019-03-24 08:09:02 +00:00
|
|
|
/* Go to the (potential) end of the first triangle */
|
|
|
|
vertex++;
|
2018-09-03 20:48:42 +00:00
|
|
|
|
2019-03-24 08:09:02 +00:00
|
|
|
uint32_t vi1, vi2, vi3;
|
2018-09-03 20:48:42 +00:00
|
|
|
|
2019-03-24 08:09:02 +00:00
|
|
|
while(vertex < end) {
|
|
|
|
vertex++;
|
|
|
|
triangle++;
|
2018-09-03 20:48:42 +00:00
|
|
|
|
|
|
|
uint8_t even = (triangle % 2) == 0;
|
2019-03-25 09:44:59 +00:00
|
|
|
Vertex* v1 = (even) ? vertex - 2 : vertex - 1;
|
|
|
|
Vertex* v2 = (even) ? vertex - 1 : vertex - 2;
|
|
|
|
Vertex* v3 = vertex;
|
2018-09-03 20:48:42 +00:00
|
|
|
|
2018-09-15 16:38:42 +00:00
|
|
|
/* Skip ahead if we don't have a complete triangle yet */
|
2018-09-15 16:41:58 +00:00
|
|
|
if(v1->flags != VERTEX_CMD || v2->flags != VERTEX_CMD) {
|
2018-09-15 16:38:42 +00:00
|
|
|
triangle = -1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-03-25 16:07:12 +00:00
|
|
|
/* Indexes into extras array */
|
|
|
|
vi1 = v1 - start;
|
|
|
|
vi2 = v2 - start;
|
|
|
|
vi3 = v3 - start;
|
|
|
|
|
2020-03-20 21:15:05 +00:00
|
|
|
/*
|
|
|
|
* 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)
|
|
|
|
*/
|
|
|
|
uint8_t visible = (
|
2020-03-23 13:44:24 +00:00
|
|
|
((v1->w > 0 && v1->xyz[2] >= -v1->w) ? 4 : 0) |
|
|
|
|
((v2->w > 0 && v2->xyz[2] >= -v2->w) ? 2 : 0) |
|
|
|
|
((v3->w > 0 && v3->xyz[2] >= -v3->w) ? 1 : 0)
|
2020-03-20 21:15:05 +00:00
|
|
|
);
|
2018-09-03 20:48:42 +00:00
|
|
|
|
|
|
|
switch(visible) {
|
2019-03-08 21:36:23 +00:00
|
|
|
case B111:
|
2018-09-03 20:48:42 +00:00
|
|
|
/* All visible? Do nothing */
|
|
|
|
continue;
|
|
|
|
break;
|
2019-03-08 21:36:23 +00:00
|
|
|
case B000:
|
2018-09-03 20:48:42 +00:00
|
|
|
/*
|
|
|
|
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 */
|
2018-09-06 18:19:00 +00:00
|
|
|
markDead(v1);
|
|
|
|
markDead(v2);
|
|
|
|
markDead(v3);
|
2018-09-03 20:48:42 +00:00
|
|
|
} else {
|
2018-09-06 18:19:00 +00:00
|
|
|
markDead(v1);
|
2019-03-25 19:30:45 +00:00
|
|
|
swapVertex(v2, v3);
|
2018-09-03 20:48:42 +00:00
|
|
|
triangle = -1;
|
|
|
|
v2->flags = VERTEX_CMD;
|
|
|
|
v3->flags = VERTEX_CMD;
|
|
|
|
}
|
|
|
|
break;
|
2019-03-08 21:36:23 +00:00
|
|
|
case B100:
|
|
|
|
case B010:
|
|
|
|
case B001:
|
|
|
|
case B101:
|
|
|
|
case B011:
|
|
|
|
case B110:
|
2019-03-24 08:09:02 +00:00
|
|
|
assert(CLIP_COUNT < MAX_CLIP_TRIANGLES);
|
|
|
|
|
2018-09-03 20:48:42 +00:00
|
|
|
/* 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;
|
2019-03-24 08:09:02 +00:00
|
|
|
|
2019-03-25 19:04:50 +00:00
|
|
|
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;
|
2019-03-24 08:09:02 +00:00
|
|
|
|
2018-09-03 20:48:42 +00:00
|
|
|
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
|
2018-09-08 19:53:28 +00:00
|
|
|
markDead(v1);
|
|
|
|
markDead(v2);
|
2018-09-03 20:48:42 +00:00
|
|
|
} else {
|
|
|
|
// End the strip
|
|
|
|
(vertex - 1)->flags = VERTEX_CMD_EOL;
|
|
|
|
}
|
|
|
|
|
2018-09-06 18:19:00 +00:00
|
|
|
markDead(vertex);
|
2018-09-03 20:48:42 +00:00
|
|
|
|
2018-09-15 15:03:21 +00:00
|
|
|
triangle = -1;
|
2018-09-08 19:53:28 +00:00
|
|
|
} else if(triangle == 0) {
|
|
|
|
/* First triangle in strip, remove first vertex */
|
|
|
|
markDead(v1);
|
2018-09-06 18:19:00 +00:00
|
|
|
|
2018-09-08 19:53:28 +00:00
|
|
|
v2->flags = VERTEX_CMD;
|
|
|
|
v3->flags = VERTEX_CMD;
|
2018-09-03 20:48:42 +00:00
|
|
|
|
|
|
|
triangle = -1;
|
2018-09-08 19:53:28 +00:00
|
|
|
} else {
|
2019-03-25 19:04:50 +00:00
|
|
|
Vertex* v4 = v3 + 1;
|
|
|
|
uint32_t vi4 = v4 - start;
|
2018-09-03 20:48:42 +00:00
|
|
|
|
|
|
|
TO_CLIP[CLIP_COUNT].vertex[0] = *v3;
|
|
|
|
TO_CLIP[CLIP_COUNT].vertex[1] = *v2;
|
|
|
|
TO_CLIP[CLIP_COUNT].vertex[2] = *v4;
|
|
|
|
|
2019-03-25 19:04:50 +00:00
|
|
|
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;
|
|
|
|
|
2018-09-03 20:48:42 +00:00
|
|
|
visible = ((v3->w > 0) ? 4 : 0) | ((v2->w > 0) ? 2 : 0) | ((v4->w > 0) ? 1 : 0);
|
|
|
|
|
|
|
|
TO_CLIP[CLIP_COUNT].visible = visible;
|
|
|
|
++CLIP_COUNT;
|
|
|
|
|
2019-03-24 08:09:02 +00:00
|
|
|
// Restart strip
|
2018-09-03 20:48:42 +00:00
|
|
|
triangle = -1;
|
|
|
|
|
2019-03-24 08:09:02 +00:00
|
|
|
// Mark the second vertex as the end of the strip
|
2018-09-03 20:48:42 +00:00
|
|
|
(vertex - 1)->flags = VERTEX_CMD_EOL;
|
|
|
|
|
|
|
|
if(v4->flags == VERTEX_CMD_EOL) {
|
2019-03-25 19:04:50 +00:00
|
|
|
markDead(v3);
|
2018-09-06 18:19:00 +00:00
|
|
|
markDead(v4);
|
2018-09-03 20:48:42 +00:00
|
|
|
} else {
|
2019-03-24 08:09:02 +00:00
|
|
|
// Swap the next vertices to start a new strip
|
2019-03-25 19:04:50 +00:00
|
|
|
swapVertex(v3, v4);
|
|
|
|
v3->flags = VERTEX_CMD;
|
2018-09-03 20:48:42 +00:00
|
|
|
v4->flags = VERTEX_CMD;
|
2019-03-25 19:04:50 +00:00
|
|
|
|
|
|
|
/* Swap the extra data too */
|
|
|
|
VertexExtra t = *ve4;
|
|
|
|
*ve3 = *ve4;
|
|
|
|
*ve4 = t;
|
|
|
|
}
|
2018-09-03 20:48:42 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now, clip all the triangles and append them to the output */
|
2019-03-24 08:09:02 +00:00
|
|
|
GLushort i;
|
2018-09-03 20:48:42 +00:00
|
|
|
for(i = 0; i < CLIP_COUNT; ++i) {
|
2019-03-24 08:09:02 +00:00
|
|
|
_glClipTriangle(&TO_CLIP[i], TO_CLIP[i].visible, target, fladeShade);
|
2018-09-03 20:48:42 +00:00
|
|
|
}
|
2018-08-28 16:51:33 +00:00
|
|
|
}
|