Math/OpenGL ES: Draw 3D bezier curve of varying width - ios

I've been working on a problem for several weeks and have reached a point that I'd like to make sure I'm not overcomplicating my approach. This is being done in OpenGL ES 2.0 on iOS, but the principles are universal, so I don't mind the answers being purely mathematical in form. Here's the rundown.
I have 2 points in 3D space along with a control point that I am using to produce a bezier curve with the following equation:
B(t) = (1 - t)2P0 + 2(1 - t)tP1 + t2P2
The start/end points are being positioned at dynamic coordinates on a fairly large sphere, so x/y/z varies greatly, making a static solution not so practical. I'm currently rendering the points using GL_LINE_STRIP. The next step is to render the curve using GL_TRIANGLE_STRIP and control the width relative to height.
According to this quick discussion, a good way to solve my problem would be to find points that are parallel to the curve along both sides taking account the direction of it. I'd like to create 3 curves in total, pass in the indices to create a bezier curve of varying width, and then draw it.
There's also talk of interpolation and using a Loop-Blinn technique that seem to solve the specific problems of their respective questions. I believe that the solutions, however, might be too complex for what I'm going after. I'm also not interested bringing textures into the mix. I prefer that the triangles are just drawn using the colors I'll calculate later on in my shaders.
So, before I go into more reading on Trilinear Interpolation, Catmull-Rom splines, the Loop-Blinn paper, or explore sampling further, I'd like to make sure what direction is most likely to be the best bet. I think I can say the problem in its most basic form is to take a point in 3D space and find two parallel points along side it that take into account the direction the next point will be plotted.
Thank you for your time and if I can provide anything further, let me know and I'll do my best to add it.

