SVG in OpenGL

First implementation

The first implementation is a naive one. We tesselate the whole curves (curvature should not exceed one pixel). Then we apply to the polygones generated the ear cutting algorithm.
To save CPU resources, we cache the result (a list of polygons and triangles) until the scale of the vector image changed.

The intersting part is the test of the recursive subdivision of curves: The flatness of the curve.


Quadratic curve flatness In the schema ABC is the convex hull of the quadratic curve. We find F a point on the quadratic curve, by splitting AB in 2, this give us D. We do the same for BC which give us E. And we cut DE in 2 which give us F. Because the curve is recursively made, ABC could also be any part of the curve at any time. To determine the flatness of the curve, we just need to calculate The length of GF. G is the middle of AC.

D = (A+B)/2
E = (B+C)/2
F = (D+E)/2 = (A+C)/4 + B/2
G = (A+C)/2

length(GF) = length (F-G) = length (B/2 - (A+C)/2)
length(GF) = sqrt( sqr(B.x-(A.x+C.x)/2) + sqr(B.y-(A.y+C.y)/2) )

So we should subdivide if the distance of GF is more than one pixel.
The test can be done on the square of the distance sqr(length(GF)) > sqr(1)



The anti-aliasing is done by rendering the polygon generated with anti-aliased lines. This is done with the following OpenGL commands:

      glEnable(GL_LINE_SMOOTH);
      glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);


Tux drawn with lines

Source code and architecture

SVGopenGL class diagram
SVGopenGL - starting point where we aggregate all the parts: a filesystem, a screen, an image vector and an image vector blitter part
Filesystem - knows how to read files even in a trapfile (big file) compressed or not
IScreen - abstraction over a screen that know how to draw triangles (openGL, DX, soft).
ScreenOGL11 - the current implementation for OpenGL 1.1 (quite old but it doesn't matter for what we are showing)
SVertexBuffer - Array of vertices and indices to be given to the screen implementation.

SIimageVector - structure of the image in vector format. Can read a SVG buffer format.
SShape - structure of a shape which is an array of curves (or broken lines if vertices are on the shape).

SImageVectorBlitter - to blit an imagevector structure to a screen. Create a cache holding the vertex buffer and display them.
SImageVectorCache - the cache created in the blitter. Recreates the triangles in the vertex buffer of the screen to be displayed by the blitter.

SShapeTri - triangulate a shape to an array of triangles and indices to be rendered.
ShapeTriCurve - Tesselate curves depending on a pixel ratio to make a polygon.

The source code : SVGopenGL.zip (166 KB)

Limits

The tesselation of the polygons is based on the ear cutting which doesn't handle loops.
Error on cubic bezier curves with loops




Second implementation

1 - Cut the cubic curves in multiple quadratic ones and handle loops.
2 - Check the curves convex hulls doesn't overlap lines of our shape.
3 - Triangulate interiors
4 - Triangulate curves
5 - Create the contour

1,2 and 3 can be done just once.
4 and 5 are done each time the scale factor of the shape changes.






Back to matthPage