Procedural terrain generation with blocks - javascript

I am using three.js to create procedurally generated terrain using Perlin Noise.
I am creating the terrain using a series of blocks, but their heights along their borders are not corresponding to one another as you can see below.
How should I approach matching the height maps across blocks?
I'm using Perlin Noise Algorithm for generating heights; the problem is that the height of each point is indipendent from the heights of the near points. I've other noise algorithm, but i have the same problem..

There's a really good video on infinite terrain here: https://www.youtube.com/watch?v=IKB1hWWedMk
It's in processing, but the same concept can be applied to whichever noise library you're using - I'm going to assume that you're using Perlin noise. In which case, you need to look at the values you're passing into this function and change them based on how big your blocks are.
For example, imagine a 3x3 grid of blocks. If your middle block is (x, y), and each block is 10x10 units in size, if you move 'north' (for lack of a better term), you'd need to be getting (x, y - 10) from your noise function.
The video explains it way better than I can, but hopefully this has helped. Without more knowledge of the function you're using I can't really give a more detailed answer.

This answer will explain how to solve it for a single axis, x. It is then trivial to do the same for the y (z in three.js) axis.
The first step is to ensure the perlin noise is using the same random seed for each block. This will ensure that blocks share the same perlin noise map and so can transition smoothly between them.
The second part is to have a mapping between your block units and what is passed into the perlin noise function. For example your block x may be going from -512 to 512 units, so you get a height value for each x vertex by passing in -0.5 to 0.5 for each x vertex into the noise function.
E.g.
vertextHeight = perlin(vertexX / 1024, vertextY / 1024)
Your second block will then be offset so its edge interfaces with the first block. E.g. its x position will be +1024 more than the first block, and so will go from 512 to 1536.
So in this sense, block0 will have an x offset of 0, and block1 will have an x offset of 1024. 1024 being the block width/size in three.js units.
Finally, you need to give the same offsets to the noise function, but scaled based on the mapping described above. In this example, 512 would become 0.5 and 1536 would become 1.5 which looks like this:
size = 1024;
vertextHeight = perlin((vertexX + offsetX) / size, (vertextY + offsetY) / size)`
Therefore, the x value given to the noise function at the edge between block0 and block 1 will be the same, and so will return the same height value.

Related

Animating along a curve using Javascript & simple math

I feel like the solution is very simple, but in all honestly I failed math multiple times in high school, so I'm barely grasping even the basic concepts right now.
The idea is very simple.. I want to have a bunch of graphical objects tween animate from one side of a 300x300px div to the other side along randomized curved paths as if they were being tossed or dropped from the top left to the bottom right (and vice versa, back and forth).
I know I need to use some form of Trigonometry to solve this (sin, cos, tan??). I also already know how to get my two points (randomizing Y points, and then randomly putting x points on the positive or negative side of the 300px width). But the part where I have to actually calculate steps along a curve is beyond me.
Here's a crappy diagram of basically what I'm attempting.. I searched Google but all of the examples were way overcomplicated or too abstract. I just want to learn how to make a curve between two points.. That's it!
So simple question: How do I randomize a curved animation (or plot points along a curve) between two points using vanilla JavaScript (no JQuery please).
First of all, if you would like a quick look into the math of JavaScript animations , you might consider visiting this link
Actually, you only need very simple trigonometry (sine and cosine). If you are tossing something from a point (X0, Y0), the equations of motion are more like a parabolic trajectory.
From Wikipedia:
Displacement and coordinates of parabolic throwing
At any time t, the projectile's horizontal and vertical displacement
are:
x = X0 + v0 * t * cos(theta)
y = Y0 + v0 * t * sin(theta) − 0.5 * g * t * t
So there you go, your coordinates in pixels for every t time step.
You may define theta and v0 as constants or also as random values to make the animation more chaotic and lively.
Play with the value of g (in Earth it is 9.8 m/s²), because probably when scaling to pixels/s² it might overshoot.
Also you may want to give negative values to X0 and Y0 in order to intercept the descending part of the trajectories, leaving the ascending out of the div.

Understanding Matrix in SVG

I need help in deep understanding of matrix in SVG. I already know about matrix, I want to rotate and scale without using scale or rotate word. I want to use transform='matrix(a,b,c,d,e,f)'. I know 'a/d' value determine the scale, 'e/f' determines the position. tan(b),tan(c) determines the skew. cos(a),sin(b),-sin(c),cos(d) determines the angle.But I want to know how this work, I need thoroughly help in understanding matrix in SVG.
Matrix operations are composed of individual, "local" transformations (i.e. translate, rotate, scale, skew) by matrix concatenation (i.e. multiplication).
For example, if you want to rotate an object by r degrees around a point (x, y), you would translate to (x, y), rotate r degrees, then translate back to the original position (-x, -y).
By what is often referred to as "chaining" (as described above) each successive "local" transformation is combined to produce a result. Therefore, at any location in a chain of transformations, the "local" transformation space (at that location) is composed of all operations that came before.
What this implies is that when transforming some parameter of an SVG element (i.e. translate) the transform is applied to it's current transformation space. So, for example if the element is already rotated 30 degrees, then a translation of (8, 5) would not go 8 to the right and 5 down, but it would go the rotation of (8, 5) by 30 degrees - relative to the current position.
So this is a bit of a gotcha.
One way to help deal with this complication is to decompose transformation matrices into their individual, total transformations (i.e. total translation, total rotation/skew, total scale), but decomposition says nothing about what individual basic transformations went into the combined totals, nor of the order in which they occurred. This is a problem because 2D transformations are not commutative, e.g. translate(x, y)->rotate(r) is not the same as rotate(r)->translate(x, y).
The best way that I've found is to only compose transformations in a certain order and keep track of the totals in that order, then when a new transformation is introduced, used the totals that have been tracked, update the one that is being modified and recompose the entire transformation.
Like so: (pseudo-code)
// EDIT: initialize components (new SVGMatrix returns the identity matrix)
var transX=0, transY=0, rot=0, scaX=0, scaY=0, skwX=0, skwY=0, matrix = new SVGmatrix();
// example rotate
function rotate(svgEl, angle){
rot = rot + angle;
updateTransform();
applyTransform(svgEl);
};
function updateTransform(){
// the order that I've found most convenient
// (others may do it differently)
matrix.translate(transX, transY);
matrix.rotate(rot);
matrix.scale(scaX, scaY);
matrix.skewX(skwX);
matrix.skewY(skwY);
};
function applyTransform(el){
el.transform = matrix;
};
To be clear, this is not suggesting that matrices are not a good way of representing transformations, nor is it suggesting a better way - far from it.
Transformation matrices are a powerful tool, and when used appropriately, they are very effective at handling complex animations, but they are not trivial to use in all cases.
This may be a bit advanced, but for more information about animations using matrix transformations, this short code example provides a wealth of information and references to start from.
http://www.w3.org/TR/2011/WD-css3-2d-transforms-20111215/#matrix-decomposition
Update:
Just a note about the decomposed skew factor proposed at the above link.
Only a single skew factor ( in x ) is computed because skewing in both x and y is equivalent to a skew in x and a combined ( offset ) rotation.
Combining x skew and y skew ( with or without a rotation or translation, as in my above preferred composition order ) will result in a different x skew, rotation ( e.g. non-zero rotation if none was originally composed ), and translation ( e.g. an offset by some amount relative to the decomposed rotation in lieu of the original y skew ), but no recoverable y skew - using the linked decomposition method.
This is a limitation of composed affine matrices. So producing a final result matrix should generally be considered a one-way computation.

Drawing a repeating sinusoidal wave with canvas api

I'm trying to get an image to flow horizontally in a sinusoidal fashion, and repeat seamlessly when it gets to the end of its own width in relation to its canvas size.
So far, I've got the image repeating and waving, but there is a significant jump when the x axis needs to be reset.
I think the problem is here:
if (x > canvasX) {
console.log('reset!!');
x = canvasX-imgW;
y = sineY(x);
}
//draw aditional image
if (x > (canvasX-imgW)) {
var ax = x-imgW+dx;
y = sineY(ax);
ctx.drawImage(img,ax,y,imgW,imgH);
}
Ultimately, what happens is that the sineY of the reset x value is about 19 degrees off of what it should be at the end of its regular period where the x value is highest. However, I can't really figure out how to adjust the bounds to make the movement seamless through the multiple periods.
Here's the fiddle: http://jsfiddle.net/3L7Dp/
The period variable needs to be normalized based on the total distance x will move.
In this case x will go image.width so period must be:
var period = x / imgW; //period must be a value in the range [0.0, 1.0]
This should give an usable value for cycling the image.
Modified fiddle
Hope this helps!
One way is to declare an offset by which x will be adjusted, such as var xOffset = 0. When calculating the sine, use x + xOffset. Every time you do x -= imgW, update the offset based on the current offset and the image width, so that the sin at the new position will equal the sin at the current position.
Doing this will allow you to have any period, even one unrelated to the width of your image.
I made my own version of your page with many simplifications, you can see it in this JsFiddle. The sine wave is seamless. My implementation also supports images much narrower than the canvas--they will be repeated all the way across, always filling the canvas (try img.width = 100 in my JsFiddle to see what I mean). In my function, since I based the period on a certain number of x-pixels, my xOffset recalculation is simplified and I can simply use modulus to calculate the new offset after subtracting from x.
Some style considerations I would like to suggest are:
Use more consistent variable names (such as context vs. ctx--if both are truly needed, give them prefixes such as baseContext, canvasContext so that context is consistent throughout the code).
Name variables closer to what they represent (for example, canvasX is not a good variable name for canvas.Width.
Don't be afraid of slightly longer variable names. imgW is less clear than imageWidth. W doesn't always mean width.
Put spaces after commas and the word function, and around operators.
Using parameter x in your sineY function is confusing as x is already declared outside.
Parameterizing your animation function is fine, but just as good is to wrap the entire script in a SEAF (self-executing anonymous function), as that properly gives all the variables a scope (keeping them out of global scope), thus simplifying your code by not having to pass around the variables.

JavaScript "pixel"-perfect collision detection for rotating sprites using math (probably linear algebra)

I'm making a 2D game in JavaScript. For it, I need to be able to "perfectly" check collision between two sprites which have x/y positions (corresponding to their centre), a rotation in radians, and of course known width/height.
After spending many weeks of work (yeah, I'm not even exaggerating), I finally came up with a working solution, which unfortunately turned out to be about 10,000x too slow and impossible to optimize in any meaningful manner. I have entirely abandoned the idea of actually drawing and reading pixels from a canvas. That's just not going to cut it, but please don't make me explain in detail why. This needs to be done with math and an "imaginated" 2D world/grid, and from talking to numerous people, the basic idea became obvious. However, the practical implementation is not. Here's what I do and want to do:
What I already have done
In the beginning of the program, each sprite is pixel-looked through in its default upright position and a 1-dimensional array is filled up with data corresponding to the alpha channel of the image: solid pixels get represented by a 1, and transparent ones by 0. See figure 3.
The idea behind that is that those 1s and 0s no longer represent "pixels", but "little math orbs positioned in perfect distances to each other", which can be rotated without "losing" or "adding" data, as happens with pixels if you rotate images in anything but 90 degrees at a time.
I naturally do the quick "bounding box" check first to see if I should bother calculating accurately. This is done. The problem is the fine/"for-sure" check...
What I cannot figure out
Now that I need to figure out whether the sprites collide for sure, I need to construct a math expression of some sort using "linear algebra" (which I do not know) to determine if these "rectangles of data points", positioned and rotated correctly, both have a "1" in an overlapping position.
Although the theory is very simple, the practical code needed to accomplish this is simply beyond my capabilities. I've stared at the code for many hours, asking numerous people (and had massive problems explaining my problem clearly) and really put in an effort. Now I finally want to give up. I would very, very much appreciate getting this done with. I can't even give up and "cheat" by using a library, because nothing I find even comes close to solving this problem from what I can tell. They are all impossible for me to understand, and seem to have entirely different assumptions/requirements in mind. Whatever I'm doing always seems to be some special case. It's annoying.
This is the pseudo code for the relevant part of the program:
function doThisAtTheStartOfTheProgram()
{
makeQuickVectorFromImageAlpha(sprite1);
makeQuickVectorFromImageAlpha(sprite2);
}
function detectCollision(sprite1, sprite2)
{
// This easy, outer check works. Please ignore it as it is unrelated to the problem.
if (bounding_box_match)
{
/*
This part is the entire problem.
I must do a math-based check to see if they really collide.
These are the relevant variables as I have named them:
sprite1.x
sprite1.y
sprite1.rotation // in radians
sprite1.width
sprite1.height
sprite1.diagonal // might not be needed, but is provided
sprite2.x
sprite2.y
sprite2.rotation // in radians
sprite2.width
sprite2.height
sprite2.diagonal // might not be needed, but is provided
sprite1.vectorForCollisionDetection
sprite2.vectorForCollisionDetection
Can you please help me construct the math expression, or the series of math expressions, needed to do this check?
To clarify, using the variables above, I need to check if the two sprites (which can rotate around their centre, have any position and any dimensions) are colliding. A collision happens when at least one "unit" (an imagined sphere) of BOTH sprites are on the same unit in our imaginated 2D world (starting from 0,0 in the top-left).
*/
if (accurate_check_goes_here)
return true;
}
return false;
}
In other words, "accurate_check_goes_here" is what I wonder what it should be. It doesn't need to be a single expression, of course, and I would very much prefer seeing it done in "steps" (with comments!) so that I have a chance of understanding it, but please don't see this as "spoon feeding". I fully admit I suck at math and this is beyond my capabilities. It's just a fact. I want to move on and work on the stuff I can actually solve on my own.
To clarify: the 1D arrays are 1D and not 2D due to performance. As it turns out, speed matters very much in JS World.
Although this is a non-profit project, entirely made for private satisfaction, I just don't have the time and energy to order and sit down with some math book and learn about that from the ground up. I take no pride in lacking the math skills which would help me a lot, but at this point, I need to get this game done or I'll go crazy. This particular problem has prevented me from getting any other work done for far too long.
I hope I have explained the problem well. However, one of the most frustrating feelings is when people send well-meaning replies that unfortunately show that the person helping has not read the question. I'm not pre-insulting you all -- I just wish that won't happen this time! Sorry if my description is poor. I really tried my best to be perfectly clear.
Okay, so I need "reputation" to be able to post the illustrations I spent time to create to illustrate my problem. So instead I link to them:
Illustrations
(censored by Stackoverflow)
(censored by Stackoverflow)
OK. This site won't let me even link to the images. Only one. Then I'll pick the most important one, but it would've helped a lot if I could link to the others...
First you need to understand that detecting such collisions cannot be done with a single/simple equation. Because the shapes of the sprites matter and these are described by an array of Width x Height = Area bits. So the worst-case complexity of the algorithm must be at least O(Area).
Here is how I would do it:
Represent the sprites in two ways:
1) a bitmap indicating where pixels are opaque,
2) a list of the coordinates of the opaque pixels. [Optional, for speedup, in case of hollow sprites.]
Choose the sprite with the shortest pixel list. Find the rigid transform (translation + rotation) that transforms the local coordinates of this sprite into the local coordinates of the other sprite (this is where linear algebra comes into play - the rotation is the difference of the angles, the translation is the vector between upper-left corners - see http://planning.cs.uiuc.edu/node99.html).
Now scan the opaque pixel list, transforming the local coordinates of the pixels to the local coordinates of the other sprite. Check if you fall on an opaque pixel by looking up the bitmap representation.
This takes at worst O(Opaque Area) coordinate transforms + pixel tests, which is optimal.
If you sprites are zoomed-in (big pixels), as a first approximation you can ignore the zooming. If you need more accuracy, you can think of sampling a few points per pixel. Exact computation will involve a square/square collision intersection algorithm (with rotation), more complex and costly. See http://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman_algorithm.
Here is an exact solution that will work regardless the size of the pixels (zoomed or not).
Use both a bitmap representation (1 opacity bit per pixel) and a decomposition into squares or rectangles (rectangles are optional, just an optimization; single pixels are ok).
Process all rectangles of the (source) sprite in turn. By means of rotation/translation, map the rectangles to the coordinate space of the other sprite (target). You will obtain a rotated rectangle overlaid on a grid of pixels.
Now you will perform a filling of this rectangle with a scanline algorithm: first split the rectangle in three (two triangles and one parallelogram), using horizontal lines through the rectangle vertexes. For the three shapes independently, find all horizontal between-pixel lines that cross them (this is simply done by looking at the ranges of Y values). For every such horizontal line, compute the two intersections points. Then find all pixel corners that fall between the two intersections (range of X values). For any pixel having a corner inside the rectangle, lookup the corresponding bit in the (target) sprite bitmap.
No too difficult to program, no complicated data structure. The computational effort is roughly proportional to the number of target pixels covered by every source rectangle.
Although you have already stated that you don't feel rendering to the canvas and checking that data is a viable solution, I'd like to present an idea which may or may not have already occurred to you and which ought to be reasonably efficient.
This solution relies on the fact that rendering any pixel to the canvas with half-opacity twice will result in a pixel of full opacity. The steps follow:
Size the test canvas so that both sprites will fit on it (this will also clear the canvas, so you don't have to create a new element each time you need to test for collision).
Transform the sprite data such that any pixel that has any opacity or color is set to be black at 50% opacity.
Render the sprites at the appropriate distance and relative position to one another.
Loop through the resulting canvas data. If any pixels have an opacity of 100%, then a collision has been detected. Return true.
Else, return false.
Wash, rinse, repeat.
This method should run reasonably fast. Now, for optimization--the bottleneck here will likely be the final opacity check (although rendering the images to the canvas could be slow, as might be clearing/resizing it):
reduce the resolution of the opacity detection in the final step, by changing the increment in your loop through the pixels of the final data.
Loop from middle up and down, rather than from the top to bottom (and return as soon as you find any single collision). This way you have a higher chance of encountering any collisions earlier in the loop, thus reducing its length.
I don't know what your limitations are and why you can't render to canvas, since you have declined to comment on that, but hopefully this method will be of some use to you. If it isn't, perhaps it might come in handy to future users.
Please see if the following idea works for you. Here I create a linear array of points corresponding to pixels set in each of the two sprites. I then rotate/translate these points, to give me two sets of coordinates for individual pixels. Finally, I check the pixels against each other to see if any pair are within a distance of 1 - which is "collision".
You can obviously add some segmentation of your sprite (only test "boundary pixels"), test for bounding boxes, and do other things to speed this up - but it's actually pretty fast (once you take all the console.log() statements out that are just there to confirm things are behaving…). Note that I test for dx - if that is too large, there is no need to compute the entire distance. Also, I don't need the square root for knowing whether the distance is less than 1.
I am not sure whether the use of new array() inside the pixLocs function will cause a problem with memory leaks. Something to look at if you run this function 30 times per second...
<html>
<script type="text/javascript">
var s1 = {
'pix': new Array(0,0,1,1,0,0,1,0,0,1,1,0),
'x': 1,
'y': 2,
'width': 4,
'height': 3,
'rotation': 45};
var s2 = {
'pix': new Array(1,0,1,0,1,0,1,0,1,0,1,0),
'x': 0,
'y': 1,
'width': 4,
'height': 3,
'rotation': 90};
pixLocs(s1);
console.log("now rotating the second sprite...");
pixLocs(s2);
console.log("collision detector says " + collision(s1, s2));
function pixLocs(s) {
var i;
var x, y;
var l1, l2;
var ca, sa;
var pi;
s.locx = new Array();
s.locy = new Array();
pi = Math.acos(0.0) * 2;
var l = new Array();
ca = Math.cos(s.rotation * pi / 180.0);
sa = Math.sin(s.rotation * pi / 180.0);
i = 0;
for(x = 0; x < s.width; ++x) {
for(y = 0; y < s.height; ++y) {
// offset to center of sprite
if(s.pix[i++]==1) {
l1 = x - (s.width - 1) * 0.5;
l2 = y - (s.height - 1) * 0.5;
// rotate:
r1 = ca * l1 - sa * l2;
r2 = sa * l1 + ca * l2;
// add position:
p1 = r1 + s.x;
p2 = r2 + s.y;
console.log("rotated pixel [ " + x + "," + y + " ] is at ( " + p1 + "," + p2 + " ) " );
s.locx.push(p1);
s.locy.push(p2);
}
else console.log("no pixel at [" + x + "," + y + "]");
}
}
}
function collision(s1, s2) {
var i, j;
var dx, dy;
for (i = 0; i < s1.locx.length; i++) {
for (j = 0; j < s2.locx.length; j++) {
dx = Math.abs(s1.locx[i] - s2.locx[j]);
if(dx < 1) {
dy = Math.abs(s1.locy[i] - s2.locy[j]);
if (dx*dx + dy+dy < 1) return 1;
}
}
}
return 0;
}
</script>
</html>

How to subdivide a shape into sections of a given size

I'm currently trying to build a kind of pie chart / voronoi diagram hybrid (in canvas/javascript) .I don't know if it's even possible. I'm very new to this, and I haven't tried any approaches yet.
Assume I have a circle, and a set of numbers 2, 3, 5, 7, 11.
I want to subdivide the circle into sections equivalent to the numbers (much like a pie chart) but forming a lattice / honeycomb like shape.
Is this even possible? Is it ridiculously difficult, especially for someone who's only done some basic pie chart rendering?
This is my view on this after a quick look.
A general solution, assuming there are to be n polygons with k vertices/edges, will depend on the solution to n equations, where each equation has no more than 2nk, (but exactly 2k non-zero) variables. The variables in each polygon's equation are the same x_1, x_2, x_3... x_nk and y_1, y_2, y_3... y_nk variables. Exactly four of x_1, x_2, x_3... x_nk have non-zero coefficients and exactly four of y_1, y_2, y_3... y_nk have non-zero coefficients for each polygon's equation. x_i and y_i are bounded differently depending on the parent shape.. For the sake of simplicity, we'll assume the shape is a circle. The boundary condition is: (x_i)^2 + (y_i)^2 <= r^2
Note: I say no more than 2nk, because I am unsure of the lowerbound, but know that it can not be more than 2nk. This is a result of polygons, as a requirement, sharing vertices.
The equations are the collection of definite, but variable-bounded, integrals representing the area of each polygon, with the area equal for the ith polygon:
A_i = pi*r^2/S_i
where r is the radius of the parent circle and S_i is the number assigned to the polygon, as in your diagram.
The four separate pairs of (x_j,y_j), both with non-zero coefficients in a polygon's equation will yield the vertices for the polygon.
This may prove to be considerably difficult.
Is the boundary fixed from the beginning, or can you deform it a bit?
If I had to solve this, I would sort the areas from large to small. Then, starting with the largest area, I would first generate a random convex polygon (vertices along a circle) with the required size. The next area would share an edge with the first area, but would be otherwise also random and convex. Each polygon after that would choose an existing edge from already-present polygons, and would also share any 'convex' edges that start from there (where 'convex edge' is one that, if used for the new polygon, would result in the new polygon still being convex).
By evaluating different prospective polygon positions for 'total boundary approaches desired boundary', you can probably generate a cheap approximation to your initial goal. This is quite similar to what word-clouds do: place things incrementally from largest to smallest while trying to fill in a more-or-less enclosed space.
Given a set of voronio centres (i.e. a list of the coordinates of the centre for each one), we can calculate the area closest to each centre:
area[i] = areaClosestTo(i,positions)
Assume these are a bit wrong, because we haven't got the centres in the right place. So we can calculate the error in our current set by comparing the areas to the ideal areas:
var areaIndexSq = 0;
var desiredAreasMagSq = 0;
for(var i = 0; i < areas.length; ++i) {
var contrib = (areas[i] - desiredAreas[i]);
areaIndexSq += contrib*contrib;
desiredAreasMagSq += desiredAreas[i]*desiredAreas[i];
}
var areaIndex = Math.sqrt(areaIndexSq/desiredAreasMagSq);
This is the vector norm of the difference vector between the areas and the desiredAreas. Think of it like a measure of how good a least squares fit line is.
We also want some kind of honeycomb pattern, so we can call that honeycombness(positions), and get an overall measure of the quality of the thing (this is just a starter, the weighting or form of this can be whatever floats your boat):
var overallMeasure = areaIndex + honeycombnessIndex;
Then we have a mechanism to know how bad a guess is, and we can combine this with a mechanism for modifying the positions; the simplest is just to add a random amount to the x and y coords of each centre. Alternatively you can try moving each point towards neighbour areas which have an area too high, and away from those with an area too low.
This is not a straight solve, but it requires minimal maths apart from calculating the area closest to each point, and it's approachable. The difficult part may be recognising local minima and dealing with them.
Incidentally, it should be fairly easy to get the start points for the process; the centroids of the pie slices shouldn't be too far from the truth.
A definite plus is that you could use the intermediate calculations to animate a transition from pie to voronoi.

Categories