How can I generate rolling hills of different height and width like Tiny Wings? Right now I'm using sin() but it obviously generates uniform hills repeating forever and ever.
What's the secret?
Thanks!
Certainly not a procedural generation expert - but you could try additively combining multiple randomly generate sin/cos functions with different periods. The more you add, the more random seeming it will be.
Something like this.
Simplex noise, or any other 2d noise function that looks the way you like.
If you're set on accomplishing this with sine waves to create this variation, here's a basic overview of how to manipulate the sine function:
Say you have an x axis, a y axis, and a sine wave y = sin(x)
y = sin(x * 0.5) makes the sine wave cross the x axis half as often (frequency)
y = 0.5 * sin(x) makes the sine wave reach a height half as high (amplitude)
y = 0.5 + sin(x) moves the central axis of the sine wave up the y axis by 0.5 (translation / offset)
Using these three properties, you can construct a wide variety of different looking waves.
Now, the trick is you'll have to overlay these waves to create variation over time. An easy way to do this is to just add the waves together,
y = sin(x * 0.5) + 0.5 * sin(x) + (0.5 + sin(x))
Or, you could define different waves over a specific subset of the x axis, and create a piecewise function. This may be more controllable / art-directable:
y = {
sin(x * 0.5) for x in (0, 5],
0.5 * sin(x) for x in (5, 10],
0.5 + sin(x) for x in (10, 5] }
However, f you try this, you'll notice this produces discontinuities in your wave. You should investigate different blending options (look up linear blending first) to see if you can create smooth transitions between these piecewise functions.
BUT, in my opinion, you should also investigate spline curves and see if they would accomplish what you want. Splines are well documented part of graphics and game programming, so it would be easy to implement (or grab someone else's code), and might provide a more intuitive way to author your levels (Generate a random set of points representing knots/control points, and pass a spline through it).
Related
I have the same rectangle in an untransformed form and in a perspective form.
Both, the coordinates from the untransformed form as well as from the perspective form are in the untransformed coordinate system.
Is there a way to reconstruct the transformation matrix which leads to this transformation?
I think it should be possible to do that by solving the 4 equations given by the 4 corners but I am not sure where to start.
// Edit:
It looks like I am victim of a xy problem here. All answers are based in a 3d environment. But I have a rectangle on an image + I know the real dimensions of this rectangle. What I need to know is how to transform other known points onto the perspective image
Note that you have 8 pairs of corresponding parameters (x and y for every point), and need to calculate 8 parameters of matrix using 8 equations
//four pairs of such equaions:
x' = (A * x + B * y + C) / (G * x + H * y + 1.0)
y' = (D * x + E * y + F) / (G * x + H * y + 1.0)
Theory of finding perspective transformation matrix is described in Paul Heckbert article.
C++ implementation could be found in antigrain library (file agg_trans_perspective.h)
One way is to plug in the values given in the transformation matrix. That has the merit of being easy and working, but it won't help you to understand it.
To understand the transform, draw a diagram with the screen vertical and looking top-down. Draw the eye. The line from the eye to the screen should be perpendicular. Then draw a point, somewhere off the screen. Then draw a line from the eye to the point, going through the screen.
It's then an exercise in highschool-level trigonometry to work out the projection of the point onto the screen.
I am back at college learning maths and I want to try and use some this knowledge to create some svg with d3.js.
If I have a function f(x) = x^3 - 3x^2 + 3x - 1
I would take the following steps:
Find the x intercepts for when y = 0
Find the y intercept when x = 0
Find the stationary points when dy\dx = 0
I would then have 2 x values from point 3 to plug into the original equation.
I would then draw a nature table do judge the flow of the graph or curve.
Plot the known points from the above and sketch the graph.
Translating what I would do on pen and paper into code instructions is what I really could do with any sort of advice on the following:
How can I programmatically factorise point 1 of the above to find the x-intercepts for when y = 0. I honestly do not know where to even start.
How would I programmatically find dy/dx and the values for the stationary points.
If I actually get this far then what should I use in d3 to join the points on the graph.
Your other "steps" have nothing to do with d3 or plotting.
Find the x intercepts for when y = 0
This is root finding. Look for algorithms to help with this.
Find the y intercept when x = 0
Easy: substitute to get y = 1.
Find the stationary points when dy\dx = 0
Take the first derivative to get 3x^2 - 12x + 9 and repeat the root finding step. Easy to get using quadratic equation.
I would then have 2 x values from point 3 to plug into the original
equation. I would then draw a nature table do judge the flow of the
graph or curve. Plot the known points from the above and sketch the
graph.
I would just draw the curve. Pick a range for x and go.
It's great to learn d3. You'll end up with something like this:
https://maurizzzio.github.io/function-plot/
For a cubic polynomial, there are closed formulas available to find all the particular points that you want (https://en.wikipedia.org/wiki/Cubic_function), and it is a sound approach to determine them.
Anyway, you will have to plot the smooth curve, which means that you will need to compute close enough points and draw a polyline that joins them.
Doing this, you are actually performing the first steps of numerical root isolation, with such an accuracy that the approximate and exact roots will be practically undistinguishable.
So an easy combined solution is to draw the curve as a polyline and find the intersections with the X axis as well as extrema using this polyline representation, rather than by means of more sophisticated methods.
This approach works for any continuous curve and is very easy to implement. So you actually draw the curve to find particular points rather than conversely as is done by analytical methods.
For best results on complicated curves, you can adapt the point density based on the local curvature, but this is another story.
If I have X amount of things (lets just randomly say 300)
Is there an algorithm that will arrange these things somewhat evenly around a central point? Like a 100 sided dice or a 3d mesh of a sphere?
Id rather have the things somewhat evenly spaced like this..
Rather than this polar way..
ps. For those interested, wondering why do I want to do this?
Well I'm doing these for fun, and after completing #7 I decided I'd like to represent the array of wires in 3d in Unity and watch them operate in a slowed down manner.
Here is a simple transformation that maps a uniform sample in the rectangle [0, 2 pi] x [-1, 1] onto a uniform sample on the sphere of radius r:
T(phi, z) = (r cos(phi) sqrt(1 - z^2), r sin(phi) sqrt(1 - zˆ2), r z)
The reason why this transformation produces uniform samples on the sphere is that the area of any region T(U) obtained by transforming the region U from the rectangle does not depend on U but on the area of U.
To prove this mathematically it is enough to verify that the norm of the vectorial product
| ∂T/∂phi x ∂T/∂z |
is constant (the area on the sphere is the integral of this vectorial product w.r.t. phi and z).
Summarizing
To produce a random sample uniformly distributed in the Sphere of radius r do the following:
Produce a random sample (phi_1, ..., phi_n) uniformly distributed in [0, 2 pi].
Produce a random sample (z_1, ..., z_n) uniformly distributed in [-1, 1].
For every pair (phi_j, z_k) calculate T(phi_j, z_k) using the formula above.
Here's a three-step approach. 1a) Make more points than you need. 1b) Remove some. 2) Adjust the rest.
1a) To make more points that you need, take any quasiregular polyhedron with sides that tessellate (triangles, squares, diamonds). Tesselate the spherical faces by subdivision, generating more vertices. For example, if you use the regular icosahedron you get geodesic domes. (Subdivide by 2, you get the dual to the C60 buckyball.) Working out exact formulas isn't hard. The number of new vertices per face is quadratic in the subdivision.
1b) Randomly remove enough points to get you down to your target number.
2) Use a force-directed layout algorithm to redistribute the vertices over the sphere. The underlying force graph is just that provided by the nearest neighbors in your underlying tesselation.
There are other ways to do step 1), such as just generating random points in any distribution. There is an advantage of starting with a quasiregular figure, though. Force-directed algorithms have a reputation for poor convergence in some cases. By starting with something that's already mostly optimal, you'll bypass most all of any convergence problems you might have.
One elegant solution I came across recently is a spherical fibonacci lattice (http://extremelearning.com.au/how-to-evenly-distribute-points-on-a-sphere-more-effectively-than-the-canonical-fibonacci-lattice/)
The nice thing about it is that you can specify the exact number of points you want
// C# Code example
Vector3[] SphericalFibonacciLattice(int n) {
Vector3[] res = new Vector3[n];
float goldenRatio = (1.0f + MathF.Sqrt(5.0f)) * 0.5f;
for(int i = 0; i < n; i++)
{
float theta = 2.0f * MathF.PI * i / goldenRatio;
float phi = MathF.Acos(1.0f - 2.0f * (i + 0.5f) / n);
Vector3 p = new Vector3(MathF.Cos(theta) * MathF.Sin(phi),
MathF.Sin(theta) * MathF.Sin(phi),
MathF.Cos(phi));
res[i] = p;
}
return res;
}
The linked article extends on this to create an even more uniform distribution, but even this basic version creates very nice results.
I'm learning Unity3d + some basic maths I've forgotten by messing around.
Heres what I'm doing now..
As you can probably tell the sides of this shape form a parabola.
The distance they are out from the centre is the base radius + the height squared * by a constant (0.05 in this image)
The code generating this is very simple..
for (int changer = 1; changer > -2; changer-=2) {
Vector3 newPos = new Vector3(
transform.position.x
,transform.position.y + currentheight*changer
,transform.position.z - RadiusAtZero -(Mathf.Pow(currentheight,2)*CurveMultiplier)
);
var newFleck = Instantiate(Fleck, newPos, Quaternion.identity)as GameObject;
newFleck.transform.RotateAround(transform.position,Vector3.up,angle*changer);
FleckList.Add(newFleck );
}
Btw the for loop and 'changer' mirror everything so 'currentheight' is really just the distance from the centreline of the parabola.
Anyway I'd like to make the cubes (or flecks as I've called them) be angled so that they are tangentional to the parabola I have made.
I need to determine the angle of a tangent to the parabola at particular point.
I found this
to find the line tangent to y=x^2 -3 at (1, -2) we can simultaneously solve
y=x^2 -3 and y+2=m(x-1) and set the discriminant equal to zero
But I dont know how to implement this. Also I reckon my 'CurveMultiplier' constant makes my parabola equation different from that one.
Can someone write some code that determines the angle? (and also maybe explain it)
Update.
Here is fixed version using the derivative of the equation. (Also I have changed from boxes to tetrahedrons and few other superficial things)
The easiest solution is to use a derivative for the parabolic equation.
In your picture then I'll assume Y is vertical, X horizontal, and Z in/out of the screen. Then the parabola being rotated, based upon your description, is:
f(h) = 0.05*h^2 + R
(h is height, R is base radius). If you imagine a plane containing the Y axis, you can rotate the plane around the Y axis at any angle and the dual parabola looks the same.
The derivative of a parabolic equation of the form f(x) = C*h^2 + R is f'(x) = 2*C*h, which is the slope of the tangent at h. In this specific case, that would be:
f'(h) = 0.1*h
Since the cross-sectional plane has an angle relative to X and Z axes, then that tangent will also have the same angular component (you have a rotated parabola).
Depending upon the units given for the constants in f(h), particularly the 0.05 value, you may have to adjust this for the correct results.
I would like to draw an animation of a polar curve (a spiral) being graphed. I am using javascript and canvas. Currently, I am using setInterval to call a draw function, which graphs an x and y coordinate found from a parametric representation of the polar curve (x and y in terms of theta). I am incrementing theta by 0.01, from 0 to 2*pi, once for every call to draw(). The problem is that I wish for the animation to draw the same amount of the curve for each call to draw, so that the drawing appears to progress with uniform speed. It doesn't matter if the time between each call to draw is different; I just need the speed (in terms of pixels drawn / # of calls to draw) to be constant for the entire awing. In other words, I need the arc length of the segment of the polar graph drawn for each call to draw to be the same. I have no idea how to go about this. Any help/sugestions would be greatly appreciated. Thanks
Let f(z) be the theta variable you are referring to in your question. Here are two parametric equations that should be very similar to what you have:
x(f(z)) = f(z)cos(f(z))
y(f(z)) = f(z)sin(f(z))
We can define the position p(f(z)) at f(z) as
p(f(z)) = [x(f(z)), y(f(z))]
The speed s(f(z)) at f(z) is the length of the derivative of p at f(z).
x'(f(z)) = f'(z)cos(f(z)) - f(z)f'(z)sin(f(z))
y'(f(z)) = f'(z)sin(f(z)) + f(z)f'(z)cos(f(z))
s(f(z)) = length(p'(f(z))) = length([x'(f(z)), y'(f(z))])
= length([f'(z)cos(f(z)) - f(z)f'(z)sin(f(z)), f'(z)sin(f(z)) + f(z)f'(z)cos(f(z))])
= sqrt([f'(z)cos(f(z))]2 + [f(z)f'(z)sin(f(z))]2 + [f'(z)sin(f(z))]2 + [f(z)f'(z)cos(f(z))]2)
= sqrt(f'(z) + [f(z)f'(z)]2)
If you want the speed s(f(z)) to be constant at C as z increases at a constant rate of 1, you need to solve this first-order nonlinear ordinary differential equation:
s(f(z)) = sqrt(f'(z) + [f(z)f'(z)]2) = C
http://www.wolframalpha.com/input/?i=sqrt%28f%27%28z%29+%2B+%5Bf%28z%29f%27%28z%29%5D%5E2%29+%3D+C
Solving this would give you a function theta = f(z) that you could use to compute theta as you keep increasing z. However, this differential equation has no closed form solution.
In other words, you'll have to make guesses at how much you should increase theta at each step, doing binary search on the delta to add to theta and line integrals over p(t) to evaluate how far each guess moves.
Easier method - change the parameter to setInterval proportional to the step arc length. That way you don't have to try to invert the arc length equation. If the interval starts getting too large, you can adjust the step size, but you can do so approximately.