add lines

This commit is contained in:
Konstantin Käfer
2014-02-18 11:11:46 +01:00
parent f7485577e8
commit 5e129c5f5a
2 changed files with 77 additions and 118 deletions

View File

@@ -35,25 +35,25 @@ FillBucket::FillBucket(const std::shared_ptr<FillVertexBuffer>& vertexBuffer,
const std::shared_ptr<LineElementsBuffer>& lineElementsBuffer,
const BucketDescription& bucket_desc)
: geom_desc(bucket_desc.geometry),
allocator(new TESSalloc {
&alloc,
&realloc,
&free,
nullptr, // userData
64, // meshEdgeBucketSize
64, // meshVertexBucketSize
32, // meshFaceBucketSize
64, // dictNodeBucketSize
8, // regionBucketSize
128, // extraVertices allocated for the priority queue.
}),
tesselator(tessNewTess(allocator)),
vertexBuffer(vertexBuffer),
triangleElementsBuffer(triangleElementsBuffer),
lineElementsBuffer(lineElementsBuffer),
vertex_start(vertexBuffer->index()),
triangle_elements_start(triangleElementsBuffer->index()),
line_elements_start(lineElementsBuffer->index()) {
allocator(new TESSalloc {
&alloc,
&realloc,
&free,
nullptr, // userData
64, // meshEdgeBucketSize
64, // meshVertexBucketSize
32, // meshFaceBucketSize
64, // dictNodeBucketSize
8, // regionBucketSize
128, // extraVertices allocated for the priority queue.
}),
tesselator(tessNewTess(allocator)),
vertexBuffer(vertexBuffer),
triangleElementsBuffer(triangleElementsBuffer),
lineElementsBuffer(lineElementsBuffer),
vertex_start(vertexBuffer->index()),
triangle_elements_start(triangleElementsBuffer->index()),
line_elements_start(lineElementsBuffer->index()) {
assert(tesselator);
}
@@ -101,65 +101,78 @@ void FillBucket::tessellate() {
// First combine contours and then triangulate, this removes unnecessary inner vertices.
if (tessTesselate(tesselator, TESS_WINDING_POSITIVE, TESS_BOUNDARY_CONTOURS, 0, 0, 0)) {
const TESSreal *vertices = tessGetVertices(tesselator);
const int contour_element_count = tessGetElementCount(tesselator);
const TESSindex *contour_elements_p = tessGetElements(tesselator);
std::vector<TESSindex> contour_elements = { contour_elements_p, contour_elements_p + contour_element_count * 2 };
const int vertex_count = tessGetVertexCount(tesselator);
const int element_count = tessGetElementCount(tesselator);
const TESSindex *elements = tessGetElements(tesselator);
for (int i = 0; i < contour_element_count; ++i) {
const TESSindex group_start = contour_elements[i * 2];
const TESSindex group_count = contour_elements[i * 2 + 1];
if (vertex_count > 65536) {
throw geometry_too_long_exception();
}
for (int i = 0; i < vertex_count; ++i) {
vertexBuffer->add(vertices[i * 2], vertices[i * 2 + 1]);
}
if (!lineGroups.size() || (lineGroups.back().vertex_length + vertex_count > 65535)) {
// Move to a new group because the old one can't hold the geometry.
lineGroups.emplace_back();
}
// We're generating triangle fans, so we always start with the first
// coordinate in this polygon.
line_group_type& group = lineGroups.back();
uint32_t index = group.vertex_length;
for (int i = 0; i < element_count; ++i) {
const TESSindex group_start = elements[i * 2];
const TESSindex group_end = group_start + elements[i * 2 + 1];
for (int i = group_start; i < group_end; ++i) {
const TESSindex prevI = (i == group_start ? group_end : i) - 1;
lineElementsBuffer->add(index + prevI, index + i);
}
}
// Add a line from the last vertex to the first vertex.
// lineElementsBuffer->add(index + vertex_count - 1, index);
group.vertex_length += vertex_count;
group.elements_length += vertex_count;
for (int i = 0; i < element_count; ++i) {
const TESSindex group_start = elements[i * 2];
const TESSindex group_count = elements[i * 2 + 1];
const TESSreal *group_vertices = &vertices[group_start * 2];
tessAddContour(tesselator, 2, group_vertices, stride, group_count);
}
if (tessTesselate(tesselator, TESS_WINDING_POSITIVE, TESS_POLYGONS, vertices_per_group, 2, 0)) {
const TESSreal *vertices = tessGetVertices(tesselator);
const TESSindex *vertex_indices = tessGetVertexIndices(tesselator);
const int vertex_count = tessGetVertexCount(tesselator);
const TESSindex *elements = tessGetElements(tesselator);
const int element_count = tessGetElementCount(tesselator);
if (vertex_count > 65536) {
throw geometry_too_long_exception();
if (!triangleGroups.size() || (triangleGroups.back().vertex_length + vertex_count > 65535)) {
// Move to a new group because the old one can't hold the geometry.
triangleGroups.emplace_back();
}
// Add vertices and create reverse index mapping for drawing the outline.
// std::map<TESSindex, int> contour_vertices;
for (int i = 0; i < vertex_count; ++i) {
// contour_vertices[vertex_indices[i]] = i;
vertexBuffer->add(vertices[i * 2], vertices[i * 2 + 1]);
// We're generating triangle fans, so we always start with the first
// coordinate in this polygon.
triangle_group_type& group = triangleGroups.back();
uint32_t index = group.vertex_length;
for (int i = 0; i < element_count; ++i) {
const TESSindex *element_group = &elements[i * vertices_per_group];
const TESSindex a = vertex_indices[element_group[0]];
const TESSindex b = vertex_indices[element_group[1]];
const TESSindex c = vertex_indices[element_group[2]];
triangleElementsBuffer->add(index + a, index + b, index + c);
}
{
if (!triangleGroups.size() || (triangleGroups.back().vertex_length + vertex_count > 65535)) {
// Move to a new group because the old one can't hold the geometry.
triangleGroups.emplace_back();
}
// We're generating triangle fans, so we always start with the first
// coordinate in this polygon.
triangle_group_type& group = triangleGroups.back();
uint32_t index = group.vertex_length;
for (int i = 0; i < element_count; ++i) {
const TESSindex *element_group = &elements[i * vertices_per_group];
if (element_group[0] == TESS_UNDEF || element_group[1] == TESS_UNDEF || element_group[2] == TESS_UNDEF) {
throw std::runtime_error("element group is not a triangle");
}
triangleElementsBuffer->add(
index + element_group[0],
index + element_group[1],
index + element_group[2]
);
}
group.vertex_length += vertex_count;
group.elements_length += element_count;
}
group.vertex_length += vertex_count;
group.elements_length += element_count;
} else {
assert(false && "tesselation failed");

View File

@@ -180,50 +180,6 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons
fill_color[2] *= properties.opacity;
fill_color[3] *= properties.opacity;
// // Draw the stencil mask.
// {
// // We're only drawing to the first seven bits (== support a maximum of
// // 127 overlapping polygons in one place before we get rendering errors).
// glStencilMask(0x3F);
// glClear(GL_STENCIL_BUFFER_BIT);
// // Draw front facing triangles. Wherever the 0x80 bit is 1, we are
// // increasing the lower 7 bits by one if the triangle is a front-facing
// // triangle. This means that all visible polygons should be in CCW
// // orientation, while all holes (see below) are in CW orientation.
// glStencilFunc(GL_NOTEQUAL, 0x80, 0x80);
// if (properties.winding == Winding::EvenOdd) {
// // When we draw an even/odd winding fill, we just invert all the bits.
// glStencilOp(GL_INVERT, GL_KEEP, GL_KEEP);
// } else {
// // When we do a nonzero fill, we count the number of times a pixel is
// // covered by a counterclockwise polygon, and subtract the number of
// // times it is "uncovered" by a clockwise polygon.
// glStencilOpSeparate(GL_FRONT, GL_INCR_WRAP, GL_KEEP, GL_KEEP);
// glStencilOpSeparate(GL_BACK, GL_DECR_WRAP, GL_KEEP, GL_KEEP);
// }
// // When drawing a shape, we first draw all shapes to the stencil buffer
// // and incrementing all areas where polygons are
// glColorMask(false, false, false, false);
// // Draw the actual triangle fan into the stencil buffer.
// useProgram(plainShader->program);
// plainShader->setMatrix(matrix);
// // Draw all groups
// bucket.drawElements(*plainShader);
// // Now that we have the stencil mask in the stencil buffer, we can start
// // writing to the color buffer.
// glColorMask(true, true, true, true);
// }
// From now on, we don't want to update the stencil buffer anymore.
// glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
// glStencilMask(0x0);
// Because we're drawing top-to-bottom, and we update the stencil mask
// below, we have to draw the outline first (!)
if (properties.antialias) {
@@ -252,9 +208,6 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons
bucket.drawVertices(*outlineShader);
}
// // Only draw regions that we marked
// glStencilFunc(GL_NOTEQUAL, 0x0, 0x3F);
if (false && properties.image.size() && *style.sprite) {
// Draw texture fill
ImagePosition imagePos = style.sprite->getPosition(properties.image, true);
@@ -285,7 +238,6 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons
// Draw a rectangle that covers the entire viewport.
coveringPatternArray.bind(*patternShader, tileStencilBuffer, BUFFER_OFFSET(0));
glDrawArrays(GL_TRIANGLES, 0, tileStencilBuffer.index());
} else {
// Draw filling rectangle.
useProgram(plainShader->program);
@@ -294,13 +246,7 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons
// Draw the actual triangle fan into the stencil buffer.
bucket.drawElements(*plainShader);
// Draw a rectangle that covers the entire viewport.
// coveringPlainArray.bind(*plainShader, tileStencilBuffer, BUFFER_OFFSET(0));
// glDrawArrays(GL_TRIANGLES, 0, tileStencilBuffer.index());
}
// glStencilFunc(GL_EQUAL, 0x80, 0x80);
}
void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, const Tile::ID& id) {