Reputation: 861
I'm looking to draw a continuous and curvy line in OpenGL with an arbitrary width. I am developing for a touch screen and have already achieved the desired effect by drawing lines between the old X & Y coordinates and the new X & Y coordinates. As the user swipes their finger across the screen, this produces a line following their finger. To ensure the line was smooth, I used the following:
pGL.glEnable(GL10.GL_LINE_SMOOTH);
pGL.glHint(GL10.GL_LINE_SMOOTH_HINT, GL10.GL_NICEST);
However, this essentially means I cannot control the width of the line, as it always defaults to 1. Therefore, I concluded that I'm going to have to come up with some other way to create this effect.
Upvotes: 1
Views: 3740
Reputation: 162164
Instead of a line use a quad strip or a triangle strip, centered along the stroke, and with the desired width.
Drawing a thick line using quads or triangles is done the following way:
The upper left 3×3 submatrix of the modelview is the rotational part. You want to draw the line with thicknes in screen space, i.e. reverse the local rotation. To do this you need the inverse of the modelview rotation. Rotations are orthogonal transformations, so inverse(M) = transpose(M)
.
Technically we're interested in only the reverse projected Z axis "Z_local". We can simply take the 3rd row vector of the modelview matrix for this, with the last element "w" being set to zero and the whole vector normalized, i.e.
Z_local_i = MV_i,3
Next we need the line tangent vector. This is as simple as the direction between the line segments. Or more mathematically, if the line is described by a function C(t), then the tangent is
T=∂C(t)/∂t
We can now take the cross product between tangent and Z_local, giving us a normal
N(t) = Z_local × T(t)
Adding the normal N(t) to C(t) gives us a equidistant curve parallel to C. This allows us to draw quads:
for t in range(0, T):
T = deriv(C(t), t)
N = cross(Z_local, T)
emit_vertex(C(t) + width*N)
emit_vertex(C(t) - width*N)
Upvotes: 3