My approach seems a bit drawn out for what is really a simple problem, I'd be interested to see how anyone else does it?
Okay,
You have an origin point (x0, y0, z0) and a destination point (x1, y1, z1) and an angle we'll call theta.
The curve function
The curve itself lies on a plane that coincides with our origin point and destination point, I will use axes called w and y, where w lies arbitrarily along the xz-plane and y is the conventional 'up' axis. The planes origin maybe translated horizontally from world-space so that the origin is (x0, 0, z0).
The general equation of the curve is
y = Aw^2 + Bw + C
Where A,B,C are three unknowns that we must resolve.
We can tell from inspection that when w=0 then y = C, and that y must also equal y0 (the origin's y-component). So, obviously C = y0.
This leaves us with only A and B to resolve.
The differential of this curve is therefore
dy/dw = 2Aw + B
From the angle of the curve we know that when w=0 the gradient of the curve must equal TAN(theta) (I'm capitalising the tan to avoid confusion with t which I will introduce later on).
So:
dy/dw = TAN(theta) when w=0
therefore: B = TAN(theta)
So now we also have B, only A to go [smile]
We know that our curve has a single turning point and at this point its gradient is zero, some value for w will produce this point, lets call this value m.
Substituting in what we know for B and m inplace of w we have
2Am + TAN(theta) = 0
Rearranging to get A
A = -TAN(theta) / 2m
So we have A although its in terms of yet another unknown, m, but thats OK, we can substitute A, B and C into our curves general equation:
y = (w^2)(-TAN(theta)/(2m)) + (w)TAN(theta) + y0
We need to resolve m, but thats more complicated.
If we know a position on our current curve function (y = f(w)) then we could substitute that in and get m.
Luckily we know that our destination point lies somewhere on our curve, we can find its position on our wy-plane as so:
w = sqrt((x1-x0)^2 + (y1-yo)^2))
y = y1
Conceptually sqrt((x1-x0)^2 + (y1-yo)^2)) is the horizontal distance of the curve, since its a-lot to type I will assign it to an alias and call it L, therefore w = L.
Substituting these in:
y1 = (-TAN(theta)/(2m))(L^2) + (L)TAN(theta) + y0
we can now rearrange to get m, although actually we need only go as far as -1/(2m)
-1/(2m) = ((y1-y0)/TAN(theta) - L) / (L^2)
And now we must substitute this back into the general equation (the one in bold-italics):
y = (w^2)TAN(theta)(((y1-y0)/TAN(theta) - L) / (L^2)) + (w)TAN(theta) + y0
At this point we can simplify the w^2 coefficients:
y = (w^2)(((y1-y0) - (L)TAN(theta)) / (L^2)) + (w)TAN(theta) + y0
Now we have the working function: y = f(w), where w is between 0 and L.
Ideally we would have a parametric function: y = f(t), where t is between 0 and 1
Its not hard to see that with the relationship w = tL then f(w) = f(tL)
So substituting tL inplace of w we get:
y = ((tL)^2)(((y1-y0) - (L)TAN(theta)) / (L^2)) + (tL)TAN(theta) + y0
The L^2 terms cancel out and we can multiply through with the t^2 term:
y = (t^2)(y1-y0) - (t^2)(L)TAN(theta) + (tL)TAN(theta) + y0
Now factorise out (tL)TAN(theta)
y = (tL)(1-t)TAN(theta) + (t^2)(y1-y0) + y0
And so finally we now have something of the form: y = f(t) [smile]
Now the x and z axes
The x and z axes are much easier to calculate.
We want functions, g and h such that:
x = g(t)
z = h(t)
Where t is in the range 0 to 1.
Both functions take the form:
p = o + t(d - o)
where p is the output position (x or z), o is the origin component and d is the destination component.
Therefore:
x = x0 + t(x1 - x0)
z = z0 + t(z1 - z0)
Now we've done the maths, lets see some code
As TheAdmiral rightly pointed out you will be needing a fourth parameter in your function definition, this is the t parameter, its in the range 0 to 1 so it needs to be floating point (float or double in C/C++ terms).
With that said, here's your function (though untested):
Vector3 calculateTrajectory(Vector3 origin, Vector3 destination, double angle, float t){ Vector3 output; // Just for convenience float xDisplacement = (destination.x - origin.x); float yDisplacement = (destination.y - origin.y); float zDisplacement = (destination.z - origin.z); float tanTheta = std::tan(angle); // Calculate the x and z components output.x = origin.x + t * xDisplacement; output.z = origin.z + t * zDisplacement; // Calculate the horizontal distance covered by our curve float distance = std::sqrt(xDisplacement*xDisplacement + zDisplacement*zDisplacement); // Calculate the y component output.y = (t*distance*(1-t)*tanTheta) + (t*t * yDisplacement) + origin.y; return output;}
Note that this function expects the angle in radians, if you desire degrees then you can convert using:
radians = degrees/180*pi
Well yes that was a very long post, but I found it interesting to write anyway [smile], my proof-reading is usually not brilliant but with any luck it makes sense.
Hope that was some help anyway
Have a nice day
David
[Edited by - dmatter on June 30, 2007 12:37:25 PM]