2018-05-31 08:38:34 +00:00
|
|
|
#include <float.h>
|
2018-07-14 20:54:43 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
|
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"
|
2018-05-31 08:38:34 +00:00
|
|
|
#include "clip.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;
|
|
|
|
|
|
|
|
unsigned char isClippingEnabled() {
|
|
|
|
return ZCLIP_ENABLED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void enableClipping(unsigned char v) {
|
|
|
|
ZCLIP_ENABLED = v;
|
|
|
|
}
|
|
|
|
|
2018-08-16 16:51:15 +00:00
|
|
|
void clipLineToNearZ(const ClipVertex* v1, const ClipVertex* v2, ClipVertex* vout, float* t) __attribute__((optimize("fast-math")));
|
2018-07-16 07:42:15 +00:00
|
|
|
void clipLineToNearZ(const ClipVertex* v1, const ClipVertex* v2, ClipVertex* vout, float* t) {
|
2018-07-16 08:01:11 +00:00
|
|
|
const float NEAR_PLANE = 0.2; // FIXME: this needs to be read from the projection matrix.. somehow
|
|
|
|
|
|
|
|
*t = (NEAR_PLANE - v1->w) / (v2->w - v1->w);
|
2018-05-31 08:38:34 +00:00
|
|
|
|
2018-07-16 07:42:15 +00:00
|
|
|
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
|
|
|
|
2018-07-16 07:42:15 +00:00
|
|
|
vout->xyz[0] = v1->xyz[0] + (vec[0] * (*t));
|
|
|
|
vout->xyz[1] = v1->xyz[1] + (vec[1] * (*t));
|
|
|
|
vout->xyz[2] = v1->xyz[2] + (vec[2] * (*t));
|
2018-05-31 08:38:34 +00:00
|
|
|
}
|
2018-07-10 18:48:25 +00:00
|
|
|
|
2018-08-01 16:57:31 +00:00
|
|
|
static inline void interpolateFloat(const float v1, const float v2, const float t, float* out) {
|
|
|
|
float v = v2 - v1;
|
|
|
|
*out = (v * t) + v1;
|
2018-07-14 20:54:43 +00:00
|
|
|
}
|
|
|
|
|
2018-08-16 16:51:15 +00:00
|
|
|
static inline void interpolateVec2(const float* v1, const float* v2, const float t, float* out) {
|
2018-07-10 18:48:25 +00:00
|
|
|
/* FIXME: SH4 has an asm instruction for this */
|
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
|
|
|
}
|
|
|
|
|
2018-08-16 16:51:15 +00:00
|
|
|
static inline void interpolateVec3(const float* v1, const float* v2, const float t, float* out) {
|
2018-07-10 18:48:25 +00:00
|
|
|
/* FIXME: SH4 has an asm instruction for this */
|
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
|
|
|
}
|
|
|
|
|
2018-08-16 16:51:15 +00:00
|
|
|
static inline void interpolateVec4(const float* v1, const float* v2, const float t, float* out) {
|
2018-08-01 11:00:56 +00:00
|
|
|
/* FIXME: SH4 has an asm instruction for this */
|
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
|
|
|
}
|
|
|
|
|
2018-08-20 08:28:30 +00:00
|
|
|
static 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);
|
|
|
|
}
|
|
|
|
|
2018-07-10 18:48:25 +00:00
|
|
|
const uint32_t VERTEX_CMD_EOL = 0xf0000000;
|
|
|
|
const uint32_t VERTEX_CMD = 0xe0000000;
|
|
|
|
|
2018-09-03 20:48:42 +00:00
|
|
|
void clipTriangleStrip2(AlignedVector* vertices, uint32_t offset) {
|
|
|
|
/* Room for clipping 16 triangles */
|
|
|
|
typedef struct {
|
|
|
|
ClipVertex vertex[3];
|
|
|
|
uint8_t visible;
|
|
|
|
} Triangle;
|
2018-08-28 16:51:33 +00:00
|
|
|
|
2018-09-03 20:48:42 +00:00
|
|
|
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) {
|
|
|
|
|
|
|
|
}
|
2018-08-28 16:51:33 +00:00
|
|
|
}
|
|
|
|
|
2018-08-21 08:37:19 +00:00
|
|
|
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) {
|
2018-07-10 18:48:25 +00:00
|
|
|
|
|
|
|
/* 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;
|
2018-07-31 08:32:55 +00:00
|
|
|
uint32_t stripCount = 2; /* The number of vertices in the source strip so far */
|
2018-07-10 18:48:25 +00:00
|
|
|
|
2018-08-21 08:37:19 +00:00
|
|
|
ClipVertex* thisVertex = vertices + 1;
|
2018-08-16 16:51:15 +00:00
|
|
|
|
2018-08-21 08:37:19 +00:00
|
|
|
for(i = 2; i < count; ++i) {
|
2018-08-16 16:51:15 +00:00
|
|
|
++thisVertex;
|
|
|
|
|
2018-07-31 08:32:55 +00:00
|
|
|
if(stripCount < 2) {
|
|
|
|
stripCount++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-08-16 16:51:15 +00:00
|
|
|
const ClipVertex* sourceTriangle[3] = {
|
|
|
|
thisVertex - 2,
|
|
|
|
thisVertex - 1,
|
2018-07-31 08:32:55 +00:00
|
|
|
thisVertex
|
2018-07-10 18:48:25 +00:00
|
|
|
};
|
|
|
|
|
2018-07-10 19:27:15 +00:00
|
|
|
/* 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 */
|
2018-08-16 16:51:15 +00:00
|
|
|
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];
|
2018-07-10 18:48:25 +00:00
|
|
|
|
2018-08-16 16:51:15 +00:00
|
|
|
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);
|
2018-07-10 18:48:25 +00:00
|
|
|
|
|
|
|
/* All visible, we're fine! */
|
|
|
|
if(visible == 0b111) {
|
2018-07-10 19:27:15 +00:00
|
|
|
if(startOfStrip) {
|
2018-07-10 18:48:25 +00:00
|
|
|
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) {
|
2018-07-14 20:54:43 +00:00
|
|
|
/* Only the first vertex is visible */
|
|
|
|
float t1 = 0, t2 = 0;
|
|
|
|
|
|
|
|
ClipVertex output[3];
|
|
|
|
|
2018-07-16 07:42:15 +00:00
|
|
|
clipLineToNearZ(v1, v2, &output[1], &t1);
|
|
|
|
clipLineToNearZ(v1, v3, &output[2], &t2);
|
2018-07-14 20:54:43 +00:00
|
|
|
|
|
|
|
interpolateFloat(v1->w, v2->w, t1, &output[1].w);
|
|
|
|
interpolateFloat(v1->w, v3->w, t2, &output[2].w);
|
|
|
|
|
|
|
|
output[0] = *v1;
|
2018-07-10 18:48:25 +00:00
|
|
|
|
2018-07-14 20:54:43 +00:00
|
|
|
/* 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);
|
|
|
|
|
2018-08-04 20:00:26 +00:00
|
|
|
interpolateVec2(v1->st, v2->st, t1, output[1].st);
|
|
|
|
interpolateVec2(v1->st, v3->st, t2, output[2].st);
|
|
|
|
|
2018-08-20 08:28:30 +00:00
|
|
|
interpolateColour(v1->bgra, v2->bgra, t1, output[1].bgra);
|
|
|
|
interpolateColour(v1->bgra, v3->bgra, t2, output[2].bgra);
|
2018-07-14 20:54:43 +00:00
|
|
|
|
|
|
|
output[0].flags = VERTEX_CMD;
|
|
|
|
output[1].flags = VERTEX_CMD;
|
|
|
|
output[2].flags = VERTEX_CMD_EOL;
|
|
|
|
|
|
|
|
aligned_vector_push_back(outBuffer, output, 3);
|
2018-07-10 18:48:25 +00:00
|
|
|
} else if(visible == 0b010) {
|
2018-07-14 20:54:43 +00:00
|
|
|
/* Only the second vertex is visible */
|
|
|
|
|
|
|
|
float t1 = 0, t2 = 0;
|
|
|
|
|
|
|
|
ClipVertex output[3];
|
|
|
|
|
2018-07-16 07:42:15 +00:00
|
|
|
clipLineToNearZ(v2, v1, &output[0], &t1);
|
|
|
|
clipLineToNearZ(v2, v3, &output[2], &t2);
|
2018-07-14 20:54:43 +00:00
|
|
|
|
|
|
|
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);
|
2018-07-10 18:48:25 +00:00
|
|
|
|
2018-07-14 20:54:43 +00:00
|
|
|
/* Interpolate texcoords */
|
|
|
|
interpolateVec2(v2->uv, v1->uv, t1, output[0].uv);
|
|
|
|
interpolateVec2(v2->uv, v3->uv, t2, output[2].uv);
|
|
|
|
|
2018-08-04 20:00:26 +00:00
|
|
|
interpolateVec2(v2->st, v1->st, t1, output[0].st);
|
|
|
|
interpolateVec2(v2->st, v3->st, t2, output[2].st);
|
|
|
|
|
2018-08-20 08:28:30 +00:00
|
|
|
interpolateColour(v2->bgra, v1->bgra, t1, output[0].bgra);
|
|
|
|
interpolateColour(v2->bgra, v3->bgra, t2, output[2].bgra);
|
2018-07-14 20:54:43 +00:00
|
|
|
|
|
|
|
output[0].flags = VERTEX_CMD;
|
|
|
|
output[1].flags = VERTEX_CMD;
|
|
|
|
output[2].flags = VERTEX_CMD_EOL;
|
|
|
|
|
|
|
|
aligned_vector_push_back(outBuffer, output, 3);
|
2018-07-10 18:48:25 +00:00
|
|
|
} else if(visible == 0b001) {
|
2018-07-14 20:54:43 +00:00
|
|
|
/* Only the third vertex is visible */
|
|
|
|
|
|
|
|
float t1 = 0, t2 = 0;
|
2018-07-10 18:48:25 +00:00
|
|
|
|
2018-07-14 20:54:43 +00:00
|
|
|
ClipVertex output[3];
|
|
|
|
|
2018-07-16 07:42:15 +00:00
|
|
|
clipLineToNearZ(v3, v1, &output[0], &t1);
|
|
|
|
clipLineToNearZ(v3, v2, &output[1], &t2);
|
2018-07-14 20:54:43 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2018-08-04 20:00:26 +00:00
|
|
|
interpolateVec2(v3->st, v1->st, t1, output[0].st);
|
|
|
|
interpolateVec2(v3->st, v2->st, t2, output[1].st);
|
|
|
|
|
2018-08-20 08:28:30 +00:00
|
|
|
interpolateColour(v3->bgra, v1->bgra, t1, output[0].bgra);
|
|
|
|
interpolateColour(v3->bgra, v2->bgra, t2, output[1].bgra);
|
2018-07-14 20:54:43 +00:00
|
|
|
|
|
|
|
output[0].flags = VERTEX_CMD;
|
|
|
|
output[1].flags = VERTEX_CMD;
|
|
|
|
output[2].flags = VERTEX_CMD_EOL;
|
|
|
|
|
|
|
|
aligned_vector_push_back(outBuffer, output, 3);
|
2018-07-10 18:48:25 +00:00
|
|
|
} else if(visible == 0b110) {
|
|
|
|
/* Third vertex isn't visible */
|
|
|
|
|
|
|
|
float t1 = 0, t2 = 0;
|
|
|
|
|
|
|
|
ClipVertex output[4];
|
|
|
|
|
2018-07-16 07:42:15 +00:00
|
|
|
clipLineToNearZ(v2, v3, &output[2], &t1);
|
|
|
|
clipLineToNearZ(v1, v3, &output[3], &t2);
|
2018-07-14 20:54:43 +00:00
|
|
|
|
|
|
|
interpolateFloat(v2->w, v3->w, t1, &output[2].w);
|
|
|
|
interpolateFloat(v1->w, v3->w, t2, &output[3].w);
|
2018-07-10 18:48:25 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2018-08-04 20:00:26 +00:00
|
|
|
interpolateVec2(v2->st, v3->st, t1, output[2].st);
|
|
|
|
interpolateVec2(v1->st, v3->st, t2, output[3].st);
|
|
|
|
|
2018-08-20 08:28:30 +00:00
|
|
|
interpolateColour(v2->bgra, v3->bgra, t1, output[2].bgra);
|
|
|
|
interpolateColour(v1->bgra, v3->bgra, t2, output[3].bgra);
|
2018-07-10 18:48:25 +00:00
|
|
|
|
|
|
|
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];
|
|
|
|
|
2018-07-16 07:42:15 +00:00
|
|
|
clipLineToNearZ(v1, v2, &output[0], &t1);
|
|
|
|
clipLineToNearZ(v1, v3, &output[2], &t2);
|
2018-07-14 20:54:43 +00:00
|
|
|
|
|
|
|
interpolateFloat(v1->w, v2->w, t1, &output[0].w);
|
|
|
|
interpolateFloat(v1->w, v3->w, t2, &output[2].w);
|
2018-07-10 18:48:25 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2018-08-04 20:00:26 +00:00
|
|
|
interpolateVec2(v1->st, v2->st, t1, output[0].st);
|
|
|
|
interpolateVec2(v1->st, v3->st, t2, output[2].st);
|
|
|
|
|
2018-08-20 08:28:30 +00:00
|
|
|
interpolateColour(v1->bgra, v2->bgra, t1, output[0].bgra);
|
|
|
|
interpolateColour(v1->bgra, v3->bgra, t2, output[2].bgra);
|
2018-07-10 18:48:25 +00:00
|
|
|
|
|
|
|
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];
|
|
|
|
|
2018-07-16 07:42:15 +00:00
|
|
|
clipLineToNearZ(v1, v2, &output[1], &t1);
|
|
|
|
clipLineToNearZ(v3, v2, &output[3], &t2);
|
2018-07-14 20:54:43 +00:00
|
|
|
|
|
|
|
interpolateFloat(v1->w, v2->w, t1, &output[1].w);
|
2018-07-15 18:48:56 +00:00
|
|
|
interpolateFloat(v3->w, v2->w, t2, &output[3].w);
|
2018-07-10 18:48:25 +00:00
|
|
|
|
|
|
|
output[0] = *v1;
|
2018-07-15 18:48:56 +00:00
|
|
|
output[2] = *v3;
|
2018-07-10 18:48:25 +00:00
|
|
|
|
|
|
|
/* Interpolate normals */
|
|
|
|
interpolateVec3(v1->nxyz, v2->nxyz, t1, output[1].nxyz);
|
2018-07-15 18:48:56 +00:00
|
|
|
interpolateVec3(v3->nxyz, v2->nxyz, t2, output[3].nxyz);
|
2018-07-10 18:48:25 +00:00
|
|
|
|
|
|
|
/* Interpolate texcoords */
|
|
|
|
interpolateVec2(v1->uv, v2->uv, t1, output[1].uv);
|
2018-07-15 18:48:56 +00:00
|
|
|
interpolateVec2(v3->uv, v2->uv, t2, output[3].uv);
|
2018-07-10 18:48:25 +00:00
|
|
|
|
2018-08-04 20:00:26 +00:00
|
|
|
interpolateVec2(v1->st, v2->st, t1, output[1].st);
|
|
|
|
interpolateVec2(v3->st, v2->st, t2, output[3].st);
|
|
|
|
|
2018-08-20 08:28:30 +00:00
|
|
|
interpolateColour(v1->bgra, v2->bgra, t1, output[1].bgra);
|
|
|
|
interpolateColour(v3->bgra, v2->bgra, t2, output[3].bgra);
|
2018-07-10 18:48:25 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2018-07-31 08:32:55 +00:00
|
|
|
|
|
|
|
/* If this vertex was the last in the list, reset the stripCount */
|
|
|
|
if(thisVertex->flags == VERTEX_CMD_EOL) {
|
|
|
|
stripCount = 0;
|
|
|
|
} else {
|
|
|
|
stripCount++;
|
|
|
|
}
|
|
|
|
|
2018-07-10 18:48:25 +00:00
|
|
|
}
|
|
|
|
}
|