Path stroke algorithm (convert to triangles/quads) or other suggestions - c++

Does anyone know a good algorithm for converting a vector path into a stroked path that is composed of triangle/quad faces? Ideally with round line joins.
Basically I am trying to draw a thick path that whose colour is based upon a value that varies with the distance along the path. I'm thinking that converting the path to triangles/quads and texture mapping it by providing the distance along the path as a 1d texture coordinate that can then be used to retrieve the colours at the corners of the triangles and interpolate.
Any other suggestions on how to do this that won't look terrible and can be anti-aliased would be appreciated.
I'm using AGG for rendering, currently, but I could maybe use an alternative provided it doesn't have too many dependencies. I guess the back-end used for rendering doesn't really matter. Whilst AGG can stroke paths, the VertexSource interface does not allow for additional vertex information other than the x/y coordinates. Additionally getting my colour mapping into the rasterizer doesn't look feasible when using the normal conv_stroke.

Here's another great resource for understanding the mechanics of stroking a path.

For anyone looking for a solution to this, I found this useful:
https://keithp.com/~keithp/talks/cairo2003.pdf
So you can effectively convolve a regular polygon with the line to generate the mesh. Requires a slightly more complicated algorithm than outlined in the pdf in order to output triangles, but it's not actually too difficult to extend it.
You can also write a custom span generator for AGG along the lines of agg::span_gouraud_rgba but one that effectively does texture mapping instead.

Related

How to mesh a 2D point cloud in C++

I have a set of 2D points of a known density I want to mesh by taking the holes in account. Basically, given the following input:
I want something link this:
I tried PCL ConcaveHull, but it doens't handle the holes and splitted mesh very well.
I looked at CGAL Alpha shapes, which seems to go in the right direction (creating a polygon from a point cloud), but I don't know how to get triangles after that.
I though of passing the resulting polygons to a constrained triangulation algorithm and mark domains, but I didn't find how to get a list of polygons.
The resulting triangulated polygon is about a two step process at the least. First you need to triangulate your 2D points (using something like a Delaunay2D algorithm). There you can set the maximum length for the triangles and get the the desired shape. Then you can decimate the point cloud and re-triangulate. Another option is to use the convex hull to get the outside polygon, then extract the inside polygon through a TriangulationCDT algorithm, the apply some PolygonBooleanOperations, obtain the desired polygon, and finaly re-triangulate.
I suggest you look into the Geometric Tools library and specifically the Geometric Samples. I think everything you need is in there, and is much less library and path heavy than CGAL (the algorithms are not free for this type of work unless is a school project) or the PCL (I really like the library for segmentation, but their triangulation breaks often and is slow).
If this solves your problem, please mark it as your answer. Thank you!

OpenGL : thick and smooth/non-broken lines *in 3D*

