summaryrefslogtreecommitdiff
path: root/src/core/clip.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/clip.c')
-rw-r--r--src/core/clip.c383
1 files changed, 227 insertions, 156 deletions
diff --git a/src/core/clip.c b/src/core/clip.c
index 51321a8..23e18ce 100644
--- a/src/core/clip.c
+++ b/src/core/clip.c
@@ -2,6 +2,122 @@
#include "shader.h"
#include "../util/type.h"
+static LinearInterpolator clip_interpolator[REG_TOTAL] = {
+ ssrS_lerpnum,
+ ssrS_lerpnum,
+ ssrS_lerpnum,
+ ssrS_lerpnum,
+ ssrS_lerpvec2,
+ ssrS_lerpvec2,
+ ssrS_lerpvec2,
+ ssrS_lerpvec2,
+ ssrS_lerpvec2,
+ ssrS_lerpvec2,
+ ssrS_lerpvec2,
+ ssrS_lerpvec2,
+ ssrS_lerpvec3,
+ ssrS_lerpvec3,
+ ssrS_lerpvec3,
+ ssrS_lerpvec3,
+ ssrS_lerpvec3,
+ ssrS_lerpvec3,
+ ssrS_lerpvec3,
+ ssrS_lerpvec3,
+ ssrS_lerpvec3,
+ ssrS_lerpvec3,
+ ssrS_lerpvec3,
+ ssrS_lerpvec3,
+ ssrS_lerpvec4,
+ ssrS_lerpvec4,
+ ssrS_lerpvec4,
+ ssrS_lerpvec4,
+ ssrS_lerpvec4,
+ ssrS_lerpvec4,
+ ssrS_lerpvec4,
+ ssrS_lerpvec4,
+};
+
+uint clip_element_size[REG_TOTAL] = {
+ 4,4,4,4, /*float*/
+ 8, 8, 8, 8,8, 8, 8, 8, /*Vec2*/
+ 12,12,12,12,12,12,12,12,12,12,12,12, /*Vec3*/
+ 16,16,16,16,16,16,16,16 /*Vec4*/
+};
+
+/*用来访问临时寄存器*/
+byte* clip_buffer_data[REG_TOTAL] =
+{
+ clip_buffer.temp_reg_num[0],
+ clip_buffer.temp_reg_num[1],
+ clip_buffer.temp_reg_num[2],
+ clip_buffer.temp_reg_num[3],
+ clip_buffer.temp_reg_v2[0],
+ clip_buffer.temp_reg_v2[1],
+ clip_buffer.temp_reg_v2[2],
+ clip_buffer.temp_reg_v2[3],
+ clip_buffer.temp_reg_v2[4],
+ clip_buffer.temp_reg_v2[5],
+ clip_buffer.temp_reg_v2[6],
+ clip_buffer.temp_reg_v2[7],
+ clip_buffer.temp_reg_v3[0],
+ clip_buffer.temp_reg_v3[1],
+ clip_buffer.temp_reg_v3[2],
+ clip_buffer.temp_reg_v3[3],
+ clip_buffer.temp_reg_v3[4],
+ clip_buffer.temp_reg_v3[5],
+ clip_buffer.temp_reg_v3[6],
+ clip_buffer.temp_reg_v3[7],
+ clip_buffer.temp_reg_v3[8],
+ clip_buffer.temp_reg_v3[9],
+ clip_buffer.temp_reg_v3[10],
+ clip_buffer.temp_reg_v3[11],
+ clip_buffer.temp_reg_v4[0],
+ clip_buffer.temp_reg_v4[1],
+ clip_buffer.temp_reg_v4[2],
+ clip_buffer.temp_reg_v4[3],
+ clip_buffer.temp_reg_v4[4],
+ clip_buffer.temp_reg_v4[5],
+ clip_buffer.temp_reg_v4[6],
+ clip_buffer.temp_reg_v4[7],
+};
+
+/*用来访问临时寄存器*/
+byte* temp_clip_buffer_data[REG_TOTAL] =
+{
+ temp_clip_buffer.temp_reg_num[0],
+ temp_clip_buffer.temp_reg_num[1],
+ temp_clip_buffer.temp_reg_num[2],
+ temp_clip_buffer.temp_reg_num[3],
+ temp_clip_buffer.temp_reg_v2[0],
+ temp_clip_buffer.temp_reg_v2[1],
+ temp_clip_buffer.temp_reg_v2[2],
+ temp_clip_buffer.temp_reg_v2[3],
+ temp_clip_buffer.temp_reg_v2[4],
+ temp_clip_buffer.temp_reg_v2[5],
+ temp_clip_buffer.temp_reg_v2[6],
+ temp_clip_buffer.temp_reg_v2[7],
+ temp_clip_buffer.temp_reg_v3[0],
+ temp_clip_buffer.temp_reg_v3[1],
+ temp_clip_buffer.temp_reg_v3[2],
+ temp_clip_buffer.temp_reg_v3[3],
+ temp_clip_buffer.temp_reg_v3[4],
+ temp_clip_buffer.temp_reg_v3[5],
+ temp_clip_buffer.temp_reg_v3[6],
+ temp_clip_buffer.temp_reg_v3[7],
+ temp_clip_buffer.temp_reg_v3[8],
+ temp_clip_buffer.temp_reg_v3[9],
+ temp_clip_buffer.temp_reg_v3[10],
+ temp_clip_buffer.temp_reg_v3[11],
+ temp_clip_buffer.temp_reg_v4[0],
+ temp_clip_buffer.temp_reg_v4[1],
+ temp_clip_buffer.temp_reg_v4[2],
+ temp_clip_buffer.temp_reg_v4[3],
+ temp_clip_buffer.temp_reg_v4[4],
+ temp_clip_buffer.temp_reg_v4[5],
+ temp_clip_buffer.temp_reg_v4[6],
+ temp_clip_buffer.temp_reg_v4[7],
+};
+
typedef enum {
POSITIVE_W,
POSITIVE_X,
@@ -61,169 +177,124 @@ static float get_intersect_ratio(Vec4* prev, Vec4* curr, Plane plane) {
return 0;
}
}
-//
-//static bool clip_against_plane(Plane plane, uint varying_flag, ClippedBuffer* src_buffer, ClippedBuffer* dst_buffer) {
-// int idx = 0;
-// for (int i = 0; i < src_buffer->count; ++i) {
-// ClippedVert* prev = &src_buffer->vertices[(i - 1 + src_buffer->count) % src_buffer->count];
-// ClippedVert* curr = &src_buffer->vertices[i];
-//
-// bool prev_inside = is_inside_plane(&prev->clip_coord, plane);
-// bool curr_inside = is_inside_plane(&curr->clip_coord, plane);
-//
-// if (prev_inside != curr_inside) {
-// ClippedVert* dst = &dst_buffer->vertices[idx];
-// float t = get_intersect_ratio(&prev->clip_coord, &curr->clip_coord, plane);
-// ssrS_lerpvec4(t, &prev->clip_coord, &curr->clip_coord, &dst->clip_coord);
-// /*set varying varibles*/
-// if (varying_flag & VARYING_BASIC) {
-// if (varying_flag & VARYING_POSITION) ssrS_lerpvec3(t, &prev->vertex.position, &curr->vertex.position, &dst->vertex.position);
-// if (varying_flag & VARYING_NORMAL) ssrS_lerpvec3(t, &prev->vertex.normal, &curr->vertex.normal, &dst->vertex.normal);
-// if (varying_flag & VARYING_TANGENT) ssrS_lerpvec3(t, &prev->vertex.tangent, &curr->vertex.tangent, &dst->vertex.tangent);
-// if (varying_flag & VARYING_TEXCOORD) ssrS_lerpvec2(t, &prev->vertex.texcoord, &curr->vertex.texcoord, &dst->vertex.texcoord);
-// if (varying_flag & VARYING_COLOR) ssrS_lerpcolor(t, prev->vertex.color, curr->vertex.color, &dst->vertex.color);
-///*
-// if (varying_flag & VARYING_JOINT) ssrS_lerpvec4(t, &prev->vertex.joint, &curr->vertex.joint, &dst->vertex.joint);
-// if (varying_flag & VARYING_WEIGHT) ssrS_lerpvec4(t, &prev->vertex.weight, &curr->vertex.weight, &dst->vertex.weight);
-//*/
-// }
-// if (varying_flag & VARYING_ANY) {
-// int j = 0;
-// if (varying_flag & VARYING_NUM) {
-// for (j = 0; j < REG_NUM_COUNT; ++j) {
-// if (varying_flag & (VARYING_NUM_00 << j)) {
-// ssrS_lerpnum(t, prev->num[j], curr->num[j], &dst->num[j]);
-// }
-// }
-// }
-// if (varying_flag & VARYING_V2) {
-// for (j = 0; j < REG_V2_COUNT; ++j) {
-// if (varying_flag & (VARYING_V2_00 << j)) {
-// ssrS_lerpvec2(t, &prev->v2[j], &curr->v2[j], &dst->v2[j]);
-// }
-// }
-// }
-// if (varying_flag & VARYING_V3) {
-// for (j = 0; j < REG_V3_COUNT; ++j) {
-// if (varying_flag & (VARYING_V3_00 << j)) {
-// ssrS_lerpvec3(t, &prev->v3[j], &curr->v3[j], &dst->v3[j]);
-// }
-// }
-// }
-// if (varying_flag & VARYING_V4) {
-// for (j = 0; j < REG_V4_COUNT; ++j) {
-// if (varying_flag & (VARYING_V4_00 << j)) {
-// ssrS_lerpvec4(t, &prev->v4[j], &curr->v4[j], &dst->v4[j]);
-// }
-// }
-// }
-// }
-// ++idx;
-// }
-//
-// if (curr_inside) {
-// ClippedVert* dst = &dst_buffer->vertices[idx];
-// *dst = *curr;
-// ++idx;
-// }
-// }
-// dst_buffer->count = idx;
-// return idx < 3;
-//}
-
-#define CLIP(plane, from, to) \
-do { \
- if (clip_against_plane(plane, varying_flag, from, to)) { \
- buffer->count = 0;/*cull this triangle*/ \
- return 1; \
- } \
-}while(0)
-ClippedBuffer clip_buffer;
+static bool clip_against_plane(
+ Plane plane
+ , uint varying_flag
+ , ClippedBuffer* src_buffer
+ , ClippedBuffer* dst_buffer
+ , byte* src_data[]
+ , byte* dst_data[]
+) {
+ bool varying = varying_flag & VARYING_ANY;
+ int idx = 0; /*顶点索引*/
+ ClippedVert *prev, *curr;
+ uint previ, curri;
+ bool prev_inside, curr_inside;
+ int i, j, regi, size;
+ float t;
+ ClippedVert* dst;
+ for (i = 0; i < src_buffer->count; ++i) {
+ prev = &src_buffer->vertices[(i - 1 + src_buffer->count) % src_buffer->count];
+ curr = &src_buffer->vertices[i];
-byte* clip_buffer_data[REG_TOTAL] =
-{
- &clip_buffer.temp_reg_num[0],
- &clip_buffer.temp_reg_num[1],
- &clip_buffer.temp_reg_num[2],
- &clip_buffer.temp_reg_num[3],
- &clip_buffer.temp_reg_v2[0],
- &clip_buffer.temp_reg_v2[1],
- &clip_buffer.temp_reg_v2[2],
- &clip_buffer.temp_reg_v2[3],
- &clip_buffer.temp_reg_v2[4],
- &clip_buffer.temp_reg_v2[5],
- &clip_buffer.temp_reg_v3[0],
- &clip_buffer.temp_reg_v3[1],
- &clip_buffer.temp_reg_v3[2],
- &clip_buffer.temp_reg_v3[3],
- &clip_buffer.temp_reg_v3[4],
- &clip_buffer.temp_reg_v3[5],
- &clip_buffer.temp_reg_v3[6],
- &clip_buffer.temp_reg_v3[7],
- &clip_buffer.temp_reg_v4[0],
- &clip_buffer.temp_reg_v4[1],
- &clip_buffer.temp_reg_v4[2],
- &clip_buffer.temp_reg_v4[3],
- &clip_buffer.temp_reg_v4[4],
- &clip_buffer.temp_reg_v4[5],
-};
+ previ = prev->vertex.index;
+ curri = curr->vertex.index;
+
+ prev_inside = is_inside_plane(&prev->clip_coord, plane);
+ curr_inside = is_inside_plane(&curr->clip_coord, plane);
-bool clip_triangle(Vec4* c0, Vec4* c1, Vec4* c2, Vert* v0, Vert* v1, Vert* v2, uint varying_flag, ClippedBuffer* buffer) {
+ if (prev_inside != curr_inside) {
+ t = get_intersect_ratio(&prev->clip_coord, &curr->clip_coord, plane);
+ dst = &dst_buffer->vertices[idx];
+ ssrS_lerpvec4(t, &prev->clip_coord, &curr->clip_coord, &dst->clip_coord);
+ dst->vertex.index = idx;
+ /*set varying variables*/
+ if (varying) {
+ for (j = 0; j < REG_TOTAL; ++j) {
+ regi = open_regsi[j];
+ if (regi == -1) break;
+ size = clip_element_size[regi];
+ clip_interpolator[regi](t, &src_data[regi][previ * size], &src_data[regi][curri * size], &dst_data[regi][idx * size]);
+ }
+ }
+ ++idx;
+ }
+
+ if (curr_inside) {
+ dst = &dst_buffer->vertices[idx];
+ *dst = *curr;
+ dst->vertex.index = idx;
+ /*copy varying variables*/
+ if (varying) {
+ for (j = 0; j < REG_TOTAL; ++j) {
+ regi = open_regsi[j];
+ if (regi == -1) break;
+ size = clip_element_size[regi];
+ ssrM_copy(&dst_data[regi][idx*size], &src_data[regi][curri*size], size);
+ }
+ }
+ ++idx;
+ }
+ }
+ dst_buffer->count = idx;
+ return idx < 3;
+}
+
+#define CLIP(plane, from, to, from_data, to_data) \
+ if (clip_against_plane(plane, varying_flag, from, to, from_data, to_data)) { \
+ buffer->count = 0;/*cull this triangle*/ \
+ return 1; \
+ }
+
+ClippedBuffer clip_buffer;
+ClippedBuffer temp_clip_buffer;
+
+bool clip_triangle(
+ Vec4* c0, Vec4* c1, Vec4* c2
+ , Vert* v0, Vert* v1, Vert* v2
+ , uint varying_flag
+ , ClippedBuffer* buffer
+) {
bool is_visible = is_vertex_visible(c0)
&& is_vertex_visible(c1)
&& is_vertex_visible(c2);
- if (is_visible) {
+ if (is_visible)
return 0; /*no need to clip*/
+
+ ssr_assert(buffer == &clip_buffer);
+
+ /*copy vert data to temp_clip_buffer*/
+ temp_clip_buffer.count = 3;
+#define COPY_VERT(i) \
+ temp_clip_buffer.vertices[i].clip_coord = *c##i; \
+ temp_clip_buffer.vertices[i].vertex = *v##i; \
+ temp_clip_buffer.vertices[i].vertex.index = ##i; \
+
+ COPY_VERT(0);
+ COPY_VERT(1);
+ COPY_VERT(2);
+
+#undef COPY_VERT
+
+ int i, index, size;
+ for (i = 0; i < REG_TOTAL; ++i) {
+ index = open_regsi[i];
+ if (index == -1) break;
+ size = registers[index].element_size;
+ ssrM_copy(&temp_clip_buffer_data[index][0], &registers[index].data[v0->index*size], size);
+ ssrM_copy(&temp_clip_buffer_data[index][size], &registers[index].data[v1->index*size], size);
+ ssrM_copy(&temp_clip_buffer_data[index][2*size], &registers[index].data[v2->index*size], size);
}
-//
-// /*clipping it*/
-//
-// /*copy vert data to clip_buffer*/
-// clip_buffer.count = 3;
-//#define INIT_CLIP_VERT(idx) \
-// clip_buffer.vertices[idx].clip_coord = *c##idx; \
-// clip_buffer.vertices[idx].vertex = *v##idx; \
-// if (varying_flag & VARYING_ANY) { \
-// int i = 0; \
-// if(varying_flag & VARYING_NUM) { \
-// for (i = 0; i < REG_NUM_COUNT; ++i) { \
-// if (varying_flag & (VARYING_NUM_00 << i)) \
-// clip_buffer.vertices[idx].num[i] = reg_num[i].num[v##idx->index]; \
-// } \
-// } \
-// if(varying_flag & VARYING_V2) { \
-// for (i = 0; i < REG_V2_COUNT; ++i) { \
-// if (varying_flag & (VARYING_V2_00 << i)) \
-// clip_buffer.vertices[idx].v2[i] = reg_v2[i].v2[v##idx->index]; \
-// } \
-// } \
-// if(varying_flag & VARYING_V3) { \
-// for (i = 0; i < REG_V3_COUNT; ++i) { \
-// if (varying_flag & (VARYING_V3_00 << i)) \
-// clip_buffer.vertices[idx].v3[i] = reg_v3[i].v3[v##idx->index]; \
-// } \
-// } \
-// if(varying_flag & VARYING_V4) { \
-// for (i = 0; i < REG_V4_COUNT; ++i) { \
-// if (varying_flag & (VARYING_V4_00 << i)) \
-// clip_buffer.vertices[idx].v4[i] = reg_v4[i].v4[v##idx->index]; \
-// } \
-// } \
-// }
-// INIT_CLIP_VERT(0);
-// INIT_CLIP_VERT(1);
-// INIT_CLIP_VERT(2);
-//#undef INIT_CLIP_VERT
-//
-// CLIP(POSITIVE_W, &clip_buffer, buffer);
-// CLIP(POSITIVE_X, buffer, &clip_buffer);
-// CLIP(NEGATIVE_X, &clip_buffer, buffer);
-// CLIP(POSITIVE_Y, buffer, &clip_buffer);
-// CLIP(NEGATIVE_Y, &clip_buffer, buffer);
-// CLIP(POSITIVE_Z, buffer, &clip_buffer);
-// CLIP(NEGATIVE_Z, &clip_buffer, buffer);
-//
-// return 1;
+
+ CLIP(POSITIVE_W, &temp_clip_buffer, buffer, temp_clip_buffer_data, clip_buffer_data);
+ CLIP(POSITIVE_X, buffer, &temp_clip_buffer, clip_buffer_data, temp_clip_buffer_data);
+ CLIP(NEGATIVE_X, &temp_clip_buffer, buffer, temp_clip_buffer_data, clip_buffer_data);
+ CLIP(POSITIVE_Y, buffer, &temp_clip_buffer, clip_buffer_data, temp_clip_buffer_data);
+ CLIP(NEGATIVE_Y, &temp_clip_buffer, buffer, temp_clip_buffer_data, clip_buffer_data);
+ CLIP(POSITIVE_Z, buffer, &temp_clip_buffer, clip_buffer_data, temp_clip_buffer_data);
+ CLIP(NEGATIVE_Z, &temp_clip_buffer, buffer, temp_clip_buffer_data, clip_buffer_data);
+
+ return 1;
}