# Offset line

I’m using VBO to draw a 1,000,000 points line strip.

I need to draw the line in black and two red lines as borders (I’ve attached example image file).

Is there a way to manipulate the matrices or do any other thing to draw the borders ?

This looks like all you need to do is to translate the red border lines, so all you need to do is to multiply the model matrix by a translation matrix.

If you will check again the image, you will notice that the red border lines are not just offset from the black line,

They are kind of longer\shorter on the corners depends which side is the border.

How about simply drawing the line 3 times at different widths (using glLineWidth). Draw a fat, red, line, then a medium width white line, followed by a narrow black line. Turn Z buffering off and draw them on top of each other using the same set of vertices. No math necessary.

I thought about it already. but the case is that i need to see what is behind the lines… if i will draw wider main (black) line it will block what is behind it.

To make it simple for understand (or harder to implement - i guess) - i need to draw just the red lines. between the lines should be nothing.

any more suggestions ?

Imagnine there is a ‘normal vector’ at every vertex at the black line. You could translate every corresponding vertex of the red lines along this normal, which should yield the result you want.

If you are able to calculate all normals so that they all point in approximately the same direction (i.e. all pointing downwards or all pointing upwards) it should be easy generating the vertices for the border lines.

Calculating the ‘normal’ probably works like that: (I didn’t test it)

-Choose a vertex
-Calculate 2 vectors describing the direction of the two adjacent lines
-find the largest angle alpha in between them (if both are 180 degrees choose one randomly)
-Create the normal by rotating it alpha/2.0 degrees
-If the normal is pointing upwards negate it (or do the opposite, negate all normals pointing downwards, doesn’t matter)

-Repeat for all other vertices

You need some other solution for the leftmost and rightmost vertices of course, maybe by simply setting the normal to (0.0, 1.0) or (0.0, -1.0) or calculating a normal orthogonal to the only line that’s connected with this vertex (which is probably the better solution)

What about just scaling them up and down ? If the origin is at the center of the black line, it should be possible. Add a little translation and you’ll have this.

First of all, Thanks for the answers.
But,

arts, if you will see, you will realize that its not simply scaling and transforming issue… the vertexes are supposed to grow and shrink depends on the angle created by the two lines its connected to.

AleaIactaEst, The thing is that i don’t want to calculate it all the time. I’m drawing complex lines with complex styles. and do that will cause lots of pre-calculations and time of loading.
But, i will try to write a vertex shader, and using the vertex attributes.

Correct me if i got you wrong

You got me right, i though calculating the vertices of the border lines on the cpu once will be fine. But even if your lines are changing dynamically, if 99% of your vertices stay the same from one frame to the next, you’ll still be able to calculate the border lines efficient on the cpu, by updating only the relevant parts.

The very same algorithm could also be implemented in the vertex shader of course, which is probably the best solution if the vertices change very often.

Great…

I will try it out and let you know.

Thanks man

Here’s a solution that requires no math, but you must draw your line 4 times. It uses the depth buffer to ‘mask’ out the middle portion of a thick red line. The depth mask is created by drawing a thinner version of the same line first. I also draw points at the vertices to clean up the joints where the lines come together. Comment out the point drawing and you’ll see what I mean. I’m sure this same approach could be done more elegantly, maybe using stencil planes. I’m more comfortable using the depth buffer.

``````void Hollow_Lines (void)
{
short v;
static float Line[5][2] = {{-1,-1},{-0.5,0.5},{1,-1.5},{2.5,-1},{3.5,.5}};

glEnable (GL_DEPTH_TEST);

glEnable    (GL_BLEND                            );
glEnable    (GL_LINE_SMOOTH                      );
glEnable    (GL_POINT_SMOOTH                     );
glHint      (GL_LINE_SMOOTH_HINT, GL_NICEST      );
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

// Write 'invisible' thin version of line into into depth buffer only.

glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);   // Disables RGBA

glLineWidth (4.0);
glPointSize (3.0);

glPushMatrix ();
glTranslatef (0,0,0.001);   // Puts thin line if 'front' of thick line.
glBegin (GL_LINE_STRIP);
for (v = 0; v < 5; v++)  glVertex2fv (Line[v]);
glEnd ();
glBegin (GL_POINTS);
for (v = 0; v < 5; v++)  glVertex2fv (Line[v]);
glEnd ();
glPopMatrix();

// Write visible, thick, red, version of line.

glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);   // Enable RGBA

glLineWidth (10.0);
glColor3f (1.0, 0.2, 0.2);
glBegin (GL_LINE_STRIP);
for (v = 0; v < 5; v++)  glVertex2fv (Line[v]);
glEnd ();

glPointSize (10.0);    // Use points at each vertex to clean up joints.
glColor3f (1.0, 0.2, 0.2);
glBegin (GL_POINTS);
for (v = 1; v < 4; v++)  glVertex2fv (Line[v]);
glEnd ();  // Try 0 and 5 here to put nice ends on the lines.
}

``````

Found time for it today.