Tiling perlin noise seamlessly - java

I have been trying to figure out how to create infinite terrain in 3D using perlin noise. I have so far got a terrain that is made of chunks, and when the player moves out of a chunk, new chunks are generated. Chunks out of range are unloaded. So I have the illusion of an infinite world.
I am using perlin noise to create height maps for the chunks (each chunk has its own height map)
My question is how do I seamlessly tile the height map of each chunk so that there aren't horrible gaps in the world between chunks, and without having the same height map for every chunk.
By "gaps in the world" I mean this.
And I followed this to implement perlin noise
Here is my perlin noise code:
private float[][] perlinNoise(int width, int height, int octave, float[][] whiteNoise)
{
float[][] result = new float[width][height];
int samplePeriod = 1 << octave;
float sampleFrequency = 1.0f / samplePeriod;
for (int i = 0; i < width; i++)
{
int x1 = (i / samplePeriod) * samplePeriod;
int x2 = (x1 + samplePeriod) % width;
float xBlend = (i - x1) * sampleFrequency;
for (int j = 0; j < height; j++)
{
int y1 = (j / samplePeriod) * samplePeriod;
int y2 = (y1 + samplePeriod) % height;
float yBlend = (j - y1) * sampleFrequency;
float top = (float) MathHelper.interpolateLinear(whiteNoise[x1][y1], whiteNoise[x2][y1], xBlend);
float bottom = (float) MathHelper.interpolateLinear(whiteNoise[x1][y2], whiteNoise[x2][y2], xBlend);
result[i][j] = (float) MathHelper.interpolateLinear(top, bottom, yBlend);
}
}
return result;
}
public float[][] generatePerlinNoise(int width, int height, Random random, int octaveCount)
{
float[][] whiteNoise = new float[width][height];
float[][][] totalNoise = new float[octaveCount][][];
float[][] perlinNoise = new float[width][height];
float amplitude = 1.0f;
float totalAmplitude = 0.0f;
float persistance = 0.5f;
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
whiteNoise[i][j] = random.nextFloat() % 1;
}
}
for (int i = 0; i < octaveCount; i++)
{
totalNoise[i] = perlinNoise(width, height, i, whiteNoise);
}
for (int o = octaveCount - 1; o >= 0; o--)
{
amplitude *= persistance;
totalAmplitude += amplitude;
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
perlinNoise[i][j] += totalNoise[o][i][j] * amplitude;
}
}
}
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
perlinNoise[i][j] /= totalAmplitude;
}
}
return perlinNoise;
}
Edit: I have just asked about this on GameDev my question there might be more detailed and helpful. Please try and answer there if possible, because I will be looking at this post less and that one more.
Edit: I have realised that my noise code is NOT PERLIN NOISE. It is actually something called VALUE NOISE, which actually doesnt look as good, and wont work for what I need anyway. I cant find any good java implementation of perlin noise. And I dont just want a link to code I can use, I would like to have a tutorial, where I can understand how the algorithm actually works.

Related

Perceptron doesn't find the right line even with a bias (Processing)

My perceptron doesn't find the right y-intercept even though I added a bias. The slope is correct. This is my second try coding a perceptron from scratch and I got the same error twice.
The perceptron evaluates if a point on a canvas is higher or lower than the interception line. The inputs are the x-coordinate, y-coordinate and 1 for the bias.
Perceptron class:
class Perceptron
{
float[] weights;
Perceptron(int layerSize)
{
weights = new float[layerSize];
for (int i = 0; i < layerSize; i++)
{
weights[i] = random(-1.0,1.0);
}
}
float Evaluate(float[] input)
{
float sum = 0;
for (int i = 0; i < weights.length; i++)
{
sum += weights[i] * input[i];
}
return sum;
}
float Learn(float[] input, int expected)
{
float guess = Evaluate(input);
float error = expected - guess;
for (int i = 0; i < weights.length; i++)
{
weights[i] += error * input[i] * 0.01;
}
return guess;
}
}
This is the testing code:
PVector[] points;
float m = 1; // y = mx+q (in canvas space)
float q = 0; //
Perceptron brain;
void setup()
{
size(600,600);
points = new PVector[100];
for (int i = 0; i < points.length; i++)
{
points[i] = new PVector(random(0,width),random(0,height));
}
brain = new Perceptron(3);
}
void draw()
{
background(255);
DrawGraph();
DrawPoints();
//noLoop();
}
void DrawPoints()
{
for (int i = 0; i < points.length; i++)
{
float[] input = new float[] {points[i].x / width, points[i].y / height, 1};
int expected = ((m * points[i].x + q) < points[i].y) ? 1 : 0; // is point above line
float output = brain.Learn(input, expected);
fill(sign(output) * 255);
stroke(expected*255,100,100);
strokeWeight(3);
ellipse(points[i].x, points[i].y, 20, 20);
}
}
int sign(float x)
{
return x >= 0 ? 1 : 0;
}
void DrawGraph()
{
float y1 = 0 * m + q;
float y2 = width * m + q;
stroke(255,100,100);
strokeWeight(3);
line(0,y1,width,y2);
}
I found the problem
float guess = Evaluate(input);
float error = expected - guess;
should be
float guess = sign(Evaluate(input));
float error = expected - guess;
The output was never exactly one ore zero even if the answer would be correct. Because of this even the correct points gave a small error that stopped the perceptron from finding the right answer. By calculating the sign of the answer first the error is 0 if the answer is correct.

