I'm trying to program a brush stroke/drawing application using OpenGL within Openframeworks. For now I'm just trying to create squiggly lines that follow your mouse.
I've started by using ofpolyline but I have just managed to create a straight line that follows my mouse. I would really appreciate some pseudo code or something to point me in the right direction.
start. set (mouseX,mouseY);
end.set(mouseX,mouseY);
ofPolyline myline;
myline.addVertex(start.x,start.y);
myline.curveTo(end.x,end.y);
myline.bezierTo(mouseX,mouseY, mouseX,mouseY,mouseX, mouseY);
myline.addVertex(end.x,end.y);
myline.draw();
A Bezier curve with two vertices is always just a straight line segment. You need to add more vertices/control points to get non-degenerate (round) curves. So you could store the last mouse position somewhere, and add a new vertex when the mouse was moved by a certain amount (eg 20 pixels). Or add a vertex when the user clicks. However, if you always just call bezierTo(x,y,x,y,x,y), you will still only get straight lines. You need to offset the two control points from (x,y) to get round curves.
Related
So for the game I am working on, I am trying to make a unique type of shader. The majority is very basic, there is just one difficult part. I only want to render what the player would see in their line of sight. This is a top-down 2D game so the player would normally be able to see rooms over. But take this image for example.
Obviously the player here is the orange circle. The area that he can see is the gray ( grey? ) filled in area. The black lines represent a room and the purple lines represent his field of vision through the door of the room. I want to only render the shaded area.
I am aware GLSL has a discard statement where you can remove specific pixels. This means that by making a boolean function I could just do the following code in my vertex shader.
if ( !playerCanSeePoint( params ) ) {
discard;
}
What I don't know how to do though is make the playerCanSeePoint function. One idea I had was to cast invisible lines from the player in all directions and find it's first intersection point. That would mean to first wall and would create the proper shape. This seems resource consuming though. So is there a good way to do this?
You start with a square the size of the view area and then for each wall you cut out a portion of it based on where the player is.
Then you can triangulate the polygon and use a stencil to prevent drawing outside of it.
I am trying to write a small drawing program with Livecode, that will show the length of the drawn line over the line so it is available for editing, I also need to display the angles of the polygon for editing. The user should be able to select one section of the polygon by clicking on the dimension. This will load the length of the line into the field on the right for editing. Once the correct number is entered the drawing will redraw itself. (I can probably figure this part out using the "points" of the polygon) I have included a screen shot of what the program should look like. I was hoping that it would display these figures as the image was being drawn by the user. I am sorry I have not included any code, however I don't even know where to start. I have written several programs involving databases, but this is my first attempting to use drawings. Thanks in advance for any advice!! http://i.stack.imgur.com/gfKS9.jpg
To get the angle you can use some trigonometry. if you have two points (which you can get by using
the points of graphic "myPolygon"
Then you get one point per line. If you want to calculate the angle between two points you can use some trigonometry. If you have a point x1, y1 and another point x2,y2 you get the angle by using
put atan2(y2-y1, x2-x1) into tRad
The angle will be in radians from -pi to +pi so you need to convert it to degrees if you want more "regular" degrees:
put tRad*180/pi into tDeg
The angle you get is according to the x-y coordinate system. So if you want the angle between to lines you need to do two calculations and add the angles.
You can't change the size of a single segment but all polygon.
To change the size of the line...
set the linesize of graphic "polygon" to 4
Paolo
I'm trying to imitate the drawing of lines in a certain iOS game on cocos2dx,
The way i chose to implement it is by creating a dynamic cubic bezier curve.
For that, i will have to get 4 x-y screen locations:
1) begin point
2) control point 1
3) control point 2
4) ending point
As for the begin and end points, it's obvious i should use onTouchBegan and onTouchEnded and retrieve the relevant locations.
Since the line should be drawn immediately meaning, not drawing the non processed line and then process it, but creating a temp bezier curve at any time, i don't really know how to approach it and create the curve.
onTouchMoved(cocos2d::Touch *Touch, cocos2d::Event *Event)
is the problematic part, how do i determine the relevant control points?
any suggestions or ideas for different implementation will be welcomed.
Cheers.
I'm creating a comic book editor. I want to be able to use some fairly complex customisable shapes for the speech balloons.
I can draw the tail and then draw a balloon but that means I have the outline inside the shape and I want it only around the edge.
I assumed QPainterPath::simplified() would solve the problem but it doesn't seem to do anything.
At the moment my best idea is to draw a shape with a thick outline and then draw it again with no outline but I don't think that will work for "zero width" outlines.
I can think of two possible solutions here:
Draw both the "tail" and the main "balloon" as a single shape. In this case, you'd simply draw a single shape with a single outline and a single fill.
Draw them separately, but twice. Draw an "expanded" version of the shapes in black first, and then draw the "normal" version of the shapes in white over the top of it. You wouldn't draw any "lines" at all - the "expanded" version of the fill would serve the same purpose.
The first method would allow alternative line styles to be used (dotted or wiggly lines), but the latter would allow the "outline" to be slightly offset, so that it appeared thicker around some edges and thinner around others.
It turns out QPainterPath::simplified() does work. It depends on whether I draw clockwise or anti-clockwise (I believe it works when drawn clockwise), which I presume is down to how Qt's Winding Fill works.
// create a path representing the bubble and its "tail"
QPainterPath tail = tail.shape();
tail.addPath(bubble.shape());
tail.setFillRule(Qt::WindingFill);
painter->drawPath(tail.simplified);
I am writing a program that will draw a solid along the curve of a spline. I am using visual studio 2005, and writing in C++ for OpenGL. I'm using FLTK to open my windows (fast and light toolkit).
I currently have an algorithm that will draw a Cardinal Cubic Spline, given a set of control points, by breaking the intervals between the points up into subintervals and drawing linesegments between these sub points. The number of subintervals is variable.
The line drawing code works wonderfully, and basically works as follows: I generate a set of points along the spline curve using the spline equation and store them in an array (as a special datastructure called Pnt3f, where the coordinates are 3 floats and there are some handy functions such as distance, length, dot and crossproduct). Then i have a single loop that iterates through the array of points and draws them as so:
glBegin(GL_LINE_STRIP);
for(pt = 0; pt<=numsubsegements ; ++pt) {
glVertex3fv(pt.v());
}
glEnd();
As stated, this code works great. Now what i want to do is, instead of drawing a line, I want to extrude a solid. My current exploration is using a 'cylinder' quadric to create a tube along the line. This is a bit trickier, as I have to orient openGL in the direction i want to draw the cylinder. My idea is to do this:
Psuedocode:
Push the current matrix,
translate to the first control point
rotate to face the next point
draw a cylinder (length = distance between the points)
Pop the matrix
repeat
My problem is getting the angles between the points. I only need yaw and pitch, roll isnt important. I know take the arc-cosine of the dot product of the two points divided by the magnitude of both points, will return the angle between them, but this is not something i can feed to OpenGL to rotate with. I've tried doing this in 2d, using the XZ plane to get x rotation, and making the points vectors from the origin, but it does not return the correct angle.
My current approach is much simpler. For each plane of rotation (X and Y), find the angle by:
arc-cosine( (difference in 'x' values)/distance between the points)
the 'x' value depends on how your set your plane up, though for my calculations I always use world x.
Barring a few issues of it making it draw in the correct quadrant that I havent worked out yet, I want to get advice to see if this was a good implementation, or to see if someone knew a better way.
You are correct in forming two vectors from the three points in two adjacent line segments and then using the arccosine of the dot product to get the angle between them. To make use of this angle you need to determine the axis around which the rotation should occur. Take the cross product of the same two vectors to get this axis. You can then build a transformation matrix using this axis-angle or pass it as parameters to glRotate.
A few notes:
first of all, this:
for(pt = 0; pt<=numsubsegements ; ++pt) {
glBegin(GL_LINE_STRIP);
glVertex3fv(pt.v());
}
glEnd();
is not a good way to draw anything. You MUST have one glEnd() for every single glBegin(). you probably want to get the glBegin() out of the loop. the fact that this works is pure luck.
second thing
My current exploration is using a
'cylinder' quadric to create a tube
along the line
This will not work as you expect. the 'cylinder' quadric has a flat top base and a flat bottom base. Even if you success in making the correct rotations according to the spline the edges of the flat tops are going to pop out of the volume of your intended tube and it will not be smooth. You can try it in 2D with just a pen and a paper. Try to draw a smooth tube using only shorter tubes with a flat bases. This is impossible.
Third, to your actual question, The definitive tool for such rotations are quaternions. Its a bit complex to explain in this scope but you can find plentyful information anywhere you look.
If you'd have used QT instead of FLTK you could have also used libQGLViewer. It has an integrated Quaternion class which would save you the implementation. If you still have a choice I strongly recommend moving to QT.
Have you considered gluLookAt? Put your control point as the eye point, the next point as the reference point, and make the up vector perpendicular to the difference between the two.