This answer does not (as far as I see) favor one of the methods you mentioned in your question, but is what I would do in this situation.
I would calculate the normalized normal (or binormal) of the curve. Let's say I take the normalized normal and have it as a function of t (N(t)). With this I would write a helper function to calculate the offset point P:
P(t, o) = B(t) + o * N(t)
Where o means the signed offset of the curve in normal direction.
Given this function one would simply calculate the points to the left and right of the curve by:
Points = [P(t, -w), P(t, w), P(t + s, -w), P(t + s, w)]
Where w is the width of the curve you want to achieve.
Then connect these points via two triangles.
For use in a triangle strip this would mean the indices:
0 1 2 3
Edit
To do some work with the curve one would generally calculate the Frenet frame.
This is a set of 3 vectors (Tangent, Normal, Binormal) that gives the orientation in a curve at a given parameter value (t).
The Frenet frame is given by:
unit tangent = B'(t) / || B'(t) ||
unit binormal = (B'(t) x B''(t)) / || B'(t) x B''(t) ||
unit normal = unit binormal x unit tangent
In this example x denotes the cross product of two vectors and || v || means the length (or norm) of the enclosed vector v.
As you can see you need the first (B'(t)) and the second (B''(t)) derivative of the curve.

Related

Nature of relationship between optic flow and depth

Assuming the static scene, with a single camera moving exactly sideways at small distance, there are two frames and a following computed optic flow (I use opencv's calcOpticalFlowFarneback):
Here scatter points are detected features, which are painted in pseudocolor with depth values (red is little depth, close to the camera, blue is more distant). Now, I obtain those depth values by simply inverting optic flow magnitude, like d = 1 / flow. Seems kinda intuitive, in a motion-parallax-way - the brighter the object, the closer it is to the observer. So there's a cube, exposing a frontal edge and a bit of a side edge to the camera.
But then I'm trying to project those feature points from camera plane to the real-life coordinates to make a kind of top view map (where X = (x * d) / f and Y = d (where d is depth, x is pixel coordinate, f is focal length, and X and Y are real-life coordinates). And here's what I get:
Well, doesn't look cubic to me. Looks like the picture is skewed to the right. I've spent some time thinking about why, and it seems that 1 / flow is not an accurate depth metric. Playing with different values, say, if I use 1 / power(flow, 1 / 3), I get a better picture:
But, of course, power of 1 / 3 is just a magic number out of my head. The question is, what is the relationship between optic flow in depth in general, and how do I suppose to estimate it for a given scene? We're just considering camera translation here. I've stumbled upon some papers, but no luck trying to find a general equation yet. Some, like that one, propose a variation of 1 / flow, which isn't going to work, I guess.
Update
What bothers me a little is that simple geometry points me to 1 / flow answer too. Like, optic flow is the same (in my case) as disparity, right? Then using this formula I get d = Bf / (x2 - x1), where B is distance between two camera positions, f is focal length, x2-x1 is precisely the optic flow. Focal length is a constant, and B is constant for any two given frames, so that leaves me with 1 / flow again multiplied by a constant. Do I misunderstand something about what optic flow is?
for a static scene, moving a camera precisely sideways a known amount, is exactly the same as a stereo camera setup. From this, you can indeed estimate depth, if your system is calibrated.
Note that calibration in this sense is rather broad. In order to get real accurate depth, you will need to in the end supply a scale parameter on top of the regular calibration stuff you have in openCV, or else there is a single uniform ambiguity of the 3D (This last step is often called going to the "metric" reconstruction from only the "Euclidean").
Another thing which is apart of broad calibration is lens distortion compensation. Before anything else, you probably want to force your cameras to behave like pin-hole cameras (which real-world cameras usually dont).
With that said, optical flow is definetely very different from a metric depth map. If you properly calibraty and rectify your system first, then optical flow is still not equivalent to disparity estimation. If your system is rectified, there is no point in doing a full optical flow estimation (such as Farnebäck), because the problem is thereafter constrained along the horizontal lines of the image. Doing a full optical flow estimation (giving 2 d.o.f) will introduce more error after said rectification likely.
A great reference for all this stuff is the classic "Multiple View Geometry in Computer Vision"

OpenGL ES 2.0 Sphere

What is the easiest way to draw a textured Sphere in OpenGL ES 2.0 with GL_TRIANGLES?
I'm especially wondering how to calculate the vertices.
There are various ways of triangulating spheres. Popular ones, less popular ones, good ones, and not so good ones. Unfortunately the most widely used approach isn't very good.
Spherical Coordinates
This might be the most widely used approach. You iterate through the two angles in a spherical coordinate system in two nested loops, and generate points for each pair of angles. With angle theta iterating from -pi/2 to pi/2 and angle phi iterating from 0 to 2*pi, and sphere radius r, each point is calculated as:
x = r * cos(theta) * cos(phi)
y = r * cos(theta) * sin(phi)
z = r * sin(theta)
The calculation can be made more efficient if necessary, but I'll skip that aspect for this answer. The level (precision) of the tessellation is determined by the number of subdivisions of the angles.
The main advantage of this approach is that it's simple to implement, and easy to understand. You can picture the subdivision as the lines of latitude and longitude on a globe.
It does not result in a very good triangulation, though. The triangles around the equator have similar dimensions in all directions, but the triangles closer to the north/south pole get increasingly narrow. At the north/south pole you have a large number of very narrow triangles meeting in a single point. Good triangulations have all very similar sized triangles, and this one does not.
Recursive Subdivision of Octahedron
With this approach, you start with a regular octahedron, giving you 8 triangles. You then recursively subdivide each triangle into 4 sub-triangles, as illustrated here:
/\
/ \
/____\
/\ /\
/ \ / \
/____\/____\
So each triangle is subdivided by calculating 3 additional vertices that are midway between two of the existing vertices, and 4 triangles are formed from these 6 vertices. For calculating the midway point between two input points, you calculate the sum of the two vectors, and normalize the result to get the point back on the sphere.
The level (precision) of the tessellation is determined by the number of levels in the recursive subdivision. It starts with the 8 original triangles of the octahedron at level 0, results in 32 triangles at level 1, 128 at level 2, 512 at level 3, etc. You normally get a reasonably good looking sphere around level 3.
This approach results in a much more regular triangulation, and is therefore superior to the spherical coordinate approach.
The main disadvantage is that it might seem more complex. The calculation of the points is in fact very simple. It gets slightly more tricky if you want to use indexed vertices, instead of repeating common vertices. And even more painful if you want to build nice triangle strips. Not terribly difficult, but it takes some work.
This is my favorite approach of drawing spheres.
Other Polyhedra
You can do the same thing I described for the octahedron starting with other polyhedra. Regular polyhedra that consist of triangles are particularly suitable, which makes the tethrahedron and the icosahedron natural candidates. The octahedron is the most attractive IMHO because the initial coordinates are so easy to enumerate. Using an icosahedron would probably result in an even more regular triangulation, and the vertex coordinates can be looked up.
Subdivided Cube
I'm not sure if anybody is actually using this. But I tried it recently, and it was kind of fun. :) The idea is that you take a cube centered at the origin, and subdivide each of the six sides into smaller sub-squares. You can then turn the cube into a sphere by simply normalizing each of the vectors that describe a vertex.
The advantage of this approach is that it's very simple, including building triangle strips. The quality of the triangulation seems reasonably good. I don't think it's as regular as the recursively subdivided octahedron, but definitely better than the (much too) widely used spherical coordinate approach.

Drawing curve working for all the quadrants / Finding dynamic control points for the Bézier curve

Problem is if somebody taps on the angle abc as shown in fig. 1, then the curve should be drawn as shown in fig. 2 using CoreGraphics. I tried it using a Bézier curve, but shapes in different quadrants need dynamic control points which is quite complex (I guess). Can anyone suggest a solution for this?
If I understood it right, then what you need to know is, how to find suitable control points in different quadrant. This link will give you exactly what you want. If you are looking to draw cubic bezier curves then page 18 is for you. However I will recommend you to read it completely to have better understanding of bezier curves.
Formulas given in this paper will help you draw elliptical arcs accurately for one quadrant. You can define your quadrant using angles. To find control points using this paper you need to give following data:
start and end angle (which will define your quadrant)
radii of curve according to your figure
Instead of going through the math , I figured to draw the curve perfect for all the quadrant programmatically.
The algorithm for this is as follows:
(This is an algorithm to find the control points for the Bézier curve perfect for all the quadrants that means you will get the dynamic control points for the Bézier curve.)
Problem: Given 3 points a, b, c, the task is to draw the curve at the angle abc (curve structure is fixed as shown in the figure in the question).
Take all 3 points a, b, c in function.
Transform all 3 points a, b, c to the origin with respect to point a.
Find whether the 3rd point c lies left or right.
Rotate the 2nd point b to coincide the x-axis.
After step 4, you are in the zero position.
(Here you can choose the control points for the Bézier curve like you desire. You do not have to solve any relation for the control points. You can set the control points using simple add/subtract math only.) The control points obtained here will be perfect for all the quadrants.
After step 5, we get all the control points for the Bézier curve, now take all those points to the original position,
a. First rotate point b and the two control points (by the rotation angle of b in step 4)
b. Translate back all points to their original location (i.e. with respect to point a - reversing transformation from step 1).
Now you get the required control points for cubic Bézier suitable for all the quadrants.
Draw the curve using the Bézier curve function.

how to calculate number of point between three points for curve drawing?

i have three points in 2D and I want to draw a spline curve passing through them. How do I calculate the middle point (x1 and y1 as in quadTo)? i want to implement free curve like denon eq curve
For the first segment of the curve, you can probably use addQuadCurveToPoint, picking a control point with the same y value as the second point (and I picked an x value half way between the two end points):
For the second portion of the curve, you can't use quad curve, because you need two control points (or, you'd have to break it up into two quad curves, which is more hassle than its worth, IMHO). So use addCurveToPoint, using control point y values that are the same value as the y value of the point to which the control point refers (and, again, I picked x values half way between the x values of the two end points):
There are lots of permutations of this idea, but I hope this illustrates the concept. I'd suggest you start playing around with UIBezierPath and addCurveToPoint until you achieve the desired effect.

How to dertmine the DirectionVector of a Line?

I have a programming problem , in the context of a geometric shape recognition(Rectangles, ovals etc).
In this context, if I have a a simple line, from say (x1,y1) to (x2,y2) - made up of a series of points(x-y pairs) -
How would I calculate the DIRECTION VECTOR for this line? I understand the math behind it, but I'm finding the algorithm provided by my client a bit vague. I'm stuck at step 3) of this algorithm.
The following is the algorithm(in English as opposed ot psedocode), exactly as provided by my client.
1) Brake the points that make up a "stroke" or "line" up in to sets of X(where by default X= 20 - we will adjust) points = a PointSet
2) For Each PointSet, find the EndPouint(average of the points at the ends) for the first and last Y points(where by default Y= X/5).
3) Find the DirectionVector of the PointSet= Subtract the CentrePoints
4) For each pair of PointSets, find the AngleChange = the angle between the DirectionVectors of the PointSets.
and so on.......
I am trying to figure out what point (3) means......
Any help would be DEEPLy appreciated folks! THANKS in advance.
If the segment from (x1,y1) to (x2,y2) is short, then you can approximate its direction vector simply by: (x2-x1)*i + (y2-y1)*j.
Otherwise, you could use PCA to estimate the direction vector as the principal axis of individual points forming the segment,

Resources