Why does this code only rotate squares?

I will use this algorithm for image rotation, however I realized that it only rotates squares, not rectangles.
Would anyone know why?
Main code-problem:
public static int[] rotate(double angle, int[] pixels, int width, int height) {
final double radians = Math.toRadians(angle);
final double cos = Math.cos(radians);
final double sin = Math.sin(radians);
final int[] pixels2 = new int[pixels.length];
for(int pixel = 0; pixel < pixels2.length; pixel++) {
pixels2[pixel] = 0xFFFFFF;
}
for(int x = 0; x < width; x++) {
for(int y = 0; y < height; y++) {
final int centerx = width / 2;
final int centery = height / 2;
final int m = x - centerx;
final int n = y - centery;
final int j = ((int) ( m * cos + n * sin ) ) + centerx;
final int k = ((int) ( n * cos - m * sin ) ) + centery;
if( j >= 0 && j < width && k >= 0 && k < height ){
pixels2[ ( y * width + x ) ] = pixels[ ( k * width + j ) ];
}
}
}
return pixels2;
}
Context application:
try {
BufferedImage testrot = ImageIO.read(new File("./32x32.png"));
int[] linearpixels = new int[testrot.getWidth() * testrot.getHeight()];
int c = 0;
for(int i = 0; i < testrot.getWidth(); i++){
for(int j = 0; j < testrot.getHeight(); j++){
linearpixels[c] = testrot.getRGB(i, j);
c++;
}
}
int[] lintestrot = rotate(50, linearpixels, 32, 32);
BufferedImage image = new BufferedImage(70, 70, BufferedImage.TYPE_INT_RGB);
c = 0;
for(int i = 0; i < 32; i++){
for(int j = 0; j < 32; j++){
image.setRGB(i, j, lintestrot[c]);
c++;
}
}
File outputfile = new File("test002.bmp");
ImageIO.write(image, "bmp", outputfile);
} catch (IOException e1) {
e1.printStackTrace();
}
If you alter to 33 width or height the result will be wrong (wrong image).
You algorithm actually does work. The problem is with your loops in your context application. Because the pixels are stored in raster order, the outer loop needs to iterate to the height and the inner loop iterates to the width, e.g:
for(int i = 0; i < testrot.getHeight(); i++){
for(int j = 0; j < testrot.getWidth(); j++){
linearpixels[c] = testrot.getRGB(j, i); //edit here, tested
c++;
}
}
Then if you change height to 40 for example:
int[] lintestrot = rotate(50, linearpixels, 32, 40);
The loops need to change like this:
c = 0;
for(int i = 0; i < 40; i++){
for(int j = 0; j < 32; j++){
image.setRGB(i, j, lintestrot[c]);
c++;
}
}
Note that the order is reversed in the loops (height then width) compared to the function call (width then height).

Edit 2D array instance variable size without Array List (image manipulation)

I need to edit the original instance variable private in[][] pixels; to be twice the width, I've done the algorithm to mirror the image and make a new array twice as wide I just don't know how to set the original int[][] pixels to it. The pixels array has to be the one modified, it can't go by another name.
private int[][] pixels;
...
if(transformationName == "Mirror"){
int[][] mirrorTemp = new int[height][width*2];
for(int h = 0; h < height; h++){
for(int w = 0; w < width; w++){
mirrorTemp[h][w] = pixels[h][w];
mirrorTemp[h][w + width] = pixels[h][width - h - 1];
}
}
int[][] pixels = new int[height][width*2];
for(int h = 0; h < height; h++){
for(int w = 0; w < (width*2); w++){
pixels[h][w] = mirrorTemp[h][w];
}
}
}
First, I believe the following is what you intended to do.
for(int h = 0; h < height; h++){
for(int w = 0; w < width; w++){
mirrorTemp[h][w] = pixels[h][w];
mirrorTemp[h][w + width] = pixels[h][width - w];
}
}
After this, you can simply
pixels = mirrorTemp;
since the two are both int[][] type.
Hope this helps.

Resize a matrix in Java

