diff options
Diffstat (limited to 'src/core/clip.c')
-rw-r--r-- | src/core/clip.c | 383 |
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], ®isters[index].data[v0->index*size], size); + ssrM_copy(&temp_clip_buffer_data[index][size], ®isters[index].data[v1->index*size], size); + ssrM_copy(&temp_clip_buffer_data[index][2*size], ®isters[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; } |