Implement 3 visibility cases in new clipping

This commit is contained in:
Luke Benstead 2020-10-29 22:04:32 +00:00
parent 5b9a0502b5
commit 30ef3efcc3
2 changed files with 234 additions and 61 deletions

View File

@ -138,8 +138,17 @@ GL_FORCE_INLINE GLboolean shift(ListIterator* it, Vertex* new_vertex) {
* Shifts in a new vertex, dropping the oldest. If
* new_vertex is NULL it will return GL_FALSE (but still
* shift) */
if(new_vertex) {
it->triangle_count++;
if(it->triangle_count > 3) it->triangle_count = 3;
} else {
// We shifted a NULL, so we're reducing
// the available count rather than increasing
it->triangle_count--;
}
if(it->triangle_count > 3) {
it->triangle_count = 3;
}
it->triangle[0] = it->triangle[1];
it->triangle[1] = it->triangle[2];
@ -153,10 +162,7 @@ GL_FORCE_INLINE GLboolean shift(ListIterator* it, Vertex* new_vertex) {
}
ListIterator* _glIteratorNext(ListIterator* it) {
/* None remaining in the list, and the stack is empty */
if(!it->remaining && it->stack_idx == -1) {
return NULL;
}
printf("R: %d\n", it->remaining);
/* Return any vertices we generated */
if(it->stack_idx > -1) {
@ -168,21 +174,36 @@ ListIterator* _glIteratorNext(ListIterator* it) {
return it;
}
if(!isVertex(it->current)) {
/* None remaining in the list, and the stack is empty */
if(!it->remaining && !it->triangle_count) {
printf("None left\n");
return NULL;
}
_Bool retry = 1;
while(retry) {
retry = 0;
_Bool is_header = !isVertex(it->current);
/* If we hit a header, and we have vertices still
* not returned, shift them out and return them */
if(is_header && it->triangle_count) {
shift(it, NULL);
it->it = it->triangle[0];
printf("Returning before header\n");
return it;
} else if(is_header) {
printf("Header\n");
return header_reset(it, current_postinc(it));
} else {
/* Make sure we have a full triangle of vertices */
while(it->triangle_count < 3) {
if(!isVertex(it->current)) {
return header_reset(it, current_postinc(it));
}
if(!shift(it, current_postinc(it))) {
/* We reached the end so just
* return the oldest until they're gone */
it->it = it->triangle[0];
printf("Bailing early!\n");
return (it->it) ? it : NULL;
printf("List end!\n");
return NULL;
} else {
printf("Shifted\n");
}
}
@ -192,6 +213,8 @@ ListIterator* _glIteratorNext(ListIterator* it) {
case B111:
/* Totally visible, return the first vertex */
it->it = it->triangle[0];
it->triangle_count--;
printf("All here!\n");
return it;
break;
case B100: {
@ -219,12 +242,34 @@ ListIterator* _glIteratorNext(ListIterator* it) {
* v1 and v2 to the stack, so next time
* around we'll need to consume and shift
* the next vertex from the source list */
it->triangle_count--;
while(it->triangle_count) {
shift(it, NULL);
}
return it;
} break;
case B000: {
/* If a triangle is invisible, there are 3 situations:
*
* 1. It's the last triangle, so we end here
* 2. It was the last triangle before a header, in which
* case we return the header
* 3. It was not the last triangle in the strip, so we just
* go around again to shift the next vertex (we don't return
* anything because it's invisible...) */
if(!it->remaining) {
return NULL;
} else if(!isVertex(it->current)) {
return header_reset(it, current_postinc(it));
} else {
it->triangle_count--;
retry = 1;
}
} break;
}
}
}
printf("Fall through\n");
return NULL;
}

View File

@ -50,6 +50,17 @@ private:
AlignedVector list_;
};
#define assert_vertex_equal(v, x, y, z) \
assert_is_not_null(v); \
printf("> %f, %f, %f\n", v->xyz[0], v->xyz[1], v->xyz[2]); \
assert_equal(v->xyz[0], x); \
assert_equal(v->xyz[1], y); \
assert_equal(v->xyz[2], z); \
#define assert_is_header(v) \
assert_false(isVertex(v)); \
class NearZClippingTests : public gldc::test::GLdcTestCase {
public:
void test_clipping_100() {
@ -93,11 +104,101 @@ public:
}
void test_clipping_110() {
/* First two vertices are visible, so we need to
* generate 2 vertices and manipulate the strip */
VertexBuilder builder;
auto list = builder.
add_header().
add(1, 1, 2, 1).
add(1, 0, 2, 1).
add_last(0, 1, 2, -1).done();
ListIterator* it = _glIteratorBegin(list.first, list.second);
Vertex* v0 = it->it;
assert_is_not_null(v0);
assert_false(isVertex(v0)); // Should be a header
it = _glIteratorNext(it);
assert_is_not_null(it);
Vertex* v1 = it->it;
assert_is_not_null(v1);
assert_true(isVertex(v1));
it = _glIteratorNext(it);
assert_is_not_null(it);
Vertex* v2 = it->it;
assert_is_not_null(v2);
assert_true(isVertex(v2));
it = _glIteratorNext(it);
assert_is_not_null(it);
Vertex* v3 = it->it;
assert_is_not_null(v3);
assert_true(isVertex(v3));
it = _glIteratorNext(it);
assert_is_not_null(it);
Vertex* v4 = it->it;
assert_is_not_null(v4);
assert_true(isVertex(v4));
it = _glIteratorNext(it);
assert_is_null(it);
}
void test_clipping_111() {
/* All vertices are visible, list should be
* totally unchanged */
VertexBuilder builder;
/* 2 triangle strips, with positive W coords */
auto list = builder.
add_header().
add(1, 1, 2, 1).
add(1, 0, 2, 1).
add_last(0, 1, 2, 1).
add_header().
add(1, 1, 2, 1).
add(1, 0, 2, 1).
add_last(0, 1, 2, 1).done();
ListIterator* it = _glIteratorBegin(list.first, list.second);
assert_is_not_null(it);
assert_is_header(it->it);
it = _glIteratorNext(it);
assert_is_not_null(it);
assert_vertex_equal(it->it, 1, 1, 2);
it = _glIteratorNext(it);
assert_is_not_null(it);
assert_vertex_equal(it->it, 1, 0, 2);
it = _glIteratorNext(it);
assert_is_not_null(it);
assert_vertex_equal(it->it, 0, 1, 2);
it = _glIteratorNext(it);
assert_is_not_null(it);
assert_is_header(it->it);
it = _glIteratorNext(it);
assert_is_not_null(it);
assert_vertex_equal(it->it, 1, 1, 2);
it = _glIteratorNext(it);
assert_is_not_null(it);
assert_vertex_equal(it->it, 1, 0, 2);
it = _glIteratorNext(it);
assert_is_not_null(it);
assert_vertex_equal(it->it, 0, 1, 2);
it = _glIteratorNext(it);
assert_is_null(it);
}
void test_clipping_101() {
@ -113,7 +214,34 @@ public:
}
void test_clipping_000() {
/* If no vertices are visible, they should be culled
* we (currently) leave headers as removing them before
* submission is too costly */
VertexBuilder builder;
/* 2 triangle strips, with negative W coords */
auto list = builder.
add_header().
add(1, 1, 2, -1).
add(1, 0, 2, -1).
add_last(0, 1, 2, -1).
add_header().
add(1, 1, 2, -1).
add(1, 0, 2, -1).
add_last(0, 1, 2, -1).done();
ListIterator* it = _glIteratorBegin(list.first, list.second);
assert_is_not_null(it);
assert_is_header(it->it);
it = _glIteratorNext(it);
assert_is_not_null(it);
assert_is_header(it->it);
// Done!
it = _glIteratorNext(it);
assert_is_null(it);
}
void test_clipping_011() {