Implement 3 visibility cases in new clipping
This commit is contained in:
parent
5b9a0502b5
commit
30ef3efcc3
167
GL/flush.c
167
GL/flush.c
|
@ -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) */
|
||||
it->triangle_count++;
|
||||
if(it->triangle_count > 3) it->triangle_count = 3;
|
||||
if(new_vertex) {
|
||||
it->triangle_count++;
|
||||
} 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,63 +174,102 @@ ListIterator* _glIteratorNext(ListIterator* it) {
|
|||
return it;
|
||||
}
|
||||
|
||||
if(!isVertex(it->current)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* OK, by this point we should have info for a complete triangle
|
||||
* including visibility */
|
||||
switch(it->visibility) {
|
||||
case B111:
|
||||
/* Totally visible, return the first vertex */
|
||||
it->it = it->triangle[0];
|
||||
return it;
|
||||
break;
|
||||
case B100: {
|
||||
/* First visible only */
|
||||
Vertex* gen2 = push_stack(it);
|
||||
Vertex* gen1 = push_stack(it);
|
||||
|
||||
/* Make sure we transfer the flags.. we don't
|
||||
* want to disrupt the strip */
|
||||
gen1->flags = it->triangle[1]->flags;
|
||||
gen2->flags = it->triangle[2]->flags;
|
||||
|
||||
interpolate_vertex(it->triangle[0], it->triangle[1], gen1);
|
||||
interpolate_vertex(it->triangle[0], it->triangle[2], gen2);
|
||||
it->visibility = B111; /* All visible now, yay! */
|
||||
|
||||
assert(isVisible(gen1));
|
||||
assert(isVisible(gen2));
|
||||
assert(isVertex(gen1));
|
||||
assert(isVertex(gen2));
|
||||
|
||||
it->it = it->triangle[0];
|
||||
|
||||
/* We're returning v0, and we've pushed
|
||||
* 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--;
|
||||
return it;
|
||||
} break;
|
||||
}
|
||||
/* 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(!shift(it, current_postinc(it))) {
|
||||
printf("List end!\n");
|
||||
return NULL;
|
||||
} else {
|
||||
printf("Shifted\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* OK, by this point we should have info for a complete triangle
|
||||
* including visibility */
|
||||
switch(it->visibility) {
|
||||
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: {
|
||||
/* First visible only */
|
||||
Vertex* gen2 = push_stack(it);
|
||||
Vertex* gen1 = push_stack(it);
|
||||
|
||||
/* Make sure we transfer the flags.. we don't
|
||||
* want to disrupt the strip */
|
||||
gen1->flags = it->triangle[1]->flags;
|
||||
gen2->flags = it->triangle[2]->flags;
|
||||
|
||||
interpolate_vertex(it->triangle[0], it->triangle[1], gen1);
|
||||
interpolate_vertex(it->triangle[0], it->triangle[2], gen2);
|
||||
it->visibility = B111; /* All visible now, yay! */
|
||||
|
||||
assert(isVisible(gen1));
|
||||
assert(isVisible(gen2));
|
||||
assert(isVertex(gen1));
|
||||
assert(isVertex(gen2));
|
||||
|
||||
it->it = it->triangle[0];
|
||||
|
||||
/* We're returning v0, and we've pushed
|
||||
* v1 and v2 to the stack, so next time
|
||||
* around we'll need to consume and shift
|
||||
* the next vertex from the source list */
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in New Issue
Block a user