I have a matrix double[][] with arbitrary dimensions but bigger than 300 (maybe in one or maybe on both dimensions). I want to scale it to double[300][300].
My main approach is to interpolate the matrix and bring it up to double[600][600] and then take four elements and find their average, i.e. the elements 0,0, 0,1, 1,0 and 1,1 will be the 0,0 of the final 300x300 matrix.
I have found the interpolation library in JAVA but I cannot figure out how to use it. Can anyone provide some examples or info?
The library is: http://docs.oracle.com/cd/E17802_01/products/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/Interpolation.html
Thnx.
What about writing a simple method that maps source cells to destination, then averages out?
public static boolean matrixReduce(double[][] dst, double[][] src) {
double dstMaxX = dst.length - 1, dstMaxY = dst[0].length - 1;
double srcMaxX = src.length - 1, srcMaxY = src[0].length - 1;
int count[][] = new int[dst.length][dst[0].length];
for (int x = 0; x < src.length; x++) {
for (int y = 0; y < src[0].length; y++) {
int xx = (int) Math.round((double) x * dstMaxX / srcMaxX);
int yy = (int) Math.round((double) y * dstMaxY / srcMaxY);
dst[xx][yy] += src[x][y];
count[xx][yy]++;
}
}
for (int x = 0; x < dst.length; x++) {
for (int y = 0; y < dst[0].length; y++) {
dst[x][y] /= count[x][y];
}
}
return true;
}

Not sure why this short processing assignment isn't working

This is a homework assignment.
Work 19 5/16 is the assignment
http://sites.stuycs.org/home/courses/ml2x/dyrland-weaver/work
I am running this in the program processing, which does not require main methods.
Blob was given to us. We had to make BlobRunner on our own.
Any advice on why my code isn't doing what its supposed to would be appreciated.
FIRST FILE BlobRunner
int popSize = 4;
int wobble = 2;
int numSides = 4;
float rad = 100;
int radInt = (int) rad;
float a = sqrt(popSize);
int rootPop = (int) a;
Blob[][] blobs = new Blob[popSize/rootPop][rootPop];
/*=====================================
The trickiest part of setup is to make
the screen an appropriate size for the
grid of blobs. The grid should be just
big enough to contain all of the blobs.
====================================*/
void setup() {
size ((popSize/rootPop)*(2*(radInt+3)), rootPop*(2*(radInt+3)));
populate();
}
/*=====================================
The main purpose of draw is to go through
the array of blobs and display each.
====================================*/
void draw() {
int createdSoFar = 0;
for (int i = 0; i<rootPop; i++){
for (int j = 0; j<popSize/rootPop; j++){
if (createdSoFar < popSize){
blobs[j][i].display();
}
createdSoFar++;
}
}
}
/*=====================================
Populate the array of blobs.
You can use any values for radius, number of sides
and wobble factor that you'd like, but you must
use x and y coordinates that ensure the blobs
are drawn in a grid without overlaping each other.
Your code should work for any reasonable value
of population (i.e. something that would fit on a
normal monitor).
====================================*/
void populate() {
for (int i = 0; i < rootPop; i++){
float y = 1;
for (int j = 0; j < (popSize/rootPop); j++){
float x = 1;
blobs[j][i] = new Blob (x*(rad+3), y*(rad+3), numSides, radInt, wobble, wobble);
x=x+2;}
y=y+2;}
}
SECOND FILE Blob
/*=====================================
A Blob object is a regular polygon variant that
can have various features.
Instance Variables:
numSides: number of sides
rad: distance from the center of the polygon
to any vertext
x: x coordinate of the center
y: y coordinate of the center
xFactor: "wobble" foctor in the x direction
yFactor: "wobble" factor in the y direction
====================================*/
class Blob {
int numSides;
int rad;
float x;
float y;
int xFactor;
int yFactor;
Blob(float cx, float cy, int sides, int r, int xf, int yf ) {
x = cx;
y = cy;
numSides = sides;
rad = r;
xFactor = xf;
yFactor = yf;
}
void display() {
float nx;
float ny;
int rx, ry;
float sy;
strokeWeight(1);
beginShape();
for( float t = 0; t <= 1; t+=( 1.0/numSides ) ) {
/*
"wobble" effect is created by adding a random number to each
x and y coordinate. The larger the x and y factors, the higher
the possible wobble value could be
*/
rx = (int)random(xFactor);
ry = (int)random(yFactor);
nx = rad * cos( 2 * PI * t ) + x + rx;
ny = rad * sin( 2 * PI * t ) + y + ry;
vertex(nx, ny);
}
endShape();
}
}
Your code runs, thus it is doing what you asked it to do and nothing more.
I asked my cat to check it out though and she was all, "the guy is re-initializing his variables inside each pass of the loop, he'll never get a grid of blobs that way. Tell him to start by moving float y = 1; float x = 1; in populate() outside of the bounds of the two for loops and start debugging from there."
Then she rolled over on to her side and I patted her.

Categories

Resources