Click here to Skip to main content
15,895,142 members
Articles / Multimedia / OpenGL

Drawing Polylines by Tessellation

Rate me:
Please Sign up or sign in to vote.
4.93/5 (39 votes)
21 Jul 2011CPOL8 min read 126.1K   5.8K   94  
Drawing Polylines by tessellation with joints, caps, feathering and per- vertex color
<!-- steps to put on blogger:
-remove head and body tag

-replace all image links:
--replace src='../sample_images/ by src='http://vaserenderer.sourceforge.net/blog/vaserendererdraft12/

-replace href='line_segment/line_segment.html' by href='http://artgrammer.blogspot.com/2011/05/drawing-nearly-perfect-2d-line-segments.html'

-replace href='polyline/polyline.html' by href='http://artgrammer.blogspot.com/2011/07/drawing-polylines-by-tessellation.html'
-->

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<head>
	<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
	<div class='vaser_wrap'>
		<div class='article_name'>
			<h1>Vase Renderer<img src='../sample_images/V.png' height=80 /></h1>
			first draft, version 0.2 (VaseR draft1_2)
		</div>
		<h2>About</h2>
<p>Vase renderer(VaseR) is a 2D graphics renderer built on top of OpenGL. Unlike most graphics libraries
 which are based on <code>SetPixel()</code>, VaseR is based on <code>glDrawArrays()</code>.
 That means, VaseR takes the advantage of GPU rasterization. Another unique feature of VaseR is rendering
 with premium quality anti- aliasing using "fade polygons", as mentioned in
 <a href='http://artgrammer.blogspot.com/2011/05/drawing-nearly-perfect-2d-line-segments.html' target="_blank">
this article</a>.
</p>
		<h2>Documentation</h2>
			<h3>API design</h3>
<p>VaseR is a renderer and merely translates input vectors into gl calls. VaseR has no states, only a set
 of functions. Thus you need to pass many parameters to a VaseR function on each call. And these
 parameters are stored in structures like WinAPI does. Normally if you do not know what options to set,
 just put <code>0</code> at the parameter <code>polyline_opt*</code>. VaseR ensures empty parameter
 <code>polyline_opt* options=0</code> <b>or</b> empty structure <code>polyline_opt opt={0};</code>
 are default options and would not cause any error.
</p>
			<h3>Usage</h3>
<p>You should provide these structs to VaseR before any vase_renderer_* include by:<br />
<pre lang="C++">
struct Vec2 { double x,y;};
struct Color { float r,g,b,a;};
<b>or</b>
typedef your_vec2 Vec2;
typedef your_color Color;

#include "../include/vase_renderer_draft1_2.cpp"</pre>
</p>

<p>
The recommended way is to include "vase_renderer_draft1_2.cpp" .<br />
You should not include "vector_operations.h" or "vertex_array_holder.h" directly. It may break things.
 They are included by "vase_renderer_draft1_2.cpp".<br />
To compile "vase_renderer_draft1_2.cpp" separately, you should create an empty cpp file and define/
 typedef the structs Vec2 and Color <b>before</b> "vase_renderer_draft1_2.cpp" as these structs are
 expected to be provided by you.<br />
example:
	<pre lang="C++">//file vase_renderer.cpp
	struct Vec2 { double x,y;};
	struct Color { float r,g,b,a;};
	#include "vase_renderer_draft1_2.cpp"
//end of file</pre>
</p>

