redpower/src/main/java/com/eloraam/redpower/core/FractalLib.java

221 lines
6.3 KiB
Java

package com.eloraam.redpower.core;
public class FractalLib {
public static long hash64shift(long key) {
key = ~key + (key << 21);
key ^= key >>> 24;
key = key + (key << 3) + (key << 8);
key ^= key >>> 14;
key = key + (key << 2) + (key << 4);
key ^= key >>> 28;
return key + (key << 31);
}
public static double hashFloat(long key) {
long f = hash64shift(key);
return Double.longBitsToDouble(4607182418800017408L | f & 4503599627370495L) - 1.0;
}
public static double noise1D(long seed, double pos, float lac, int octave) {
double tr = 0.5;
double scale = (double)(1 << octave);
for(int i = 0; i < octave; ++i) {
double p = pos * scale;
long pint = (long)Math.floor(p);
double m1 = hashFloat(seed + pint);
double m2 = hashFloat(seed + pint + 1L);
p -= Math.floor(p);
double v = 0.5 + 0.5 * Math.cos(Math.PI * p);
v = v * m1 + (1.0 - v) * m2;
tr = (double)(1.0F - lac) * tr + (double)lac * v;
scale *= 0.5;
}
return tr;
}
public static double perturbOld(long seed, float pos, float lac, int octave) {
double tr = 0.0;
double mscale = 1.0;
double scale = 1.0;
for(int i = 0; i < octave; ++i) {
long v = (long)Math.floor((double)pos * scale);
long p = hash64shift(seed + v);
double mag = Double.longBitsToDouble(4607182418800017408L | p & 4503599627370495L) - 1.0;
tr += mscale * mag * Math.sin(Math.PI * 2 * (double)pos * scale);
scale *= 2.0;
mscale *= (double)lac;
}
return tr;
}
public static void fillVector(Vector3 v, Vector3 org, Vector3 dest, float pos, long seed) {
double window = 4.0 * Math.sin(Math.PI * (double)pos);
v.x = org.x + (double)(pos * pos) * dest.x + window * perturbOld(seed, pos, 0.7F, 5);
v.y = org.y + (double)pos * dest.y + window * perturbOld(seed + 1L, pos, 0.7F, 5);
v.z = org.z + (double)(pos * pos) * dest.z + window * perturbOld(seed + 2L, pos, 0.7F, 5);
}
public static int mdist(Vector3 a, Vector3 b) {
return (int)(Math.abs(Math.floor(a.x) - Math.floor(b.x)) + Math.abs(Math.floor(a.y) - Math.floor(b.y)) + Math.abs(Math.floor(a.z) - Math.floor(b.z)));
}
public static class BlockRay {
private Vector3 p1;
private Vector3 p2;
private Vector3 dv;
public Vector3 enter;
public Vector3 exit;
public int xp;
public int yp;
public int zp;
public int dir;
public int face;
public BlockRay(Vector3 s, Vector3 d) {
this.p1 = new Vector3(s);
this.p2 = new Vector3(d);
this.dv = new Vector3(d);
this.dv.subtract(s);
this.exit = new Vector3(s);
this.enter = new Vector3();
this.xp = (int)Math.floor(s.x);
this.yp = (int)Math.floor(s.y);
this.zp = (int)Math.floor(s.z);
this.dir = 0;
this.dir |= d.x > s.x ? 4 : 0;
this.dir |= d.y > s.y ? 1 : 0;
this.dir |= d.z > s.z ? 2 : 0;
}
public void set(Vector3 s, Vector3 d) {
this.p1.set(s);
this.p2.set(d);
this.dv.set(d);
this.dv.subtract(s);
this.exit.set(s);
this.xp = (int)Math.floor(s.x);
this.yp = (int)Math.floor(s.y);
this.zp = (int)Math.floor(s.z);
this.dir = 0;
this.dir |= d.x > s.x ? 4 : 0;
this.dir |= d.y > s.y ? 1 : 0;
this.dir |= d.z > s.z ? 2 : 0;
}
boolean step() {
double bp = 1.0;
int sd = -1;
if (this.dv.x != 0.0) {
int x = this.xp;
if ((this.dir & 4) > 0) {
++x;
}
double d = ((double)x - this.p1.x) / this.dv.x;
if (d >= 0.0 && d <= bp) {
bp = d;
sd = (this.dir & 4) > 0 ? 4 : 5;
}
}
if (this.dv.y != 0.0) {
int y = this.yp;
if ((this.dir & 1) > 0) {
++y;
}
double d = ((double)y - this.p1.y) / this.dv.y;
if (d >= 0.0 && d <= bp) {
bp = d;
sd = (this.dir & 1) > 0 ? 0 : 1;
}
}
if (this.dv.z != 0.0) {
int z = this.zp;
if ((this.dir & 2) > 0) {
++z;
}
double d = ((double)z - this.p1.z) / this.dv.z;
if (d >= 0.0 && d <= bp) {
bp = d;
sd = (this.dir & 2) > 0 ? 2 : 3;
}
}
this.face = sd;
switch(sd) {
case 0:
++this.yp;
break;
case 1:
--this.yp;
break;
case 2:
++this.zp;
break;
case 3:
--this.zp;
break;
case 4:
++this.xp;
break;
case 5:
--this.xp;
}
this.enter.set(this.exit);
this.exit.set(this.dv);
this.exit.multiply(bp);
this.exit.add(this.p1);
return bp >= 1.0;
}
}
public static class BlockSnake {
int fep = -1;
FractalLib.BlockRay ray;
Vector3 org;
Vector3 dest;
Vector3 fracs;
Vector3 frace;
long seed;
public BlockSnake(Vector3 o, Vector3 d, long s) {
this.org = new Vector3(o);
this.dest = new Vector3(d);
this.fracs = new Vector3(o);
this.frace = new Vector3();
this.seed = s;
FractalLib.fillVector(this.frace, this.org, this.dest, 0.125F, this.seed);
this.ray = new FractalLib.BlockRay(this.fracs, this.frace);
}
public boolean iterate() {
if (this.fep == -1) {
++this.fep;
return true;
} else if (!this.ray.step()) {
return true;
} else if (this.fep == 8) {
return false;
} else {
this.fracs.set(this.frace);
FractalLib.fillVector(this.frace, this.org, this.dest, (float)this.fep / 8.0F, this.seed);
this.ray.set(this.fracs, this.frace);
++this.fep;
return true;
}
}
public Vector3 get() {
return new Vector3((double)this.ray.xp, (double)this.ray.yp, (double)this.ray.zp);
}
}
}