Perlin noise generating visible "blocky" formations, Java - java

I've been trying to implement a perlin noise generator in java, based on this article. Homever, my generator produces noise that is not continuous but instead "blocky", forming visible lines between every even numbered -coordinate. Below is my current code:
private static final Point[] grads = {
new Point(1, 0), new Point(-1, 0), new Point(0, 1), new Point(0, -1),
new Point(1, 1), new Point(1, -1), new Point(-1, 1), new Point(-1, -1)
};
private int permutations[] = new int[512];
private int frequency;
private int seed;
private double[][] heightMap;
private double amplitude;
public PerlinNoise(int frequency, int seed, double[][] heightMap, double amplitude) {
this.frequency = frequency;
this.seed = seed; //Seed for randomizing the permutation table
this.heightMap = heightMap; //The Heightmap where the finalt result will be stored
this.amplitude = amplitude;
}
private void seedPermutationTables() {
LinkedList<PermutationValue> l = new LinkedList<PermutationValue>();
Random rand = new Random(this.seed);
for (int i = 0; i < 256; i++) {
l.add(new PermutationValue(i, rand));
}
Collections.sort(l);
for (int i = 0; i < 512; i++) {
permutations[i] = l.get(i & 255).getValue();
}
}
public void generateNoise() {
this.seedPermutationTables();
int sWidth = this.heightMap.length / frequency;
int sHeight = this.heightMap[0].length / frequency;
for (int i = 0; i < this.heightMap.length; i++) {
for (int j = 0; j < this.heightMap[i].length; j++) {
double x = (double)i / sWidth;
double y = (double)j / sHeight;
this.heightMap[i][j] = this.noise(x, y);
}
}
}
private double noise(double x, double y) {
int xi = (int)x & 255;
int yi = (int)y & 255;
double xf = x - (int)x;
double yf = y - (int)y;
double u = this.fade(xf);
double v = this.fade(yf);
int aa = permutations[permutations[xi] + yi];
int ab = permutations[permutations[xi] + yi + 1];
int ba = permutations[permutations[xi + 1] + yi];
int bb = permutations[permutations[xi + 1] + yi + 1];
double x1 = this.lerp(this.grad(aa, xf, yf), this.grad(ab, xf - 1, yf), u);
double x2 = this.lerp(this.grad(ba, xf, yf - 1), this.grad(bb, xf - 1, yf - 1), u);
double noise = this.lerp(x1, x2, v);
return (1D + noise) / 2 * this.amplitude; //The noise returns values between -1 and 1
//So we change the range to 0-amplitude
}
private double grad(int hash, double x, double y) {
hash = hash & 7;
Point p = grads[hash];
return p.x * x + p.y * y;
}
private double lerp(double a, double b, double x) {
return a + x * (b - a);
}
private double fade(double x) {
return x * x * x * (x * (x * 6 - 15) + 10);
}
private class PermutationValue implements Comparable<PermutationValue> {
private int value;
private double sortValue;
public PermutationValue(int value, Random rand) {
this.setValue(value);
this.sortValue = rand.nextDouble();
}
#Override
public int compareTo(PermutationValue pv) {
if (pv.sortValue > this.sortValue) {
return -1;
}
return 1;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
The heightmap array simply stores the height value for every pixel. Any suggestions or ideas what might be causing these formations?

hash tables can be replaced with 1-2 multiplications as in rndng fct:
blocky can come from lack of cubic interpolation or digital noise from the hash table.
in your case it sounds like it's not lerping between two values of the hash table. lerp just takes any 2 values and smooths between them. so if that's not running ok, it's blocky.
function rndng ( n: float ): float //total noise pseudo
{//random proportion -1, 1
var e = ( n *321.9)%1;
return (e*e*111.0)%2-1;
}
function lerps(o:float, v:float, alpha:float):float
{
o += ( v - o ) * alpha;
return o;
}
function lnz ( vtx: Vector3 ): float//3d noise
{
vtx= Vector3 ( Mathf.Abs(vtx.x) , Mathf.Abs(vtx.y) , Mathf.Abs(vtx.z) ) ;
var I = Vector3 (Mathf.Floor(vtx.x),Mathf.Floor(vtx.y),Mathf.Floor(vtx.z));
var D = Vector3(vtx.x%1,vtx.y%1,vtx.z%1);
D = Vector3(D.x*D.x*(3.0-2.0*D.x),D.y*D.y*(3.0-2.0*D.y),D.z*D.z*(3.0-2.0*D.z));
var W = I.x + I.y*71.0 + 125.0*I.z;
return lerps(
lerps( lerps(rndng(W+0.0),rndng(W+1.0),D.x) , lerps(rndng(W+71.0),rndng(W+72.0),D.x) , D.y)
,
lerps( lerps(rndng(W+125.0),rndng(W+126.0),D.x) , lerps(rndng(W+153.0),rndng(W+154.0),D.x) , D.y)
,
D.z
);
}
function lnzo ( vtx: Vector3 ): float
{
var total = 0.0;
for (var i:int = 1; i < 5; i ++)
{
total+= lnz2(Vector3 (vtx.x*(i*i),0.0,vtx.z*(i*i)))/(i*i);
}
return total*5;
}
function lnzh ( vtx: Vector3 ): float//3 axis 3d noise
{
vtx= Vector3 ( Mathf.Abs(vtx.z) , Mathf.Abs(vtx.z*.5-vtx.x*.866) , Mathf.Abs(vtx.z*.5+vtx.x*.866) ) ;
var I = Vector3 (Mathf.Floor(vtx.x),Mathf.Floor(vtx.y),Mathf.Floor(vtx.z));
var D = Vector3(vtx.x%1,vtx.y%1,vtx.z%1);
//D = Vector3(D.x*D.x*(3.0-2.0*D.x),D.y*D.y*(3.0-2.0*D.y),D.z*D.z*(3.0-2.0*D.z));
var W = I.x + I.y*71.0 + 125.0*I.z;
return lerps(
lerps( lerps(rndng(W+0.0),rndng(W+1.0),D.x) , lerps(rndng(W+71.0),rndng(W+72.0),D.x) , D.y)
,
lerps( lerps(rndng(W+125.0),rndng(W+126.0),D.x) , lerps(rndng(W+153.0),rndng(W+154.0),D.x) , D.y)
,
D.z
);
}
function lnz2 ( vtx: Vector3 ): float//2d noise
{
vtx= Vector3 ( Mathf.Abs(vtx.x) , Mathf.Abs(vtx.y) , Mathf.Abs(vtx.z) ) ;
var I = Vector3 (Mathf.Floor(vtx.x),Mathf.Floor(vtx.y),Mathf.Floor(vtx.z));
var D = Vector3(vtx.x%1,vtx.y%1,vtx.z%1);
D = Vector3(D.x*D.x*(3.0-2.0*D.x),D.y*D.y*(3.0-2.0*D.y),D.z*D.z*(3.0-2.0*D.z));
var W = I.x + I.y*71.0 + 125.0*I.z;
return lerps(
lerps( lerps(rndng(W+0.0),rndng(W+1.0),D.x) , lerps(rndng(W+71.0),rndng(W+72.0),D.x) , D.z)
,
lerps( rndng(W+125.0), rndng(W+126.0),D.x)
,
D.z
);
}

Related

draw mandlebrot onto bitmap

I am currently converting java code into c# code and i have it almost working i think but I am trying to draw the mandlebrot onto the bitmap but nothing is displaying . The form pops up but nothing is drawn onto it.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Assignment1
{
public partial class Form1 : Form
{
public Form1()
{
init();
start();
stop();
destroy();
InitializeComponent();
}
public struct HSBColor
{
float h;
float s;
float b;
int a;
public HSBColor(float h, float s, float b)
{
this.a = 0xff;
this.h = Math.Min(Math.Max(h, 0), 255);
this.s = Math.Min(Math.Max(s, 0), 255);
this.b = Math.Min(Math.Max(b, 0), 255);
}
public HSBColor(int a, float h, float s, float b)
{
this.a = a;
this.h = Math.Min(Math.Max(h, 0), 255);
this.s = Math.Min(Math.Max(s, 0), 255);
this.b = Math.Min(Math.Max(b, 0), 255);
}
public float H
{
get { return h; }
}
public float S
{
get { return s; }
}
public float B
{
get { return b; }
}
public int A
{
get { return a; }
}
public Color Color
{
get
{
return FromHSB(this);
}
}
public static Color FromHSB(HSBColor hsbColor)
{
float r = hsbColor.b;
float g = hsbColor.b;
float b = hsbColor.b;
if (hsbColor.s != 0)
{
float max = hsbColor.b;
float dif = hsbColor.b * hsbColor.s / 255f;
float min = hsbColor.b - dif;
float h = hsbColor.h * 360f / 255f;
if (h < 60f)
{
r = max;
g = h * dif / 60f + min;
b = min;
}
else if (h < 120f)
{
r = -(h - 120f) * dif / 60f + min;
g = max;
b = min;
}
else if (h < 180f)
{
r = min;
g = max;
b = (h - 120f) * dif / 60f + min;
}
else if (h < 240f)
{
r = min;
g = -(h - 240f) * dif / 60f + min;
b = max;
}
else if (h < 300f)
{
r = (h - 240f) * dif / 60f + min;
g = min;
b = max;
}
else if (h <= 360f)
{
r = max;
g = min;
b = -(h - 360f) * dif / 60 + min;
}
else
{
r = 0;
g = 0;
b = 0;
}
}
return Color.FromArgb
(
hsbColor.a,
(int)Math.Round(Math.Min(Math.Max(r, 0), 255)),
(int)Math.Round(Math.Min(Math.Max(g, 0), 255)),
(int)Math.Round(Math.Min(Math.Max(b, 0), 255))
);
}
}
private const int MAX = 256; // max iterations
private const double SX = -2.025; // start value real
private const double SY = -1.125; // start value imaginary
private const double EX = 0.6; // end value real
private const double EY = 1.125; // end value imaginary
private static int x1, y1, xs, ys, xe, ye;
private static double xstart, ystart, xende, yende, xzoom, yzoom;
private static bool action, rectangle, finished;
private static float xy;
private Image picture;
private Graphics g1;
private Cursor c1, c2;
//private HSB HSBcol=new HSB();
public void init() // all instances will be prepared
{
//HSBcol = new HSB();
this.Size = new Size(640,480);
finished = false;
//addMouseListener(this);
//addMouseMotionListener(this);
//c1 = new Cursor(Cursor.WAIT_CURSOR);
//c2 = new Cursor(Cursor.CROSSHAIR_CURSOR);
x1 = this.Width;
y1 = this.Height;
xy = (float)x1 / (float)y1;
Bitmap img = new Bitmap(1, 1);
g1 = Graphics.FromImage(img);
finished = true;
}
public void destroy() // delete all instances
{
if (finished)
{
//removeMouseListener(this);
//removeMouseMotionListener(this);
picture = null;
g1 = null;
c1 = null;
c2 = null;
GC.Collect(); // garbage collection
}
}
public void start()
{
action = false;
rectangle = false;
initvalues();
xzoom = (xende - xstart) / (double)x1;
yzoom = (yende - ystart) / (double)y1;
mandelbrot();
}
public void stop()
{
}
public void paint(Graphics g)
{
update(g);
}
public void update(Graphics g)
{
g.DrawImage(picture, 0, 0);
if (rectangle)
{
Pen WhitePen = new Pen(Color.White);
if (xs < xe)
{
if (ys < ye) g.DrawRectangle(WhitePen, xs, ys, (xe - xs), (ye - ys));
else g.DrawRectangle(WhitePen, xs, ye, (xe - xs), (ys - ye));
}
else
{
if (ys < ye) g.DrawRectangle(WhitePen, xe, ys, (xs - xe), (ye - ys));
else g.DrawRectangle(WhitePen, xe, ye, (xs - xe), (ys - ye));
}
}
}
private void mandelbrot() // calculate all points
{
int x, y;
float h, b, alt = 0.0f;
Pen FractalPen;
action = false;
//SetCursor(c1);
//showStatus("Mandelbrot-Set will be produced - please wait...");
for (x = 0; x < x1; x+=2)
for (y = 0; y < y1; y++)
{
h = pointcolour(xstart + xzoom * (double)x, ystart + yzoom * (double)y); // color value
if (h != alt)
{
b = 1.0f - h * h; // brightnes
///djm added
//HSBcol.fromHSB(h,0.8f,b); //convert hsb to rgb then make a Java Color
Color color = HSBColor.FromHSB(new HSBColor(h * 255, 0.8f * 255, b * 255)); // VERY IMPORTANT
//g1.setColor(col);
//djm end
//djm added to convert to RGB from HSB
//g1.setColor(Color.getHSBColor(h, 0.8f, b));
//djm test
//Color col = Color.getHSBColor(h,0.8f,b);
//int red = col.getRed();
//int green = col.getGreen();
//int blue = col.getBlue();
//djm
alt = h;
FractalPen = new Pen(color);
g1.DrawLine(FractalPen, x, y, x + 1, y);
}
}
//showStatus("Mandelbrot-Set ready - please select zoom area with pressed mouse.");
//setCursor(c2);
action = true;
}
private float pointcolour(double xwert, double ywert) // color value from 0.0 to 1.0 by iterations
{
double r = 0.0, i = 0.0, m = 0.0;
int j = 0;
while ((j < MAX) && (m < 4.0))
{
j++;
m = r * r - i * i;
i = 2.0 * r * i + ywert;
r = m + xwert;
}
return (float)j / (float)MAX;
}
private void initvalues() // reset start values
{
xstart = SX;
ystart = SY;
xende = EX;
yende = EY;
if ((float)((xende - xstart) / (yende - ystart)) != xy )
xstart = xende - (yende - ystart) * (double)xy;
}
/*public void mousePressed(MouseEvent e)
{
e.consume();
if (action)
{
xs = e.getX();
ys = e.getY();
}
}
public void mouseReleased(MouseEvent e)
{
int z, w;
e.consume();
if (action)
{
xe = e.getX();
ye = e.getY();
if (xs > xe)
{
z = xs;
xs = xe;
xe = z;
}
if (ys > ye)
{
z = ys;
ys = ye;
ye = z;
}
w = (xe - xs);
z = (ye - ys);
if ((w < 2) && (z < 2)) initvalues();
else
{
if (((float)w > (float)z * xy)) ye = (int)((float)ys + (float)w / xy);
else xe = (int)((float)xs + (float)z * xy);
xende = xstart + xzoom * (double)xe;
yende = ystart + yzoom * (double)ye;
xstart += xzoom * (double)xs;
ystart += yzoom * (double)ys;
}
xzoom = (xende - xstart) / (double)x1;
yzoom = (yende - ystart) / (double)y1;
mandelbrot();
rectangle = false;
repaint();
}
}
public void mouseEntered(MouseEvent e)
{
}
public void mouseExited(MouseEvent e)
{
}
public void mouseClicked(MouseEvent e)
{
}
public void mouseDragged(MouseEvent e)
{
e.consume();
if (action)
{
xe = e.getX();
ye = e.getY();
rectangle = true;
repaint();
}
}
public void mouseMoved(MouseEvent e)
{
}
public String getAppletInfo()
{
return "fractal.class - Mandelbrot Set a Java Applet by Eckhard Roessel 2000-2001";
}*/
}
}
Bitmap img = new Bitmap(1, 1);
This could be the problem. You forgot to replace it with width,height. Like this
Bitmap img = new Bitmap(x1, y1);
call your paint method like this (picturebox is not needed, but for me it was fastest when painting with winforms:
Rectangle r = new Rectangle();
var g = pictureBox1.CreateGraphics();
var pea = new PaintEventArgs(g, r);
yourPaintMethod(pea);
calls:
public void yourPaintMethod(PaintEventArgs e ) {
Graphics g = e.Graphics;
Pen pBlack = new Pen(Color.Black, 1);
g.DrawLine(pBlack........ etc.

Java - Sorting a Set of Points Based on Both X and Y Coordinates

I have a list of point objects that need to be sorted by both X and Y coordinates, but when I pass them to a comparator object only one coordinate gets sorted (the first one called). Any ideas to why this might be happening?
static public List<Point> convertToThreeByThreeGrid(String points) {
String[] ptsArray;
List<Point> ptsList = new ArrayList<>();
String stripString = points.replace("[", "").replace("]", "").replace("(", "").replace(")", "").replace(" ", ",").trim();
ptsArray = stripString.split(",");
for(int i = 0; i < ptsArray.length; i += 2) {
int x = Integer.parseInt(ptsArray[i]);
int y = Integer.parseInt(ptsArray[i + 1]);
System.out.println("X: " + x);
System.out.println("Y: " + y);
ptsList.add(new Point(x, y));
}
Collections.sort(ptsList, new Comparator<Point>() {
public int compare(Point a, Point b) {
int result = Integer.compare((int) a.getX(), (int) b.getX());
if (result == 0 ) {
result = Integer.compare((int) a.getY(), (int) b.getY());
}
return result;
}
});
// subtract each coordinate by smallest x and y coordinate values
List<Point> convertedPtList = new ArrayList<>();
int smallestX = (int) ptsList.get(0).getX();
int smallestY = (int) ptsList.get(0).getY();
for (int i = 1; i < ptsList.size(); i++) {
int x = ((int) ptsList.get(i).getX() - smallestX);
int y = ((int) ptsList.get(i).getY() - smallestY);
convertedPtList.add(new Point(x, y));
}
return convertedPtList;
}
}
Output:
[java.awt.Point[x=10,y=26], java.awt.Point[x=10,y=26], java.awt.Point[x=10,y=28], java.awt.Point[x=12,y=26]]
[java.awt.Point[x=13,y=26], java.awt.Point[x=13,y=28], java.awt.Point[x=13,y=28], java.awt.Point[x=14,y=27], java.awt.Point[x=14,y=27], java.awt.Point[x=15,y=26], java.awt.Point[x=15,y=28], java.awt.Point[x=15,y=28]]
[java.awt.Point[x=16,y=26], java.awt.Point[x=16,y=28], java.awt.Point[x=16,y=28], java.awt.Point[x=18,y=26], java.awt.Point[x=18,y=26], java.awt.Point[x=18,y=28]]
for(int i = 0; i < ptsArray.length; i += 2) {
int x = Integer.parseInt(ptsArray[i]);
int y = Integer.parseInt(ptsArray[i+1]);
ptsList.add(new Point(x, y));
}
Collections.sort( ptsList, new Comparator<Point>() {
public int compare(Point x1, Point x2) {
int result = Double.compare(x1.getX(), x2.getX());
if ( result == 0 ) {
// both X are equal -> compare Y too
result = Double.compare(x1.getY(), x2.getY());
}
return result;
}
});
// ptsList is now sorted by both X and Y!
Edit:
To just find the lowest X and the lowest Y you can also go the 'classic' way without any (double-)sorting:
int minX = Integer.MAX_VALUE;
int minY = Integer.MAX_VALUE;
for ( Point p : ptsList ) {
final int x = (int)p.getX();
final int y = (int)p.getY();
if ( x < minX ) {
minX = x;
}
if ( y < minY ) {
minY = y;
}
}

java graphics gouraud shading

I want to fill triangles with gouraud shading
I calculated normals for each vertex and used the following code but it dosn't work correctly
I interpolated colors against y using these formulas
Ir = Ir2 - (Ir2 - Ir1)* (v2.y -y)/dy;
Ig = Ig2 - (Ig2 - Ig1)* (v2.y -y)/dy;
Ib = Ib2 - (Ib2 - Ib1)* (v2.y -y)/dy;
and against x direction using
rr = r2- (r2-r1)*(Xs2-j)/dxs;
in method drawCurrentTriangle(Graphics2D g) how can i calculate color from interpolated vertex normal.(there is no lights in the scene (only triangle color))
public boolean convert(Triangle triangle) {
ensureCapacity();
clearCurrentScan();
triangle.getVlist()[0].r = triangle.normals[0].x;
triangle.getVlist()[0].g = triangle.normals[0].y;
triangle.getVlist()[0].b = triangle.normals[0].z;
triangle.getVlist()[1].r = triangle.normals[1].x;
triangle.getVlist()[1].g = triangle.normals[1].y;
triangle.getVlist()[1].b = triangle.normals[1].z;
triangle.getVlist()[2].r = triangle.normals[2].x;
triangle.getVlist()[2].g = triangle.normals[2].y;
triangle.getVlist()[2].b = triangle.normals[2].z;
for (int i = 0; i < 3; i++) {
Vector3d v1 = triangle.getVlist()[i];
Vector3d v2;
if (i == 2) {
v2 = triangle.getVlist()[0];
} else {
v2 = triangle.getVlist()[i + 1];
}
// ensure v1.y < v2.y
if (v1.y > v2.y) {
Vector3d temp = v1;
v1 = v2;
v2 = temp;
}
double dy = v2.y - v1.y;
Ir1 = v1.r;
Ig1 = v1.g;
Ib1 = v1.b;
Ir2 = v2.r;
Ig2 = v2.g;
Ib2 = v2.b;
// ignore horizontal lines
if (dy == 0) {
continue;
}
int startY = Math.max(FastMath.ceil(v1.y), minY);
int endY = Math.min(FastMath.ceil(v2.y) - 1, maxY);
top = Math.min(top, startY);
bottom = Math.max(bottom, endY);
double dx = v2.x - v1.x;
double Ir;
double Ig;
double Ib;
double Ic;
double Ia;
double Yc;
// special case: vertical line
if (dx == 0) {
int x = FastMath.ceil(v1.x);
// ensure x within view bounds
x = Math.min(maxX + 1, Math.max(x, minX));
for (int y = startY; y <= endY; y++) {
Ir = Ir2 - (Ir2 - Ir1)* (v2.y -y)/dy;
Ig = Ig2 - (Ig2 - Ig1)* (v2.y -y)/dy;
Ib = Ib2 - (Ib2 - Ib1)* (v2.y -y)/dy;
scans[y].setBoundary(x, Ir, Ig, Ib);
}
} else {
// scan-convert this edge (line equation)
double gradient = dx / dy;
// (slower version)
for (int y = startY; y <= endY; y++) {
int x = FastMath.ceil(v1.x + (y - v1.y) * gradient);
// ensure x within view bounds
x = Math.min(maxX + 1, Math.max(x, minX));
Ir = Ir2 - (Ir2 - Ir1)* (v2.y -y)/dy;
Ig = Ig2 - (Ig2 - Ig1)* (v2.y -y)/dy;
Ib = Ib2 - (Ib2 - Ib1)* (v2.y -y)/dy;
scans[y].setBoundary(x, Ir, Ig, Ib);
}
// check if visible (any valid scans)
for (int i = top; i <= bottom; i++) {
if (scans[i].isValid()) {
return true;
}
}
return false;
}
}
}
protected void drawCurrentTriangle(Graphics2D g) {
int y = scanConverter.getTopBoundary();
double Xs1 = 0;
double Xs2 = 0;
double dxs = 0;
double r1 = 0;
double g1 = 0;
double b1 = 0;
double r2 = 0;
double g2 = 0;
double b2 = 0;
double rr = 0;
double gg = 0;
double bb = 0;
while (y <= scanConverter.getBottomBoundary()) {
GouraudTriangleScanConverter.Scan scan = scanConverter.getScan(y);
if (scan.isValid()) {
r1 = scan.rL;
g1 = scan.gL;
b1 = scan.bL;
r2 = scan.rR;
g2 = scan.gR;
b2 = scan.bR;
Xs1 = scan.left;
Xs2 = scan.right;
dxs = Xs2-Xs1;
for (int j = scan.left; j < scan.right; j++) {
rr = r2- (r2-r1)*(Xs2-j)/dxs;
gg = g2- (g2-g1)*(Xs2-j)/dxs;
bb = b2- (b2-b1)*(Xs2-j)/dxs;
if(rr > 255) rr = 255;
if(gg > 255) gg = 255;
if(bb > 255) bb = 255;
g.setColor(new Color((int)rr, (int)gg, (int)bb));
g.drawLine(j,y,j,y);
}
//g.drawLine(scan.right,y,scan.right,y);
}
y++;
}
}
public static class Scan {
public int left;
public int right;
public double rL = -1;
public double gL = -1;
public double bL = -1;
public double rR = -1;
public double gR = -1;
public double bR = -1;
/**
* Sets the left and right boundary for this scan if
* the x value is outside the current boundary.
*/
public void setBoundary(int x, double r, double g, double b) {
if (x > max)
max = x;
if (x < left) {
left = x;
rL = r;
gL = g;
bL = b;
}
if (x - 1 > right) {
right = x - 1;
rR = r;
gR = g;
bR = b;
}
}
/**
* Determines if this scan is valid (if left <= right).
*/
public boolean isValid() {
return (left <= right);
}
}
how can i apply colors to mesh.when i in
fix colors(no lighting)

Java perlin noise

I need to make perlin noise like in AS3.0:
bitmapData.perlinNoise(baseX, baseY, numOctaves,
randomSeed, stitch, fractalNoise, grayScale, offsets);
It's seamless noise:
I found a lot of material about it, but I can't make it like in my as3.0 image. Java code:
import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class Noise extends JPanel{
public static int octaves = 4;
public static int size = 128;
public static float[][][] noise = new float[size][size][octaves];
public static float[][] perlinnoise = new float[size][size];
public static float p = (float) 1/4;
public static Random gen = new Random();
public static float GenerateNoise() {
return gen.nextFloat();
}
public static float SmoothNoise(int x, int y, int z) {
try{
float corners = (noise[x - 1][y - 1][z] + noise[x + 1][y - 1][z] + noise[x - 1][y + 1][z] + noise[x + 1][y + 1][z]) / 16;
float sides = (noise[x - 1][y][z] + noise[x + 1][y][z] + noise[x][y - 1][z] + noise[x][y + 1][z]) / 8;
float center = noise[x][y][z] / 4;
return corners + sides + center;
}catch(Exception e) {
return 0;
}
}
public static float InterpolatedNoise(float x, float y, int pX, int pY, int pZ) {
int intX = (int) x;
int intY = (int) y;
float fracX = x - intX;
float fracY = y - intY;
float v1 = SmoothNoise(pX, pY, pZ);
float v2 = SmoothNoise(pX + 1, pY, pZ);
float v3 = SmoothNoise(pX, pY + 1, pZ);
float v4 = SmoothNoise(pX + 1, pY + 1, pZ);
float i1 = Interpolate(v1, v2, fracX);
float i2 = Interpolate(v3, v4, fracX);
return Interpolate(i1, i2, fracY);
}
public static float Interpolate(float a, float b, float x) {
float ft = (float) (x * 3.1415927);
float f = (float) ((1 - Math.cos(ft)) * 0.5);
return (float) (a * (1 - f) + b * f);
}
public static float Perlin2D(float x, float y, int posX, int posY, int posZ) {
float total = 0;
for(int i = 0; i < octaves; i++) {
double f = Math.pow(2, i);
double a = Math.pow(p, i);
total = (float) (total + InterpolatedNoise((float)(x * f), (float)(y * f), posX, posY, posZ) * a);
}
return total;
}
public static void main(String [] args) {
for(int z = 0; z < octaves; z++) {
for(int y = 0; y < size; y++) {
for(int x = 0; x < size; x++) {
noise[x][y][z] = GenerateNoise();
}
}
}
for(int z = 0; z < octaves; z++) {
for(int y = 0; y < size; y++) {
for(int x = 0; x < size; x++) {
perlinnoise[x][y] = Perlin2D(x / (size - 1), y / (size - 1), x, y, z) / octaves;
}
}
}
JFrame f = new JFrame("Perlin Noise");
f.setSize(400, 400);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new Noise());
f.setVisible(true);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
for(int y = 0; y < size; y++) {
for(int x = 0; x < size; x++) {
g.setColor(new Color(perlinnoise[x][y], perlinnoise[x][y], perlinnoise[x][y]));
g.fillRect(x * 2, y * 2, 2, 2);
}
}
repaint();
}
}
Help please!
The trick is, the Perlin noise does not use pseudo-random generator, it uses a function that takes an argument and returns predefined value for that argument, but when argument shifts by 1, the value jumps almost randomly. Check the sources for the permutation formulae, the init() method makes a permutation that then is used to make the entire noise.

Collision Bug in 2D Platformer Game

I am currently developing a 2D Mario-Like Platformer Game. I ran into a collision problem i've been trying to solve for a while now, but nothing seems to work :/
Basicly, i have a CenterLayer, which stores at which Position what kind of Tile is.
Then i have some Sprites and a Player, which should collide with these Tiles.
Because these Tiles can be triangular shaped (or any other kind of convex polygon), i decided to handle collision via SAT (Seperating Axis Theorem). This works great, but when it comes to collision with the floor where many tiles are adjacent to eachother and the sprite is moving left, it pickes the wrong edge and moves the Sprite to the right, but expected result would be moving it up. This causes the sprite to get stuck.
This is the code im currently using:
package level;
import java.awt.Polygon;
import tiles.Tile;
import sprites.*;
public class Collider {
/** Collide Sprite (or Player) with CenterLayer **/
public static void collide(Sprite s, CenterLayer c){
CollisionPolygon ps = s.getPolygon();
//Get blocks to collide with
int startXTile = (int) (s.getX() / CenterLayer.TILE_WIDTH) - 1;
int endXTile = (int) Math.ceil((s.getX() + s.getWidth()) / CenterLayer.TILE_WIDTH) + 1;
int startYTile = (int) (s.getY() / CenterLayer.TILE_HEIGHT) - 1;
int endYTile = (int) Math.ceil((s.getY() + s.getHeight()) / CenterLayer.TILE_HEIGHT) +1;
//limit to level boundaries
if(startXTile < 0) startXTile = 0;
if(endXTile > c.LEVEL_WIDTH) endXTile = c.LEVEL_WIDTH;
if(startYTile < 0) startYTile = 0;
if(endYTile > c.LEVEL_HEIGHT) endYTile = c.LEVEL_HEIGHT;
int sizeX = endXTile - startXTile;
int sizeY = endYTile - startYTile;
//loop through tiles and collide
for(int xc = 0; xc < sizeX; xc++)
for(int yc = 0; yc < sizeY; yc++){
int xblock = xc + startXTile;
int yblock = yc + startYTile;
Tile t = c.getTile(xblock, yblock);
if(t!=null){ //if tile == null --> tile is air
CollisionPolygon pt = t.getPolygon(xblock, yblock);
double[] projection = PolygonCollision(ps, pt);
//if collision has happened
if(projection[0] != 0 || projection[1] != 0){
//collide
s.moveBy(projection[0], projection[1]);
//update sprites polygon to new position
ps = s.getPolygon();
}
}
}
}
public static double dotProduct(double x, double y, double dx, double dy) {
return x * dx + y * dy;
}
// Calculate the projection of a polygon on an axis (ax, ay)
// and returns it as a [min, max] interval
public static double[] ProjectPolygon(double ax, double ay, Polygon p) {
double dotProduct = dotProduct(ax, ay, p.xpoints[0], p.ypoints[0]);
double min = dotProduct;
double max = dotProduct;
for (int i = 0; i < p.npoints; i++) {
dotProduct = dotProduct(p.xpoints[i], p.ypoints[i], ax, ay);
if (dotProduct < min) {
min = dotProduct;
} else if (dotProduct > max) {
max = dotProduct;
}
}
return new double[] { min, max };
}
// Calculate the distance between [minA, maxA](p1[0], p1[1]) and [minB, maxB](p2[0], p2[1])
// The distance will be negative if the intervals overlap
public static double IntervalDistance(double[] p1, double[] p2) {
if (p1[0] < p2[0]) {
return p2[0] - p1[1];
} else {
return p1[0] - p2[1];
}
}
public static double[] PolygonCollision(CollisionPolygon p1, CollisionPolygon p2){
boolean intersection = true;
int edgeCount1 = p1.npoints;
int edgeCount2 = p2.npoints;
double projectionX = 0;
double projectionY = 0;
double projectionDist = Double.POSITIVE_INFINITY;
//loop through all the edges
for(int edgeIndex = 0; edgeIndex < edgeCount1 + edgeCount2; edgeIndex++){
//find edges
double[] axis;
if(edgeIndex < edgeCount1){
axis = p1.getAxis(edgeIndex);
} else {
axis = p2.getAxis(edgeIndex - edgeCount1);
}
double axisX = axis[0];
double axisY = axis[1];
//System.out.println("edge: " +axisX + ", "+ axisY);
//find the projection of both polygons on current axis
final double[] proj1 = ProjectPolygon(axisX, axisY, p1);
final double[] proj2 = ProjectPolygon(axisX, axisY, p2);
//Check if polygons are intersecting, if not end loop
double id = IntervalDistance(proj1, proj2);
if(id > 0){
intersection = false;
break;
}
//Check if projection would be shorter than previous one
id = Math.abs(id);
if(id < projectionDist){
projectionDist = id;
projectionX = axisX;
projectionY = axisY;
//check if hit from "false" side
double d1x = p1.getCenterX();
double d1y = p1.getCenterY();
double d2x = p2.getCenterX();
double d2y = p2.getCenterY();
double midx = d1x - d2x;
double midy = d1y - d2y;
double dot = dotProduct(midx, midy, projectionX, projectionY);
if(dot < 0){
projectionX = -projectionX;
projectionY = -projectionY;
}
}
}
double[] result = new double[]{0, 0};
if(intersection){
//System.out.println("colliison: " + projectionX +"; "+ projectionY + ", " + projectionDist);
result[0] = projectionX * projectionDist;
result[1] = projectionY * projectionDist;
}
return result;
}
}
Any Ideas?
Tom
I had this bug too , it happens when there are parallel edges on a poly.The easy way to fix this is to project the difference between the polygon centers on the found axis.If the result is negative you would just multiply the axis by -1.
Vector aMidPoint = new Vector();
Vector bMidPoint = new Vector();
for ( Vector v : aVerts) {
aMidPoint = aMidPoint.add(v);
}
for ( Vector v : bVerts) {
bMidPoint = bMidPoint.add(v);
}
aMidPoint = aMidPoint.scalarDivision(aVerts.size());
bMidPoint = bMidPoint.scalarDivision(bVerts.size());
Vector ba = aMidPoint.subtract(bMidPoint);
if (ba.dotProduct(minOverlapVector) < 0) {
minOverlapVector = minOverlapVector.scalarMultiplication(-1);
}

Categories

Resources