PDA

View Full Version : Add extra methods for drawing primitives



Denis Hilliard
10-03-2013, 05:22 AM
I'd like to see some extra methods on the canvas for drawing solid/dashed circle outlines and arc and such. I've been doing a few things myself and have an implementation for drawing arcs written


void draw_arc(clan::Canvas & canvas, const clan::Pointf & center, const float radius, const float start_angle, const float arc_angle, const int num_segments,const clan::Colorf & color = clan::Colorf::white)
{
float theta = arc_angle / float(num_segments - 1);
float tangetial_factor = tanf(theta);
float radial_factor = cosf(theta);

float x = radius * cosf(start_angle);
float y = radius * sinf(start_angle);

std::vector<clan::Vec2f> points(num_segments);
for(int i = 0; i < num_segments; i++)
{
points[i] = clan::Vec2f(x+center.x,y+center.y);
float tx = -y;
float ty = x;
x += tx * tangetial_factor;
y += ty * tangetial_factor;
x *= radial_factor;
y *= radial_factor;
}
canvas.draw_line_strip(points.data(),num_segments-1,color);
}

rombust
10-03-2013, 09:57 AM
I'm unsure if that function would be better on the clan::Shape2D class.

If your function was on the clan::Shape2D class, it would work as an outline and filled. It could be also cached by the application code (i.e. only recreate the outlines/triangles when required).

On a side note, adding it as a draw_arc(), fill_src() to the clan::Canvas :

The other week, I replied to pap, who had the following suggestion to add a function to clan::Canvas:


void draw_circle(clan::Canvas &canvas,const clan::Pointf center,const float radius,const clan::Colorf color) {
// A workaround for the lack of canvas.draw_circle() method.
clan::Shape2D shape;
std::vector<clan::Vec2f> circle;
shape.add_circle(center,radius,false);shape.add_ci rcle(center,radius-1.f,true);
shape.get_triangles(circle);
canvas.fill_triangles(circle,color);
}

My reply was:


"I thought about that myself. But decided against it. Although draw_circle() is a nice convenience function, it is relatively slow. Also, I am not sure it's useful.
I also thought of adding Shape2D::draw_circle() static. But the code to do it is so trivial, it would just add to ClanLib API bloat.

I am now unsure.

Denis Hilliard
10-05-2013, 05:39 PM
Great. That's awesome to hear.

I experimented with that particular code however found it quite slow (comparatively) to the code I posted especially as the circle radius was increased past a threshold.

As glLineStipple has now been depreciated looking at other means for fast and customisable line drawing. It seems like geometry shaders is the way to go but that requires adjacency primitives to proceed.

rombust
10-05-2013, 09:02 PM
Maybe you can use a texture containing the line.

For example the texture contains various line stippling combinations:

######## <--- Solid line
#######=
###=###=
#=#=#=#=
====####

And use " void draw_lines(const Vec2f *line_positions, const Vec2f *texture_positions, int num_vertices, const Texture2D &texture, const Colorf &line_color = Colorf::white);"
(With Texture2D set to repeat)

By adjusting the x2 coordinate of the texture position, controls the stippling size

You can need to disable Texture2D linear filtering as well

Denis Hilliard
10-09-2013, 04:21 PM
Thanks for that idea, it seems to work great in certain use cases. It tends to fall flat when I want to adjust the line width. glLineWidth also appears to be depreciated in opengl 3.0+ Ideally these lines would be a fixed width regardless of the cameras position. I've experimented with generating the geometry (for lines) on the cpu but to get that i would have to regenerate the entire buffer each frame.