<table class='api_table' style='width:100%;'>
	
	<tr><td>
	<h3>polyline()</h3>
	For technical details about polyline() <a href='http://artgrammer.blogspot.com/2011/07/drawing-polylines-by-tessellation.html' target='_blank'>look at here</a>.
		<pre lang="C++">void polyline(
	Vec2* P,       //array of point of a polyline
	Color* C,      //array of color
	double* weight,//array of weight
	int size_of_P, //size of the buffers
	polyline_opt* options); //extra options</pre>
	All arrays must be of the same size otherwise memory error will occur.
		<h4>options</h4>
		<pre lang="C++">struct polyline_opt
{	//set the whole structure to 0 will give default options
	char joint;
		#define LJ_miter 0
		#define LJ_bevel 1
		#define LJ_round 2
	char cap;
		#define LC_butt   0
		#define LC_round  1
		#define LC_square 2
		#define LC_rect   3 //unique to vase renderer
	bool feather;
		double feathering;
		bool no_feather_at_cap;
		bool no_feather_at_core;
};</pre>
	
	<code>polyline_opt opt={0}; //consider this structure: <br /><br />
		<table>
			<caption>opt.joint</caption>
			<tr>	<td>LJ_miter<img src='../sample_images/polyline_joint_LJ_miter.png' /></td>
				<td>LJ_bevel<img src='../sample_images/polyline_joint_LJ_bevel.png' /></td>
				<td>LJ_round<img src='../sample_images/polyline_joint_LJ_round.png' /></td>
			</tr>
		</table>
		<br />
		<table>
			<caption>opt.cap</caption>
			<tr>	<td>LC_butt  <img src='../sample_images/polyline_cap_LC_butt.png' /></td>
				<td>LC_round <img src='../sample_images/polyline_cap_LC_round.png' /></td>
				<td>LC_square<img src='../sample_images/polyline_cap_LC_square.png' /></td>
			</tr>
			<tr>
				<td colspan=10>LC_rect<br />
				LC_rect is related to feathering. Unlike the above 3 common cap types, LC_rect is unique
		to VaseR. LC_rect puts the fade polygon out of the end points of a 
		polyline.<br />When feather=false, LC_rect looks very close to LC_butt. The difference is only obvious
		 at high value of feathering.
				</td>
			</tr>
			<tr>
				<td>LC_rect (with high value of feathering)<img src='../sample_images/polyline_cap_LC_rect.png' /></td>
				<td>LC_butt (with high value of feathering)<img src='../sample_images/polyline_cap_LC_butt_high_feathering.png' /></td>
			</tr>
		</table>
		<br />
		<table>
			<caption>opt.feather, opt.feathering, opt.no_feather_at_cap, opt.no_feather_at_core</caption>
		<tr>		<td> feathering is a multiplier to the magnitude of the fade polygon.
		do not set it to lower than 1.0 .<br />
		feathering is unique to VaseR. A feathered polyline with round cap and round joint can mimic
		the feel of an air brush stroke.
				</td>
				<td><img src='../sample_images/polyline_mimic_airbrush.png'/></td>
		</tr>
		</table>
		<table>
			<tr>	
				<td>opt.feather = false;<br /><img src='../sample_images/polyline_joint_LJ_miter.png' /></td>
				
				<td>opt.feather = true;<br />opt.feathering = 8.0;<br />
				<img src='../sample_images/polyline_feathering_8.png' />
				</td>
			</tr>
			<tr>
				<td>opt.feather = true;<br />
				opt.feathering = 8.0;<br />
				opt.no_feather_at_cap = true;<br />
				opt.no_feather_at_core = false;<br />
				<img src='../sample_images/polyline_no_feather_at_cap.png' />
				</td>
				
				<td>opt.feather = true;<br />
				opt.feathering = 8.0;<br />
				opt.no_feather_at_cap = false;<br />
				opt.no_feather_at_core = true;<br />
				<img src='../sample_images/polyline_no_feather_at_core.png' />
				</td>
			</tr>
			<tr>	<td colspan=10>
				remarks: no_feather_at_cap only affects cap type LC_butt,
				LC_square and LC_rect .
				</td>
			</tr>
		</table>
		<br />
	</code>
		<h4>Usage</h4>
		<pre lang="C++">
void sample_polyline()
{
	int size_of_AP=4;
	Vec2 AP[size_of_AP];
		AP[0].x=200; AP[0].y=50;
		AP[1].x=100; AP[1].y=150;
		AP[2].x=300; AP[2].y=150;
		AP[3].x=200; AP[3].y=250;
	Color AC[size_of_AP];
		{ Color col={1 , 0, 0, 1}; cc[0]=col;}
		{ Color col={.8,.8, 0, 1}; cc[1]=col;}
		{ Color col={ 0, 0, 1, 1}; cc[2]=col;}
		{ Color col={1 , 0, 0, 1}; cc[3]=col;}
	double Aw[size_of_AP];
		Aw[0] = 8.0;
		Aw[1] = 8.0;
		Aw[2] = 8.0;
		Aw[3] = 8.0;
		
	polyline_opt opt={0};
	polyline( AP, AC, Aw, size_of_AP, &opt);
}

glEnableClientState(GL_VERTEX_ARRAY);  //]vertex and color is required by polyline()
glEnableClientState(GL_COLOR_ARRAY);   //]
glDisableClientState(GL_NORMAL_ARRAY); //example only, manage your enabled states carefully
	sample_polyline();
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);</pre>
	<img src='../sample_images/test1.png' />
			<h4>Notes</h4>
Varying color is stable but will cause overdraw at degenerated cases.<br />
Varying weight is unstable.<br />
polyline() will "go wild" when a segment is shorter than its own width.<br />

			<h4>Further work</h4>
After solving the above 3 mentioned problems,<br />
can provide the choice between color blending profiles, possibly 'hard' and 'soft'.
	</td></tr><!--polyline-->

</table><!--table of API-->

		<h3>Source code</h3>
Development package with documentation, source code, sample images and sample programs is at
 <a href='http://vaserenderer.git.sourceforge.net/git/gitweb.cgi?p=vaserenderer/vaserenderer;a=summary' target='_blank'>sourceforge</a>.

		<h3>Credit and license</h3>
<p>Current maintainer and copyright holder is Chris Tsang, tyt2y3@gmail.com<br />
Comments, discussions, and contributions are greatly appreciated.
</p>
<p>
The license terms at this version "Vase Renderer first draft, version 0.2 (draft1_2)" are:<br />
If you used Vase Renderer (abbreviated as VaseR )in your program or produced derived work of VaseR, you should include a notice along with the distribution of your work describing how you used VaseR.<br />
No extra restriction on commercial use. No warranty provided.
</p>
	</div> <!--<div id='wrap'>-->
</body>

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Hong Kong Hong Kong
Chris H.F. Tsang
tyt2y3@gmail.com

Comments and Discussions