I have a 3D CAD-like application for which I use OpenGL wrapper library (OpenSceneGraph). For the application I am trying to come up with the best strategy on how to render thick and smooth lines in 3D.
By thick and smooth I mean:
line thickness can be more than OpenGL maximum linewidth value (it seems to be 10.f on my machine)
when composing polylines I want to avoid the look of "broken lines" (see example image below)
At the moment I render my polylines by using GL_LINE_STRIP_ADJACENCY.
I found there are many different resources on how to render nice looking lines and curves in 2D. The simplest approach that does not require much thinking is to render the line as a set of quads (GL_QUAD_STRIP). The good thing about this solution is that it solves both of my problems at the same time.
As an example, I also found this nice library that allows to achieve wide range of line and curve looks. It uses triangles for rendering.
Note: I do not seek for fancy effects like per-vertex coloring or brush-like strokes, just a 3D line segment that can have large thickness and that connects well with another line segment without any gaps between them.
The problem with those 2D approaches is that they are 2D. When I change the view point, it is obvious my line geometries are not lines but rather 2D "ribbons" lying in certain 3D planes. And I want them to look like 3D lines.
When thinking about the problem, I could only come up the the following approaches:
Render line as a set of 2D quads (triangles) and then make them to always face the camera
Use some 3D shape like cylinder to represent a line segment
I am not sure how feasible any of the two solutions are (I am beginner in OpenGL). I might have hundreds or even thousands of polylines on the scene. I am also wondering if there is a better, smarter way to approach the problem? I am open to anything and interested in the most efficient way. Thank you.
EDIT: as pointed by user #rickyviking, I didn't clarify explicitly that I am going after a 2D look (like in any CAD-like app) which would mean: the thickness of the lines does not depend on how far/near the camera is located from them.
UPDATE: thanks for answer of #rickyviking, I chose the direction to move with - geometry shaders. I still do not have a complete solution, but might post a final update and minimal code when the result is achieved, here.
I ended up using geometry shader as was suggested by one of the answers. The main idea was to convert every line segment into a triangular strip and to make sure that it always faces the camera and thickness remains the same.
I also wrote a blog post about the implementation details. If someone finds it useful, I placed the shader codes on one of my github repos (the code also provides example on how to draw thick and smooth Bezier curves using the same technique).
Here are some result screenshots (green lines are drawn using the shaders, red are by using GL_LINE_STRIP_ADJACENCY):
Note the gaps between the adjacent line segments of the red lines compared to the green ones.
Two Bezier curves (all drawn using the shaders):
First of all you need clarify yourself whether the result you're after should "look" 2D or 3D.
When you mention cylinders, they will certainly have a "3D effect" (geometries farther away thinner/smaller than geometries closer to the viewpoint), but that is not what CAD-like applications normally looks like.
I believe you're after a 2D looking result, where the width of your lines is independent from their distance from viewpoint.
When using a library like the one you mention, you should recompute the geometries every time you change your viewpoint (possibly every frame) to have them always face the screen plane.
An alternative and better performing approach would be to use the "solid wireframe" technique, here is an implementation from NVidia, which uses geometry shaders (you can find several examples on how to use them in OpenSceneGraph).
Other similar techniques are shown here: https://forum.libcinder.org/topic/smooth-thick-lines-using-geometry-shader
I don't know too much about it but one of the many interesting things about NVidia's "path rendering" SDK (which was on the face of it just another one of those nice 2D libraries you're talking about) was that it actually put a bit of effort into interoperating with 3D. See the "Eureka: 3D Path Rendering!" section in this whitepaper.
There used to be talk of it becoming a standard (non-vendor-specific) OpenGL extension but I'm not sure it ever happened.
I've used cylinders before, but that was an application that needed actual real-world sizes, varying sizes in one line and even color changing.

Generate volume out of 3d-matrix in cpp

I have a function for generating a 3d-matrix with grey values (char values from 0 to 255). Now I want to generate a 3d-object out of this matrix, e.g. I want to display these values as a 3d-object (in cpp). What is the best way to do that platform-independent and as fast as possible?
I have already read a bit about using OGL, but then I run in the following problem: The matrix can contain up to $4\cdot10^9$ values. When I want to load the complete matrix into the RAM, it will collapse. So a direct draw from the matrix is impossible. Furthermore I only found functions for drawing 2d-images in OGL. Is there a way to draw 3d-pixels in OGL? Or should I rather use another approach?
I do not need a moving functionality (at least not at the moment), I just want to display the data.
Edit 2: For narrowing the question in: Is there a way to draw pixels in 3d-space with OGL taken from a 3d-matrix? I did not find a suitable function, I only found 2d-functions.
What you're looking to do is called volume rendering. There are various techniques to achieve it, and ultimately it depends on what you want it to look like.
There is no simple way to do this either. You can't just draw 3d pixels. You can draw using GL_POINTS and have each transformed point raster to 1 pixel, but this is probably completely unsatisfactory for you because it will only draw a some pixels to the screen (you wont see anything on big resolutions).
A general solution would be to just render a cube using normal triangles, for each point. Sort it back to front if you need alpha blending. If you want a more specific answer you will need to narrow your request. Ray tracing also has merits in volume rendering. Learn more on volume rendering.

what are good mesh animation techniques?

I want to create a 2D game with monsters build as a custom vertex mesh and a texture map. I want to use this mesh to provide smooth vector animations. I'm using opengl es 2.0.
For now the best idea i have is to write a simple editor, where i can create a mesh and make key-frame based animation by changing position of each vertex and specifying the key-frames interpolation technics ( linear, quadric and so on).
I also have some understanding of bone animation (and skin based on bones), but i'm not sure i will be able to provide a good skeletons for my monsters.
I'm not sure it is a good way to go. Can you suggest some better ideas and / or editors, libraries for such mesh animations ?
PS: i'm using C++ now and so c++ libraries are the most welcome
You said this is a 2D game, so I'm going to assume your characters are flat polygons on to which you apply a texture map. Please add more detail to your question if this is not the case.
As far as the C++ part I think the same principles used for 3D blend shape animation can be applied to this case. For each character you will have a list of possible 'morph targets' or poses, each being a different polygon shape with same number of vertices. The character's AI will determine when to change from one to another, and how long a transition takes. So at any given point time your character can be either at a fixed state, matching one of your morph targets, or it can be in a transition state between two poses. The first has no trouble, the second case is handled by interpolating the vertices of the two polygons one by one to arrive to a morphed polygon. You can start with linear interpolation and see if that is sufficient, I suspect you may want to at least apply an easing function to the start and end of the transitions, maybe the smoothstep function.
As far as authoring these characters, have you considered using Blender? You can design and test your characters entirely within this package, then export the meshes as .obj files that you can easily import into your game.

How do I render thick 2D lines as polygons?

I have a path made up of a list of 2D points. I want to turn these into a strip of triangles in order to render a textured line with a specified thickness (and other such things). So essentially the list of 2D points need to become a list of vertices specifying the outline of a polygon that if rendered would render the line. The problem is handling the corner joins, miters, caps etc. The resulting polygon needs to be "perfect" in the sense of no overdraw, clean joins, etc. so that it could feasibly be extruded or otherwise toyed with.
Are there any simple resources around that can provide algorithm insight, code or any more information on doing this efficiently?
I absolutely DO NOT want a full fledged 2D vector library (cairo, antigrain, OpenVG, etc.) with curves, arcs, dashes and all the bells and whistles. I've been digging in multiple source trees for OpenVG implementations and other things to find some insight, but it's all terribly convoluted.
I'm definitely willing to code it myself, but there are many degenerate cases (small segments + thick widths + sharp corners) that create all kinds of join issues. Even a little help would save me hours of trying to deal with them all.
EDIT: Here's an example of one of those degenerate cases that causes ugliness if you were simply to go from vertex to vertex. Red is the original path. The orange blocks are rectangles drawn at a specified width aligned and centered on each segment.
Oh well - I've tried to solve that problem myself. I wasted two month on a solution that tried to solve the zero overdraw problem. As you've already found out you can't deal with all degenerated cases and have zero overdraw at the same time.
You can however use a hybrid approach:
Write yourself a routine that checks if the joins can be constructed from simple geometry without problems. To do so you have to check the join-angle, the width of the line and the length of the joined line-segments (line-segments that are shorter than their width are a PITA). With some heuristics you should be able to sort out all the trivial cases.
I don't know how your average line-data looks like, but in my case more than 90% of the wide lines had no degenerated cases.
For all other lines:
You've most probably already found out that if you tolerate overdraw, generating the geometry is a lot easier. Do so, and let a polygon CSG algorithm and a tesselation algorithm do the hard job.
I've evaluated most of the available tesselation packages, and I ended up with the GLU tesselator. It was fast, robust, never crashed (unlike most other algorithms). It was free and the license allowed me to include it in a commercial program. The quality and speed of the tesselation is okay. You will not get delaunay triangulation quality, but since you just need the triangles for rendering that's not a problem.
Since I disliked the tesselator API I lifted the tesselation code from the free SGI OpenGL reference implementation, rewrote the entire front-end and added memory pools to get the number of allocations down. It took two days to do this, but it was well worth it (like factor five performance improvement). The solution ended up in a commercial OpenVG implementation btw :-)
If you're rendering with OpenGL on a PC, you may want to move the tesselation/CSG-job from the CPU to the GPU and use stencil-buffer or z-buffer tricks to remove the overdraw. That's a lot easier and may be even faster than CPU tesselation.
I just found this amazing work:
http://www.codeproject.com/Articles/226569/Drawing-polylines-by-tessellation
It seems to do exactly what you want, and its licence allows to use it even in commercial applications. Plus, the author did a truly great job to detail his method. I'll probably give it a shot at some point to replace my own not-nearly-as-perfect implementation.
A simple method off the top of my head.
Bisect the angle of each 2d Vertex, this will create a nice miter line. Then move along that line, both inward and outward, the amount of your "thickness" (or thickness divided by two?), you now have your inner and outer polygon points. Move to the next point, repeat the same process, building your new polygon points along the way. Then apply a triangualtion to get your render-ready vertexes.
I ended up having to get my hands dirty and write a small ribbonizer to solve a similar problem.
For me the issue was that I wanted fat lines in OpenGL that did not have the kinds of artifacts that I was seeing with OpenGL on the iPhone. After looking at various solutions; bezier curves and the like - I decided it was probably easiest to just make my own. There are a couple of different approaches.
One approach is to find the angle of intersection between two segments and then move along that intersection line a certain distance away from the surface and treat that as a ribbon vertex. I tried that and it did not look intuitive; the ribbon width would vary.
Another approach is to actually compute a normal to the surface of the line segments and use that to compute the ideal ribbon edge for that segment and to do actual intersection tests between ribbon segments. This worked well except that for sharp corners the ribbon line segment intersections were too far away ( if the inter-segment angle approached 180' ).
I worked around the sharp angle issue with two approaches. The Paul Bourke line intersection algorithm ( which I used in an unoptimized way ) suggested detecting if the intersection was inside of the segments. Since both segments are identical I only needed to test one of the segments for intersection. I could then arbitrate how to resolve this; either by fudging a best point between the two ends or by putting on an end cap - both approaches look good - the end cap approach may throw off the polygon front/back facing ordering for opengl.
See http://paulbourke.net/geometry/lineline2d/
See my source code here : https://gist.github.com/1474156
I'm interested in this too, since I want to perfect my mapping application's (Kosmos) drawing of roads. One workaround I used is to draw the polyline twice, once with a thicker line and once with a thinner, with a different color. But this is not really a polygon, it's just a quick way of simulating one. See some samples here: http://wiki.openstreetmap.org/wiki/Kosmos_Rendering_Help#Rendering_Options
I'm not sure if this is what you need.
I think I'd reach for a tessellation algorithm. It's true that in most case where these are used the aim is to reduce the number of vertexes to optimise rendering, but in your case you could parameterise to retain all the detail - and the possibility of optimising may come in useful.
There are numerous tessellation algorithms and code around on the web - I wrapped up a pure C on in a DLL a few years back for use with a Delphi landscape renderer, and they are not an uncommon subject for advanced graphics coding tutorials and the like.
See if Delaunay triangulation can help.
In my case I could afford to overdraw. I just drow circles with radius = width/2 centered on each of the polyline's vertices.
Artifacts are masked this way, and it is very easy to implement, if you can live with "rounded" corners and some overdrawing.
From your image it looks like that you are drawing box around line segments with FILL on and using orange color. Doing so is going to create bad overdraws for sure. So first thing to do would be not render black border and fill color can be opaque.
Why can't you use GL_LINES primitive to do what you intent to do? You can specify width, filtering, smoothness, texture anything. You can render all vertices using glDrawArrays(). I know this is not something you have in mind but as you are focusing on 2D drawing, this might be easier approach. (search for Textured lines etc.)