generated from tilera/1710mod
221 lines
6.3 KiB
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);
|
|
}
|
|
}
|
|
}
|