Created
April 20, 2019 01:36
-
-
Save Andrewcpu/4e38caea9c38b1850c4eab1932847c1c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<project version="4"> | |
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_9" default="true" project-jdk-name="9" project-jdk-type="JavaSDK"> | |
<output url="file://$PROJECT_DIR$/out" /> | |
</component> | |
</project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<project version="4"> | |
<component name="ProjectModuleManager"> | |
<modules> | |
<module fileurl="file://$PROJECT_DIR$/3DRenderingRaw.iml" filepath="$PROJECT_DIR$/3DRenderingRaw.iml" /> | |
</modules> | |
</component> | |
</project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<module type="JAVA_MODULE" version="4"> | |
<component name="NewModuleRootManager" inherit-compiler-output="true"> | |
<exclude-output /> | |
<content url="file://$MODULE_DIR$"> | |
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> | |
</content> | |
<orderEntry type="inheritedJdk" /> | |
<orderEntry type="sourceFolder" forTests="false" /> | |
<orderEntry type="module-library"> | |
<library> | |
<CLASSES> | |
<root url="jar://$APPLICATION_HOME_DIR$/redist/annotations-java8.jar!/" /> | |
</CLASSES> | |
<JAVADOC /> | |
<SOURCES /> | |
</library> | |
</orderEntry> | |
</component> | |
</module> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import javafx.geometry.Point3D; | |
public class Camera { | |
private double x, y, z; | |
private double sideRotation = 0; | |
private double verticalRotation = 0; | |
private double speed = 1; | |
private double fov = 90; | |
public Camera(double x, double y, double z) { | |
this.x = x; | |
this.y = y; | |
this.z = z; | |
} | |
public double getFov() { | |
return fov; | |
} | |
public void setFov(double fov) { | |
this.fov = fov; | |
} | |
public double getX() { | |
return x; | |
} | |
public void setX(double x) { | |
this.x = x; | |
} | |
public double getY() { | |
return y; | |
} | |
public void setY(double y) { | |
this.y = y; | |
} | |
public double getZ() { | |
return z; | |
} | |
public void setZ(double z) { | |
this.z = z; | |
} | |
public double getSideRotation() { | |
return sideRotation; | |
} | |
public void setSideRotation(double sideRotation) { | |
this.sideRotation = sideRotation; | |
sync(); | |
} | |
public void forward(){ | |
this.x += Math.sin(getSideRotation()) * speed; | |
this.y += Math.sin(getVerticalRotation()) * speed; | |
this.z += Math.cos(getSideRotation()) * speed; | |
} | |
public Point3D getForward(){ | |
return new Point3D(Math.sin(getSideRotation()), Math.sin(getVerticalRotation()), Math.cos(getSideRotation())); | |
} | |
public void backwards(){ | |
this.x -= Math.sin(getSideRotation()) * speed; | |
this.z -= Math.cos(getSideRotation()) * speed; | |
} | |
public double getSpeed() { | |
return speed; | |
} | |
public void setSpeed(double speed) { | |
this.speed = speed; | |
} | |
public double getVerticalRotation() { | |
return verticalRotation; | |
} | |
public void setVerticalRotation(double verticalRotation) { | |
this.verticalRotation = verticalRotation; | |
sync(); | |
} | |
public void sync(){ | |
this.verticalRotation = Math.toDegrees(this.verticalRotation); | |
while(verticalRotation > 360) | |
verticalRotation -= 360; | |
while(verticalRotation < 0) | |
verticalRotation += 360; | |
this.sideRotation = Math.toDegrees(this.sideRotation); | |
while(sideRotation > 360) | |
sideRotation -= 360; | |
while(sideRotation < 0) | |
sideRotation += 360; | |
this.verticalRotation = Math.toRadians(this.verticalRotation); | |
this.sideRotation = Math.toRadians(this.sideRotation); | |
} | |
public Point3D getLocation(){ | |
return new Point3D(getX(),getY(),getZ()); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import javafx.geometry.Point3D; | |
import org.jetbrains.annotations.NotNull; | |
public class CoordinateUtilities { | |
public static void printCartesian2D(double[] a){ | |
printCartesian2D(a[0],a[1]); | |
} | |
public static void printCartesian2D(double x, double y){ | |
System.out.println("(" + x + ", " + y + ")"); | |
} | |
public static void printPolar2D(double r, double theta){ | |
System.out.println("R: " + r + ", THETA: " + Math.toDegrees(theta )); | |
} | |
public static void printPolar2D(double[] a){ | |
printPolar2D(a[0],a[1]); | |
} | |
public static int getQuadrant(double x, double y){ | |
if( x < 0 && y > 0) | |
return 2; | |
if(x <0 && y < 0) | |
return 3; | |
if(x > 0 && y < 0) | |
return 4; | |
return 1; | |
} | |
public static double[] to2DPolarCoordinate(double x, double y){ | |
double theta = x == 0 ? Math.PI / 2.0 : Math.atan(y / x); | |
double[] a = new double[]{Math.sqrt(x * x + y * y), theta}; | |
int quad = getQuadrant(x,y); | |
if(quad == 2 || quad == 3) | |
a[1] += Math.toRadians(180); | |
if(quad == 4) | |
a[1] += Math.toRadians(360); | |
return a; | |
} | |
public static double[] to2DCartesianCoordinate(double r, double theta){ | |
return new double[]{r * Math.cos(Math.toRadians(theta)), r * Math.sin(Math.toRadians(theta))}; | |
} | |
public static double toDegree(double outsideDegree){ | |
while (outsideDegree > 360) | |
outsideDegree-=360; | |
while(outsideDegree < 0) | |
outsideDegree+=360; | |
return outsideDegree; | |
} | |
public static double[] to3DSphereicalCoordinates(double x, double y, double z){ | |
double a[] = {0,0,0}; | |
a[0] = Math.sqrt(x * x + y * y + z * z); | |
a[1] = Math.acos(z / a[0]); | |
a[2] = Math.atan(y / z); | |
return a; | |
} | |
public static double[] to3DCartesianCoordinates(double r, double t, double a){ | |
double[] ret = {0,0,0}; | |
ret[0] = r * Math.cos(t) * Math.sin(a); | |
ret[1] = r * Math.sin(t) * Math.sin(a); | |
ret[2] = r * Math.cos(t); | |
return ret; | |
} | |
//vertical and horizontal rotations ARE IN RADIANS IDIOT, DONT MESS IT UP. | |
public static double[] rotateCartesian3DPointAroundOrigin(double x, double y, double z, double vertical, double horizontal){ | |
double[] spherical = to3DSphereicalCoordinates(x,y,z); | |
return to3DCartesianCoordinates(spherical[0], spherical[1] + vertical, spherical[2] + horizontal); | |
} | |
//r value overrides distance from origin, | |
public static double[] rotateCartesian3DPointAroundOrigin(double x, double y, double z, double r, double vertical, double horizontal){ | |
double[] spherical = to3DSphereicalCoordinates(x,y,z); | |
return to3DCartesianCoordinates(r, spherical[1] + vertical, spherical[2] + horizontal); | |
} | |
public static double[] getDistanceToOrigin(Point3D point3D){ | |
return getDistanceToOrigin(new double[]{point3D.getX(),point3D.getY(),point3D.getZ()}); | |
} | |
public static double[] getDistanceToOrigin(double[] coordinates){ | |
return coordinates; | |
} | |
//fov in degrees | |
public double get2DChordLength(double fov, double distance){ | |
double d = distance * Math.sin(Math.toRadians(fov / 2.0)); // chord length, which gives us the distance out at a given point with a radius of pointerDistance | |
return d; | |
} | |
public static double[] map3DTo2DScreen(double x, double y, double z, double planeDistance, double fov){ | |
Point3D point = getPointOnPlane(new Point3D(x,y,z),planeDistance, fov); | |
return new double[]{point.getX(),point.getY()}; | |
} | |
public static Point3D getPointOnPlane(Point3D vectorA, double planeZ, double fov){ | |
Point3D vector = new Point3D(vectorA.getX(),vectorA.getY(),vectorA.getZ()); | |
double mod = planeZ / vector.getZ(); | |
vector = new Point3D(vector.getX() * mod, vector.getY() * mod, planeZ); | |
double dimensions = 500; | |
double d = (getDimensions(fov, planeZ)); | |
//d(x) = dimensions | |
double modifier = dimensions / (d / 2.0); | |
return new Point3D(vector.getX() * modifier,vector.getY() * modifier,planeZ); | |
} | |
public static double getDimensions(double fov, double planeZ){ | |
double length = planeZ * Math.tan(Math.toRadians(fov / 2.0)) * 2; | |
return length; | |
} | |
public static boolean hasLineOfSight(Point3D target){ | |
return false; | |
} | |
public static boolean isVisible(Point3D checkMe, double fov){ | |
if(checkMe.getZ() < 1) return false; | |
double length = checkMe.distance(0,0,0); | |
if(length > 2000) return false; | |
double inverseLength = 1.0 / length; | |
Point3D direction = new Point3D(checkMe.getX() * inverseLength, checkMe.getY() * inverseLength, checkMe.getZ() * inverseLength); | |
Point3D norm2 = new Point3D(0,0,1); | |
double dot = norm2.dotProduct(direction); | |
return dot >= Math.cos(Math.toRadians(fov / 2.0)); | |
} | |
public static Point3D getVectorBetweenPoints(Point3D from, Point3D to){ | |
return new Point3D(to.getX() - from.getX(), to.getY() - from.getY(), to.getZ() - from.getZ()); | |
} | |
public static double[] rotateAroundY3D(Point3D point, double t){ | |
double x = point.getX(); | |
double z = point.getZ(); | |
double nX = x * Math.cos(t) - z * Math.sin(t); | |
double nZ = z * Math.cos(t) + x * Math.sin(t); | |
return new double[]{nX, point.getY(), nZ}; | |
} | |
public static double[] rotateAroundX3D (Point3D point, double theta) { | |
double sinTheta = Math.sin(theta); | |
double cosTheta = Math.cos(theta); | |
double y = point.getY(); | |
double z = point.getZ(); | |
double nY = y * cosTheta - z * sinTheta; | |
double nZ = z * cosTheta + y * sinTheta; | |
return new double[]{point.getX(),nY,nZ}; | |
} | |
public static void main(String[] args) { | |
Point3D a = new Point3D(3.0,3.0,3.0); | |
for(double f = 0; f<360; f++){ | |
double[] cartesian = rotateAroundY3D(a, Math.toRadians(f)); | |
System.out.println(cartesian[0] + ", " + cartesian[1] + ", " + cartesian[2]); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import javafx.geometry.Point3D; | |
public class Cube { | |
private double x, y, z; | |
private double width, height; | |
private Point3D[] nodes = new Point3D[8]; | |
private int[][] faces = new int[12][2]; | |
private Point3D velocity = new Point3D(0,0,0); | |
private boolean hovering = false; | |
private int hoverLevel = 0; | |
private boolean hoverState = false; // false = down | |
public Cube(double x, double y, double z, double width, double height) { | |
this.x = x; | |
this.y = y; | |
this.z = z; | |
this.width = width; | |
this.height = height; | |
updateNodes(); | |
faces[0][0] = 0; | |
faces[0][1] = 1; | |
faces[1][0] = 1; | |
faces[1][1] = 3; | |
faces[2][0] = 3; | |
faces[2][1] = 2; | |
faces[3][0] = 2; | |
faces[3][1] = 0; | |
faces[4][0] = 4; | |
faces[4][1] = 5; | |
faces[5][0] = 5; | |
faces[5][1] = 7; | |
faces[6][0] = 7; | |
faces[6][1] = 6; | |
faces[7][0] = 6; | |
faces[7][1] = 4; | |
faces[8][0] = 0; | |
faces[8][1] = 4; | |
faces[9][0] = 1; | |
faces[9][1] = 5; | |
faces[10][0] = 3; | |
faces[10][1] = 7; | |
faces[11][0] = 2; | |
faces[11][1] = 6; | |
//FACES TELL YOU WHICH NODES CONNECT. DONT MESS THIS UP. | |
} | |
public Point3D getFrontTopLeft(){ | |
return new Point3D(getX(), getY(), getZ()); | |
} | |
public Point3D getFrontTopRight(){ | |
return new Point3D(getX() + getWidth(), getY(), getZ()); | |
} | |
public Point3D getFrontBottomLeft(){ | |
return new Point3D(getX(), getY() + getHeight(), getZ()); | |
} | |
public Point3D getFrontBottomRight(){ | |
return new Point3D(getX() + getWidth(), getY() + getHeight(), getZ()); | |
} | |
public Point3D getBackTopLeft(){ | |
return new Point3D(getX(), getY(), getZ() + getWidth()); | |
} | |
public Point3D getBackTopRight(){ | |
return new Point3D(getX() + getWidth(), getY(), getZ() + getWidth()); | |
} | |
public Point3D getBackBottomLeft(){ | |
return new Point3D(getX(), getY() + getHeight(), getZ() + getWidth()); | |
} | |
public Point3D getBackBottomRight(){ | |
return new Point3D(getX() + getWidth(), getY() + getHeight(), getZ() + getWidth()); | |
} | |
public Point3D getVelocity() { | |
return velocity; | |
} | |
public void setVelocity(Point3D velocity) { | |
this.velocity = velocity; | |
this.gravity = velocity.getY(); | |
} | |
public RenderBlock getRenderBlock(Camera camera){ | |
Point3D[] points = new Point3D[nodes.length]; | |
double[] translation = {camera.getX(),camera.getY(),camera.getZ()}; | |
for(int n = 0; n<nodes.length; n++){ | |
Point3D nodeA = nodes[n]; | |
Point3D node = new Point3D(nodeA.getX() - translation[0], nodeA.getY() - translation[1], nodeA.getZ() - translation[2] ); | |
double[] pointA = CoordinateUtilities.rotateAroundY3D(node, camera.getSideRotation()); | |
double[] point = CoordinateUtilities.rotateAroundX3D(new Point3D(pointA[0], pointA[1], pointA[2]), camera.getVerticalRotation()); | |
points[n] = new Point3D(point[0] , point[1] ,point[2]); | |
} | |
return new RenderBlock(faces,points); | |
} | |
private double gravity = 0; | |
public void toggleHovering(){ | |
hovering = !hovering; | |
} | |
public void tick(){ | |
double steps = 15; | |
for(int i = 0; i<steps; i++){ | |
x += velocity.getX() / steps; | |
y += velocity.getY() / steps; | |
z += velocity.getZ() / steps; | |
updateNodes(); | |
} | |
if(hovering){ | |
//hoverState, false = down, true = up | |
int bound = 10; | |
if(hoverState){ | |
hoverLevel--; | |
y--; | |
} | |
else{ | |
hoverLevel++; | |
y++; | |
} | |
if(Math.abs(hoverLevel) > bound) | |
hoverState = !hoverState; | |
} | |
velocity = new Point3D(velocity.getX() * 0.9, velocity.getY() * 0.9, velocity.getZ() * .9); | |
gravity --; | |
if(gravity > -10) | |
gravity = -10; | |
} | |
public double getX() { | |
return x; | |
} | |
public void setX(double x) { | |
this.x = x; | |
updateNodes(); | |
} | |
public double getY() { | |
return y; | |
} | |
public void setY(double y) { | |
this.y = y; | |
updateNodes(); | |
} | |
public double getZ() { | |
return z; | |
} | |
public void setZ(double z) { | |
this.z = z; | |
updateNodes(); | |
} | |
public void updateNodes(){ | |
nodes[0] = getFrontTopLeft(); | |
nodes[1] = getFrontTopRight(); | |
nodes[2] = getFrontBottomLeft(); | |
nodes[3] = getFrontBottomRight(); | |
nodes[4] = getBackTopLeft(); | |
nodes[5] = getBackTopRight(); | |
nodes[6] = getBackBottomLeft(); | |
nodes[7] = getBackBottomRight(); | |
} | |
public double getWidth() { | |
return width; | |
} | |
public void setWidth(double width) { | |
this.width = width; | |
updateNodes(); | |
} | |
public double getHeight() { | |
return height; | |
} | |
public void setHeight(double height) { | |
this.height = height; | |
updateNodes(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import javax.swing.*; | |
import java.awt.*; | |
import java.awt.event.MouseEvent; | |
import java.awt.event.MouseMotionListener; | |
import java.util.concurrent.Executors; | |
import java.util.concurrent.TimeUnit; | |
public class FOVTest extends JFrame { | |
public static void main(String[] args) { | |
new FOVTest(); | |
} | |
public Canvas canvas = new Canvas(); | |
public FOVTest(){ | |
setBounds(0,0,500,500); | |
add(canvas); | |
canvas.setBounds(getBounds()); | |
setVisible(true); | |
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(()->canvas.repaint(), 20, 20, TimeUnit.MILLISECONDS); | |
} | |
} | |
class Canvas extends JComponent implements MouseMotionListener { | |
public Canvas(){ | |
addMouseMotionListener(this); | |
} | |
private Point point = new Point(0,0); | |
@Override | |
public void mouseDragged(MouseEvent e) { | |
} | |
@Override | |
public void mouseMoved(MouseEvent e) { | |
point = e.getPoint(); | |
} | |
private double rotation = 0; | |
public double getRotation() { | |
return rotation; | |
} | |
public void setRotation(double rotation) { | |
while(rotation > 360) | |
rotation -= 360; | |
while( rotation < 0) | |
rotation += 360; | |
this.rotation = rotation; | |
} | |
public Point getPoint() { | |
return point; | |
} | |
public void setPoint(Point point) { | |
double[] polar = toPolarCoordinate(point.x - 250,point.y - 250); | |
polar[1] -= Math.toRadians(getRotation()); | |
double[] cart = toCartesianCoordinate(polar[0], polar[1]); | |
this.point = new Point((int)cart[0] + 250, (int)-cart[1] + 250); | |
System.out.println(point.toString()); | |
} | |
@Override | |
public void paint(Graphics g){ | |
int offset = 250; | |
double solidFOV = 60; | |
double bottomAvg = (rotation) - solidFOV / 2 ; | |
double topAvg= (rotation) + solidFOV / 2 ; | |
for(int i = 0; i<getWidth(); i++){ | |
for(int j = 0; j<getHeight(); j++){ | |
double[] polar = toPolarCoordinate(i - offset, -j + offset); | |
polar[1] = Math.toDegrees(polar[1]) ; | |
if(isBetween(polar[1],bottomAvg,topAvg, solidFOV)) | |
g.setColor(Color.GREEN); | |
else | |
g.setColor(Color.BLACK); | |
g.fillRect(i,j,1,1); | |
} | |
} | |
double pointerDistance = 100; | |
double[] p1 = (toCartesianCoordinate(pointerDistance, (360 - rotation - solidFOV / 2.0))); // bottom line | |
double[] p2 = (toCartesianCoordinate(pointerDistance, (360 - rotation + solidFOV / 2.0))); //top line | |
double[] p3 = (toCartesianCoordinate(pointerDistance * 2, (360 - rotation))); //mid line | |
double[] p4 = (toCartesianCoordinate(pointerDistance, (360 - Math.toDegrees(toPolarCoordinate(point.x - offset, -point.y + offset)[1])))); | |
double mouseAngle = ( Math.toDegrees(toPolarCoordinate(point.x - offset, -point.y + offset)[1])); | |
g.setColor(Color.RED); | |
g.fillOval((int)p1[0] + offset - 5,(int)p1[1] + offset - 5, 10, 10); | |
g.drawLine((int)p1[0] + offset,(int)p1[1] + offset, offset, offset); | |
g.fillOval((int)p2[0] + offset - 5,(int)p2[1] + offset - 5, 10, 10); | |
g.drawLine((int)p2[0] + offset,(int)p2[1] + offset, offset, offset); | |
g.fillOval((int)p3[0] + offset - 5,(int)p3[1] + offset - 5, 10, 10); | |
g.drawLine((int)p3[0] + offset,(int)p3[1] + offset, offset, offset); | |
g.drawLine((int)p2[0] + offset,(int)p2[1] + offset, (int)p1[0] + offset, (int)p1[1] + offset); | |
g.drawOval((int)p4[0] + offset, (int)p4[1] + offset, 5, 5); | |
//mouse line | |
g.drawLine(offset, offset, (int)p4[0] + offset, (int)p4[1] + offset); | |
//bounding circle | |
g.drawOval((int)(-pointerDistance) + offset, (int)(-pointerDistance) + offset, (int)pointerDistance * 2, (int)pointerDistance * 2); | |
double d = pointerDistance * Math.sin(Math.toRadians(solidFOV / 2.0)); // chord length, which gives us the distance out at a given point with a radius of pointerDistance | |
// double f = pointerDistance - Math.sqrt(pointerDistance * pointerDistance - (d) * (d)); | |
//double dist = pointerDistance - f; // middle of chord is this distance from the center of the circle | |
// double[] chordMiddleLocation = toCartesianCoordinate(dist, 360 - rotation); | |
// g.drawOval((int)chordMiddleLocation[0] + offset, (int)chordMiddleLocation[1] + offset, 5, 5); | |
double a = (d * Math.sqrt(3) / Math.cos(Math.toRadians(-mouseAngle + rotation))); | |
a = (d * Math.sqrt(3) / Math.cos(Math.toRadians(-mouseAngle + rotation))); | |
double[] chordPoint = toCartesianCoordinate(a, mouseAngle); | |
g.drawOval((int)chordPoint[0] + 250, ((int)-chordPoint[1]) + 250, 5, 5); | |
g.setColor(Color.WHITE); | |
g.drawString(bottomAvg + "", 10, 10); | |
g.drawString(topAvg + "", 10, 30); | |
g.drawString(rotation + "", 10, 50); | |
g.drawString((toPolarCoordinate(point.x,-point.y + offset)[1]) + "", 10, 70); | |
g.drawString((d * 2)+ " = Chord length", 10, 90); | |
// g.drawString(f + " = Sagitta", 10, 110); | |
if(this.rotation > 360) | |
this.rotation -= 360; | |
if(this.rotation < 0) | |
this.rotation += 360; | |
// this.rotation += .1; | |
// if(this.rotation > 360) this.rotation -= 360; | |
} | |
public boolean isBetween(double a, double b, double c, double fov){ | |
if(b + fov > 360){ | |
if( a >= b || a <= c - 360) | |
return true; | |
return false; | |
} | |
else{ | |
if( a >= b && a <= c) | |
return true; | |
} | |
if(b < 0){ | |
if(360 + b <= a && a <= 360) | |
return true; | |
} | |
return false; | |
} | |
public void printCartesian(double[] a){ | |
printCartesian(a[0],a[1]); | |
} | |
public void printCartesian(double x, double y){ | |
System.out.println("(" + x + ", " + y + ")"); | |
} | |
public void printPolar(double r, double theta){ | |
System.out.println("R: " + r + ", THETA: " + Math.toDegrees(theta )); | |
} | |
public void printPolar(double[] a){ | |
printPolar(a[0],a[1]); | |
} | |
public int getQuadrant(double x, double y){ | |
if( x < 0 && y > 0) | |
return 2; | |
if(x <0 && y < 0) | |
return 3; | |
if(x > 0 && y < 0) | |
return 4; | |
return 1; | |
} | |
public double[] toPolarCoordinate(double x, double y){ | |
double theta = x == 0 ? Math.PI / 2.0 : Math.atan(y / x); | |
double[] a = new double[]{Math.sqrt(x * x + y * y), theta}; | |
int quad = getQuadrant(x,y); | |
if(quad == 2 || quad == 3) | |
a[1] += Math.toRadians(180); | |
if(quad == 4) | |
a[1] += Math.toRadians(360); | |
return a; | |
} | |
public double[] toCartesianCoordinate(double r, double theta){ | |
return new double[]{r * Math.cos(Math.toRadians(theta)), r * Math.sin(Math.toRadians(theta))}; | |
} | |
public double toDegree(double outsideDegree){ | |
while (outsideDegree > 360) | |
outsideDegree-=360; | |
while(outsideDegree < 0) | |
outsideDegree+=360; | |
return outsideDegree; | |
} | |
public double[] getVectorToPoint(double x, double y, double j, double k){ | |
double [] b = new double[]{(j-x),(k - y)}; | |
double mod = Math.sqrt(b[0] * b[0] + b[1] * b[1]); | |
return new double[]{b[0] / mod, b[1] / mod}; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import javafx.geometry.Point3D; | |
import javax.swing.*; | |
import java.awt.*; | |
import java.awt.event.KeyEvent; | |
import java.awt.event.KeyListener; | |
import java.lang.reflect.Executable; | |
import java.util.concurrent.Executors; | |
import java.util.concurrent.TimeUnit; | |
public class Main extends JFrame { | |
public static void main(String[] args) { | |
new Main(); | |
} | |
public Main(){ | |
MainCanvas canvas = new MainCanvas(); | |
setBounds(0,0,500,500); | |
add(canvas); | |
addKeyListener(canvas); | |
canvas.setBounds(getBounds()); | |
setVisible(true); | |
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(()->{ | |
repaint(); | |
},20,20,TimeUnit.MILLISECONDS); | |
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(()->{ | |
tick(); | |
}, 20, 20, TimeUnit.MILLISECONDS); | |
} | |
public void tick(){ | |
Renderer renderer = Renderer.getInstance(); | |
for(Cube cube : renderer.getCubes()){ | |
cube.tick(); | |
} | |
} | |
} | |
class MainCanvas extends JComponent implements KeyListener { | |
private Camera camera = new Camera(0,0,0); | |
private Renderer renderer = new Renderer(camera); | |
public MainCanvas(){ | |
addKeyListener(this); | |
} | |
@Override | |
public void keyTyped(KeyEvent e) { | |
} | |
@Override | |
public void keyPressed(KeyEvent e) { | |
if(e.getKeyCode() == KeyEvent.VK_RIGHT) | |
d+=2; | |
else if(e.getKeyCode() == KeyEvent.VK_LEFT) | |
d-=2; | |
if(e.getKeyCode() == KeyEvent.VK_O){ | |
Cube cube = new Cube(camera.getX(),camera.getY(),camera.getZ(), 10, 10); | |
cube.setVelocity(camera.getForward().multiply(5)); | |
cube.toggleHovering(); | |
Renderer.getInstance().getCubes().add(cube); | |
} | |
if(e.getKeyCode() == KeyEvent.VK_UP){ | |
camera.setVerticalRotation(camera.getVerticalRotation() + Math.toRadians(1)); | |
} | |
if(e.getKeyCode() == KeyEvent.VK_DOWN){ | |
camera.setVerticalRotation(camera.getVerticalRotation() - Math.toRadians(1)); | |
} | |
if(e.getKeyCode() == KeyEvent.VK_BACK_SPACE){ | |
renderer.getCubes().add(new Cube(camera.getX(),camera.getY(),camera.getZ(),10,10)); | |
} | |
if(e.getKeyCode() == KeyEvent.VK_SPACE){ | |
camera.setY(camera.getY() + 1); | |
} | |
if(e.getKeyCode() == KeyEvent.VK_SHIFT){ | |
camera.setY(camera.getY() + 1); | |
} | |
if(e.getKeyCode() == KeyEvent.VK_A){ | |
camera.setX(camera.getX() - 1); | |
} | |
if(e.getKeyCode() == KeyEvent.VK_D){ | |
camera.setX(camera.getX() + 1); | |
} | |
if(e.getKeyCode() == KeyEvent.VK_W){ | |
camera.forward(); | |
} | |
if(e.getKeyCode() == KeyEvent.VK_S){ | |
camera.backwards(); | |
} | |
if(d > 360) | |
d -= 360; | |
if(d < 0) | |
d += 360; | |
} | |
@Override | |
public void keyReleased(KeyEvent e) { | |
} | |
double d = 0; | |
@Override | |
public void paint(Graphics g){ | |
camera.setSideRotation( Math.toRadians(d)); | |
renderer.updateRenderBlocks(); | |
renderer.render(g); | |
// cast.cast(); | |
//cast.drawCast(g); | |
g.setColor(Color.BLACK); | |
g.drawString(Math.toDegrees(camera.getSideRotation()) + "", 10, 10); | |
g.setColor(Color.WHITE); | |
g.drawString(camera.getX() + ", " + camera.getY() + ", " + camera.getZ(), 20, 20); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* OpenSimplex Noise in Java. | |
* by Kurt Spencer | |
* | |
* v1.1 (October 5, 2014) | |
* - Added 2D and 4D implementations. | |
* - Proper gradient sets for all dimensions, from a | |
* dimensionally-generalizable scheme with an actual | |
* rhyme and reason behind it. | |
* - Removed default permutation array in favor of | |
* default seed. | |
* - Changed seed-based constructor to be independent | |
* of any particular randomization library, so results | |
* will be the same when ported to other languages. | |
*/ | |
public class OpenSimplexNoise { | |
private static final double STRETCH_CONSTANT_2D = -0.211324865405187; //(1/Math.sqrt(2+1)-1)/2; | |
private static final double SQUISH_CONSTANT_2D = 0.366025403784439; //(Math.sqrt(2+1)-1)/2; | |
private static final double STRETCH_CONSTANT_3D = -1.0 / 6; //(1/Math.sqrt(3+1)-1)/3; | |
private static final double SQUISH_CONSTANT_3D = 1.0 / 3; //(Math.sqrt(3+1)-1)/3; | |
private static final double STRETCH_CONSTANT_4D = -0.138196601125011; //(1/Math.sqrt(4+1)-1)/4; | |
private static final double SQUISH_CONSTANT_4D = 0.309016994374947; //(Math.sqrt(4+1)-1)/4; | |
private static final double NORM_CONSTANT_2D = 47; | |
private static final double NORM_CONSTANT_3D = 103; | |
private static final double NORM_CONSTANT_4D = 30; | |
private static final long DEFAULT_SEED = 0; | |
private short[] perm; | |
private short[] permGradIndex3D; | |
public OpenSimplexNoise() { | |
this(DEFAULT_SEED); | |
} | |
public OpenSimplexNoise(short[] perm) { | |
this.perm = perm; | |
permGradIndex3D = new short[256]; | |
for (int i = 0; i < 256; i++) { | |
//Since 3D has 24 gradients, simple bitmask won't work, so precompute modulo array. | |
permGradIndex3D[i] = (short)((perm[i] % (gradients3D.length / 3)) * 3); | |
} | |
} | |
//Initializes the class using a permutation array generated from a 64-bit seed. | |
//Generates a proper permutation (i.e. doesn't merely perform N successive pair swaps on a base array) | |
//Uses a simple 64-bit LCG. | |
public OpenSimplexNoise(long seed) { | |
perm = new short[256]; | |
permGradIndex3D = new short[256]; | |
short[] source = new short[256]; | |
for (short i = 0; i < 256; i++) | |
source[i] = i; | |
seed = seed * 6364136223846793005l + 1442695040888963407l; | |
seed = seed * 6364136223846793005l + 1442695040888963407l; | |
seed = seed * 6364136223846793005l + 1442695040888963407l; | |
for (int i = 255; i >= 0; i--) { | |
seed = seed * 6364136223846793005l + 1442695040888963407l; | |
int r = (int)((seed + 31) % (i + 1)); | |
if (r < 0) | |
r += (i + 1); | |
perm[i] = source[r]; | |
permGradIndex3D[i] = (short)((perm[i] % (gradients3D.length / 3)) * 3); | |
source[r] = source[i]; | |
} | |
} | |
//2D OpenSimplex Noise. | |
public double eval(double x, double y) { | |
//Place input coordinates onto grid. | |
double stretchOffset = (x + y) * STRETCH_CONSTANT_2D; | |
double xs = x + stretchOffset; | |
double ys = y + stretchOffset; | |
//Floor to get grid coordinates of rhombus (stretched square) super-cell origin. | |
int xsb = fastFloor(xs); | |
int ysb = fastFloor(ys); | |
//Skew out to get actual coordinates of rhombus origin. We'll need these later. | |
double squishOffset = (xsb + ysb) * SQUISH_CONSTANT_2D; | |
double xb = xsb + squishOffset; | |
double yb = ysb + squishOffset; | |
//Compute grid coordinates relative to rhombus origin. | |
double xins = xs - xsb; | |
double yins = ys - ysb; | |
//Sum those together to get a value that determines which region we're in. | |
double inSum = xins + yins; | |
//Positions relative to origin point. | |
double dx0 = x - xb; | |
double dy0 = y - yb; | |
//We'll be defining these inside the next block and using them afterwards. | |
double dx_ext, dy_ext; | |
int xsv_ext, ysv_ext; | |
double value = 0; | |
//Contribution (1,0) | |
double dx1 = dx0 - 1 - SQUISH_CONSTANT_2D; | |
double dy1 = dy0 - 0 - SQUISH_CONSTANT_2D; | |
double attn1 = 2 - dx1 * dx1 - dy1 * dy1; | |
if (attn1 > 0) { | |
attn1 *= attn1; | |
value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, dx1, dy1); | |
} | |
//Contribution (0,1) | |
double dx2 = dx0 - 0 - SQUISH_CONSTANT_2D; | |
double dy2 = dy0 - 1 - SQUISH_CONSTANT_2D; | |
double attn2 = 2 - dx2 * dx2 - dy2 * dy2; | |
if (attn2 > 0) { | |
attn2 *= attn2; | |
value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, dx2, dy2); | |
} | |
if (inSum <= 1) { //We're inside the triangle (2-Simplex) at (0,0) | |
double zins = 1 - inSum; | |
if (zins > xins || zins > yins) { //(0,0) is one of the closest two triangular vertices | |
if (xins > yins) { | |
xsv_ext = xsb + 1; | |
ysv_ext = ysb - 1; | |
dx_ext = dx0 - 1; | |
dy_ext = dy0 + 1; | |
} else { | |
xsv_ext = xsb - 1; | |
ysv_ext = ysb + 1; | |
dx_ext = dx0 + 1; | |
dy_ext = dy0 - 1; | |
} | |
} else { //(1,0) and (0,1) are the closest two vertices. | |
xsv_ext = xsb + 1; | |
ysv_ext = ysb + 1; | |
dx_ext = dx0 - 1 - 2 * SQUISH_CONSTANT_2D; | |
dy_ext = dy0 - 1 - 2 * SQUISH_CONSTANT_2D; | |
} | |
} else { //We're inside the triangle (2-Simplex) at (1,1) | |
double zins = 2 - inSum; | |
if (zins < xins || zins < yins) { //(0,0) is one of the closest two triangular vertices | |
if (xins > yins) { | |
xsv_ext = xsb + 2; | |
ysv_ext = ysb + 0; | |
dx_ext = dx0 - 2 - 2 * SQUISH_CONSTANT_2D; | |
dy_ext = dy0 + 0 - 2 * SQUISH_CONSTANT_2D; | |
} else { | |
xsv_ext = xsb + 0; | |
ysv_ext = ysb + 2; | |
dx_ext = dx0 + 0 - 2 * SQUISH_CONSTANT_2D; | |
dy_ext = dy0 - 2 - 2 * SQUISH_CONSTANT_2D; | |
} | |
} else { //(1,0) and (0,1) are the closest two vertices. | |
dx_ext = dx0; | |
dy_ext = dy0; | |
xsv_ext = xsb; | |
ysv_ext = ysb; | |
} | |
xsb += 1; | |
ysb += 1; | |
dx0 = dx0 - 1 - 2 * SQUISH_CONSTANT_2D; | |
dy0 = dy0 - 1 - 2 * SQUISH_CONSTANT_2D; | |
} | |
//Contribution (0,0) or (1,1) | |
double attn0 = 2 - dx0 * dx0 - dy0 * dy0; | |
if (attn0 > 0) { | |
attn0 *= attn0; | |
value += attn0 * attn0 * extrapolate(xsb, ysb, dx0, dy0); | |
} | |
//Extra Vertex | |
double attn_ext = 2 - dx_ext * dx_ext - dy_ext * dy_ext; | |
if (attn_ext > 0) { | |
attn_ext *= attn_ext; | |
value += attn_ext * attn_ext * extrapolate(xsv_ext, ysv_ext, dx_ext, dy_ext); | |
} | |
return value / NORM_CONSTANT_2D; | |
} | |
//3D OpenSimplex Noise. | |
public double eval(double x, double y, double z) { | |
//Place input coordinates on simplectic honeycomb. | |
double stretchOffset = (x + y + z) * STRETCH_CONSTANT_3D; | |
double xs = x + stretchOffset; | |
double ys = y + stretchOffset; | |
double zs = z + stretchOffset; | |
//Floor to get simplectic honeycomb coordinates of rhombohedron (stretched cube) super-cell origin. | |
int xsb = fastFloor(xs); | |
int ysb = fastFloor(ys); | |
int zsb = fastFloor(zs); | |
//Skew out to get actual coordinates of rhombohedron origin. We'll need these later. | |
double squishOffset = (xsb + ysb + zsb) * SQUISH_CONSTANT_3D; | |
double xb = xsb + squishOffset; | |
double yb = ysb + squishOffset; | |
double zb = zsb + squishOffset; | |
//Compute simplectic honeycomb coordinates relative to rhombohedral origin. | |
double xins = xs - xsb; | |
double yins = ys - ysb; | |
double zins = zs - zsb; | |
//Sum those together to get a value that determines which region we're in. | |
double inSum = xins + yins + zins; | |
//Positions relative to origin point. | |
double dx0 = x - xb; | |
double dy0 = y - yb; | |
double dz0 = z - zb; | |
//We'll be defining these inside the next block and using them afterwards. | |
double dx_ext0, dy_ext0, dz_ext0; | |
double dx_ext1, dy_ext1, dz_ext1; | |
int xsv_ext0, ysv_ext0, zsv_ext0; | |
int xsv_ext1, ysv_ext1, zsv_ext1; | |
double value = 0; | |
if (inSum <= 1) { //We're inside the tetrahedron (3-Simplex) at (0,0,0) | |
//Determine which two of (0,0,1), (0,1,0), (1,0,0) are closest. | |
byte aPoint = 0x01; | |
double aScore = xins; | |
byte bPoint = 0x02; | |
double bScore = yins; | |
if (aScore >= bScore && zins > bScore) { | |
bScore = zins; | |
bPoint = 0x04; | |
} else if (aScore < bScore && zins > aScore) { | |
aScore = zins; | |
aPoint = 0x04; | |
} | |
//Now we determine the two lattice points not part of the tetrahedron that may contribute. | |
//This depends on the closest two tetrahedral vertices, including (0,0,0) | |
double wins = 1 - inSum; | |
if (wins > aScore || wins > bScore) { //(0,0,0) is one of the closest two tetrahedral vertices. | |
byte c = (bScore > aScore ? bPoint : aPoint); //Our other closest vertex is the closest out of a and b. | |
if ((c & 0x01) == 0) { | |
xsv_ext0 = xsb - 1; | |
xsv_ext1 = xsb; | |
dx_ext0 = dx0 + 1; | |
dx_ext1 = dx0; | |
} else { | |
xsv_ext0 = xsv_ext1 = xsb + 1; | |
dx_ext0 = dx_ext1 = dx0 - 1; | |
} | |
if ((c & 0x02) == 0) { | |
ysv_ext0 = ysv_ext1 = ysb; | |
dy_ext0 = dy_ext1 = dy0; | |
if ((c & 0x01) == 0) { | |
ysv_ext1 -= 1; | |
dy_ext1 += 1; | |
} else { | |
ysv_ext0 -= 1; | |
dy_ext0 += 1; | |
} | |
} else { | |
ysv_ext0 = ysv_ext1 = ysb + 1; | |
dy_ext0 = dy_ext1 = dy0 - 1; | |
} | |
if ((c & 0x04) == 0) { | |
zsv_ext0 = zsb; | |
zsv_ext1 = zsb - 1; | |
dz_ext0 = dz0; | |
dz_ext1 = dz0 + 1; | |
} else { | |
zsv_ext0 = zsv_ext1 = zsb + 1; | |
dz_ext0 = dz_ext1 = dz0 - 1; | |
} | |
} else { //(0,0,0) is not one of the closest two tetrahedral vertices. | |
byte c = (byte)(aPoint | bPoint); //Our two extra vertices are determined by the closest two. | |
if ((c & 0x01) == 0) { | |
xsv_ext0 = xsb; | |
xsv_ext1 = xsb - 1; | |
dx_ext0 = dx0 - 2 * SQUISH_CONSTANT_3D; | |
dx_ext1 = dx0 + 1 - SQUISH_CONSTANT_3D; | |
} else { | |
xsv_ext0 = xsv_ext1 = xsb + 1; | |
dx_ext0 = dx0 - 1 - 2 * SQUISH_CONSTANT_3D; | |
dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_3D; | |
} | |
if ((c & 0x02) == 0) { | |
ysv_ext0 = ysb; | |
ysv_ext1 = ysb - 1; | |
dy_ext0 = dy0 - 2 * SQUISH_CONSTANT_3D; | |
dy_ext1 = dy0 + 1 - SQUISH_CONSTANT_3D; | |
} else { | |
ysv_ext0 = ysv_ext1 = ysb + 1; | |
dy_ext0 = dy0 - 1 - 2 * SQUISH_CONSTANT_3D; | |
dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_3D; | |
} | |
if ((c & 0x04) == 0) { | |
zsv_ext0 = zsb; | |
zsv_ext1 = zsb - 1; | |
dz_ext0 = dz0 - 2 * SQUISH_CONSTANT_3D; | |
dz_ext1 = dz0 + 1 - SQUISH_CONSTANT_3D; | |
} else { | |
zsv_ext0 = zsv_ext1 = zsb + 1; | |
dz_ext0 = dz0 - 1 - 2 * SQUISH_CONSTANT_3D; | |
dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_3D; | |
} | |
} | |
//Contribution (0,0,0) | |
double attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0; | |
if (attn0 > 0) { | |
attn0 *= attn0; | |
value += attn0 * attn0 * extrapolate(xsb + 0, ysb + 0, zsb + 0, dx0, dy0, dz0); | |
} | |
//Contribution (1,0,0) | |
double dx1 = dx0 - 1 - SQUISH_CONSTANT_3D; | |
double dy1 = dy0 - 0 - SQUISH_CONSTANT_3D; | |
double dz1 = dz0 - 0 - SQUISH_CONSTANT_3D; | |
double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1; | |
if (attn1 > 0) { | |
attn1 *= attn1; | |
value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, dx1, dy1, dz1); | |
} | |
//Contribution (0,1,0) | |
double dx2 = dx0 - 0 - SQUISH_CONSTANT_3D; | |
double dy2 = dy0 - 1 - SQUISH_CONSTANT_3D; | |
double dz2 = dz1; | |
double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2; | |
if (attn2 > 0) { | |
attn2 *= attn2; | |
value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, dx2, dy2, dz2); | |
} | |
//Contribution (0,0,1) | |
double dx3 = dx2; | |
double dy3 = dy1; | |
double dz3 = dz0 - 1 - SQUISH_CONSTANT_3D; | |
double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3; | |
if (attn3 > 0) { | |
attn3 *= attn3; | |
value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, dx3, dy3, dz3); | |
} | |
} else if (inSum >= 2) { //We're inside the tetrahedron (3-Simplex) at (1,1,1) | |
//Determine which two tetrahedral vertices are the closest, out of (1,1,0), (1,0,1), (0,1,1) but not (1,1,1). | |
byte aPoint = 0x06; | |
double aScore = xins; | |
byte bPoint = 0x05; | |
double bScore = yins; | |
if (aScore <= bScore && zins < bScore) { | |
bScore = zins; | |
bPoint = 0x03; | |
} else if (aScore > bScore && zins < aScore) { | |
aScore = zins; | |
aPoint = 0x03; | |
} | |
//Now we determine the two lattice points not part of the tetrahedron that may contribute. | |
//This depends on the closest two tetrahedral vertices, including (1,1,1) | |
double wins = 3 - inSum; | |
if (wins < aScore || wins < bScore) { //(1,1,1) is one of the closest two tetrahedral vertices. | |
byte c = (bScore < aScore ? bPoint : aPoint); //Our other closest vertex is the closest out of a and b. | |
if ((c & 0x01) != 0) { | |
xsv_ext0 = xsb + 2; | |
xsv_ext1 = xsb + 1; | |
dx_ext0 = dx0 - 2 - 3 * SQUISH_CONSTANT_3D; | |
dx_ext1 = dx0 - 1 - 3 * SQUISH_CONSTANT_3D; | |
} else { | |
xsv_ext0 = xsv_ext1 = xsb; | |
dx_ext0 = dx_ext1 = dx0 - 3 * SQUISH_CONSTANT_3D; | |
} | |
if ((c & 0x02) != 0) { | |
ysv_ext0 = ysv_ext1 = ysb + 1; | |
dy_ext0 = dy_ext1 = dy0 - 1 - 3 * SQUISH_CONSTANT_3D; | |
if ((c & 0x01) != 0) { | |
ysv_ext1 += 1; | |
dy_ext1 -= 1; | |
} else { | |
ysv_ext0 += 1; | |
dy_ext0 -= 1; | |
} | |
} else { | |
ysv_ext0 = ysv_ext1 = ysb; | |
dy_ext0 = dy_ext1 = dy0 - 3 * SQUISH_CONSTANT_3D; | |
} | |
if ((c & 0x04) != 0) { | |
zsv_ext0 = zsb + 1; | |
zsv_ext1 = zsb + 2; | |
dz_ext0 = dz0 - 1 - 3 * SQUISH_CONSTANT_3D; | |
dz_ext1 = dz0 - 2 - 3 * SQUISH_CONSTANT_3D; | |
} else { | |
zsv_ext0 = zsv_ext1 = zsb; | |
dz_ext0 = dz_ext1 = dz0 - 3 * SQUISH_CONSTANT_3D; | |
} | |
} else { //(1,1,1) is not one of the closest two tetrahedral vertices. | |
byte c = (byte)(aPoint & bPoint); //Our two extra vertices are determined by the closest two. | |
if ((c & 0x01) != 0) { | |
xsv_ext0 = xsb + 1; | |
xsv_ext1 = xsb + 2; | |
dx_ext0 = dx0 - 1 - SQUISH_CONSTANT_3D; | |
dx_ext1 = dx0 - 2 - 2 * SQUISH_CONSTANT_3D; | |
} else { | |
xsv_ext0 = xsv_ext1 = xsb; | |
dx_ext0 = dx0 - SQUISH_CONSTANT_3D; | |
dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D; | |
} | |
if ((c & 0x02) != 0) { | |
ysv_ext0 = ysb + 1; | |
ysv_ext1 = ysb + 2; | |
dy_ext0 = dy0 - 1 - SQUISH_CONSTANT_3D; | |
dy_ext1 = dy0 - 2 - 2 * SQUISH_CONSTANT_3D; | |
} else { | |
ysv_ext0 = ysv_ext1 = ysb; | |
dy_ext0 = dy0 - SQUISH_CONSTANT_3D; | |
dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D; | |
} | |
if ((c & 0x04) != 0) { | |
zsv_ext0 = zsb + 1; | |
zsv_ext1 = zsb + 2; | |
dz_ext0 = dz0 - 1 - SQUISH_CONSTANT_3D; | |
dz_ext1 = dz0 - 2 - 2 * SQUISH_CONSTANT_3D; | |
} else { | |
zsv_ext0 = zsv_ext1 = zsb; | |
dz_ext0 = dz0 - SQUISH_CONSTANT_3D; | |
dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D; | |
} | |
} | |
//Contribution (1,1,0) | |
double dx3 = dx0 - 1 - 2 * SQUISH_CONSTANT_3D; | |
double dy3 = dy0 - 1 - 2 * SQUISH_CONSTANT_3D; | |
double dz3 = dz0 - 0 - 2 * SQUISH_CONSTANT_3D; | |
double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3; | |
if (attn3 > 0) { | |
attn3 *= attn3; | |
value += attn3 * attn3 * extrapolate(xsb + 1, ysb + 1, zsb + 0, dx3, dy3, dz3); | |
} | |
//Contribution (1,0,1) | |
double dx2 = dx3; | |
double dy2 = dy0 - 0 - 2 * SQUISH_CONSTANT_3D; | |
double dz2 = dz0 - 1 - 2 * SQUISH_CONSTANT_3D; | |
double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2; | |
if (attn2 > 0) { | |
attn2 *= attn2; | |
value += attn2 * attn2 * extrapolate(xsb + 1, ysb + 0, zsb + 1, dx2, dy2, dz2); | |
} | |
//Contribution (0,1,1) | |
double dx1 = dx0 - 0 - 2 * SQUISH_CONSTANT_3D; | |
double dy1 = dy3; | |
double dz1 = dz2; | |
double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1; | |
if (attn1 > 0) { | |
attn1 *= attn1; | |
value += attn1 * attn1 * extrapolate(xsb + 0, ysb + 1, zsb + 1, dx1, dy1, dz1); | |
} | |
//Contribution (1,1,1) | |
dx0 = dx0 - 1 - 3 * SQUISH_CONSTANT_3D; | |
dy0 = dy0 - 1 - 3 * SQUISH_CONSTANT_3D; | |
dz0 = dz0 - 1 - 3 * SQUISH_CONSTANT_3D; | |
double attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0; | |
if (attn0 > 0) { | |
attn0 *= attn0; | |
value += attn0 * attn0 * extrapolate(xsb + 1, ysb + 1, zsb + 1, dx0, dy0, dz0); | |
} | |
} else { //We're inside the octahedron (Rectified 3-Simplex) in between. | |
double aScore; | |
byte aPoint; | |
boolean aIsFurtherSide; | |
double bScore; | |
byte bPoint; | |
boolean bIsFurtherSide; | |
//Decide between point (0,0,1) and (1,1,0) as closest | |
double p1 = xins + yins; | |
if (p1 > 1) { | |
aScore = p1 - 1; | |
aPoint = 0x03; | |
aIsFurtherSide = true; | |
} else { | |
aScore = 1 - p1; | |
aPoint = 0x04; | |
aIsFurtherSide = false; | |
} | |
//Decide between point (0,1,0) and (1,0,1) as closest | |
double p2 = xins + zins; | |
if (p2 > 1) { | |
bScore = p2 - 1; | |
bPoint = 0x05; | |
bIsFurtherSide = true; | |
} else { | |
bScore = 1 - p2; | |
bPoint = 0x02; | |
bIsFurtherSide = false; | |
} | |
//The closest out of the two (1,0,0) and (0,1,1) will replace the furthest out of the two decided above, if closer. | |
double p3 = yins + zins; | |
if (p3 > 1) { | |
double score = p3 - 1; | |
if (aScore <= bScore && aScore < score) { | |
aScore = score; | |
aPoint = 0x06; | |
aIsFurtherSide = true; | |
} else if (aScore > bScore && bScore < score) { | |
bScore = score; | |
bPoint = 0x06; | |
bIsFurtherSide = true; | |
} | |
} else { | |
double score = 1 - p3; | |
if (aScore <= bScore && aScore < score) { | |
aScore = score; | |
aPoint = 0x01; | |
aIsFurtherSide = false; | |
} else if (aScore > bScore && bScore < score) { | |
bScore = score; | |
bPoint = 0x01; | |
bIsFurtherSide = false; | |
} | |
} | |
//Where each of the two closest points are determines how the extra two vertices are calculated. | |
if (aIsFurtherSide == bIsFurtherSide) { | |
if (aIsFurtherSide) { //Both closest points on (1,1,1) side | |
//One of the two extra points is (1,1,1) | |
dx_ext0 = dx0 - 1 - 3 * SQUISH_CONSTANT_3D; | |
dy_ext0 = dy0 - 1 - 3 * SQUISH_CONSTANT_3D; | |
dz_ext0 = dz0 - 1 - 3 * SQUISH_CONSTANT_3D; | |
xsv_ext0 = xsb + 1; | |
ysv_ext0 = ysb + 1; | |
zsv_ext0 = zsb + 1; | |
//Other extra point is based on the shared axis. | |
byte c = (byte)(aPoint & bPoint); | |
if ((c & 0x01) != 0) { | |
dx_ext1 = dx0 - 2 - 2 * SQUISH_CONSTANT_3D; | |
dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D; | |
dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D; | |
xsv_ext1 = xsb + 2; | |
ysv_ext1 = ysb; | |
zsv_ext1 = zsb; | |
} else if ((c & 0x02) != 0) { | |
dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D; | |
dy_ext1 = dy0 - 2 - 2 * SQUISH_CONSTANT_3D; | |
dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D; | |
xsv_ext1 = xsb; | |
ysv_ext1 = ysb + 2; | |
zsv_ext1 = zsb; | |
} else { | |
dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D; | |
dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D; | |
dz_ext1 = dz0 - 2 - 2 * SQUISH_CONSTANT_3D; | |
xsv_ext1 = xsb; | |
ysv_ext1 = ysb; | |
zsv_ext1 = zsb + 2; | |
} | |
} else {//Both closest points on (0,0,0) side | |
//One of the two extra points is (0,0,0) | |
dx_ext0 = dx0; | |
dy_ext0 = dy0; | |
dz_ext0 = dz0; | |
xsv_ext0 = xsb; | |
ysv_ext0 = ysb; | |
zsv_ext0 = zsb; | |
//Other extra point is based on the omitted axis. | |
byte c = (byte)(aPoint | bPoint); | |
if ((c & 0x01) == 0) { | |
dx_ext1 = dx0 + 1 - SQUISH_CONSTANT_3D; | |
dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_3D; | |
dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_3D; | |
xsv_ext1 = xsb - 1; | |
ysv_ext1 = ysb + 1; | |
zsv_ext1 = zsb + 1; | |
} else if ((c & 0x02) == 0) { | |
dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_3D; | |
dy_ext1 = dy0 + 1 - SQUISH_CONSTANT_3D; | |
dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_3D; | |
xsv_ext1 = xsb + 1; | |
ysv_ext1 = ysb - 1; | |
zsv_ext1 = zsb + 1; | |
} else { | |
dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_3D; | |
dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_3D; | |
dz_ext1 = dz0 + 1 - SQUISH_CONSTANT_3D; | |
xsv_ext1 = xsb + 1; | |
ysv_ext1 = ysb + 1; | |
zsv_ext1 = zsb - 1; | |
} | |
} | |
} else { //One point on (0,0,0) side, one point on (1,1,1) side | |
byte c1, c2; | |
if (aIsFurtherSide) { | |
c1 = aPoint; | |
c2 = bPoint; | |
} else { | |
c1 = bPoint; | |
c2 = aPoint; | |
} | |
//One contribution is a permutation of (1,1,-1) | |
if ((c1 & 0x01) == 0) { | |
dx_ext0 = dx0 + 1 - SQUISH_CONSTANT_3D; | |
dy_ext0 = dy0 - 1 - SQUISH_CONSTANT_3D; | |
dz_ext0 = dz0 - 1 - SQUISH_CONSTANT_3D; | |
xsv_ext0 = xsb - 1; | |
ysv_ext0 = ysb + 1; | |
zsv_ext0 = zsb + 1; | |
} else if ((c1 & 0x02) == 0) { | |
dx_ext0 = dx0 - 1 - SQUISH_CONSTANT_3D; | |
dy_ext0 = dy0 + 1 - SQUISH_CONSTANT_3D; | |
dz_ext0 = dz0 - 1 - SQUISH_CONSTANT_3D; | |
xsv_ext0 = xsb + 1; | |
ysv_ext0 = ysb - 1; | |
zsv_ext0 = zsb + 1; | |
} else { | |
dx_ext0 = dx0 - 1 - SQUISH_CONSTANT_3D; | |
dy_ext0 = dy0 - 1 - SQUISH_CONSTANT_3D; | |
dz_ext0 = dz0 + 1 - SQUISH_CONSTANT_3D; | |
xsv_ext0 = xsb + 1; | |
ysv_ext0 = ysb + 1; | |
zsv_ext0 = zsb - 1; | |
} | |
//One contribution is a permutation of (0,0,2) | |
dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D; | |
dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D; | |
dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D; | |
xsv_ext1 = xsb; | |
ysv_ext1 = ysb; | |
zsv_ext1 = zsb; | |
if ((c2 & 0x01) != 0) { | |
dx_ext1 -= 2; | |
xsv_ext1 += 2; | |
} else if ((c2 & 0x02) != 0) { | |
dy_ext1 -= 2; | |
ysv_ext1 += 2; | |
} else { | |
dz_ext1 -= 2; | |
zsv_ext1 += 2; | |
} | |
} | |
//Contribution (1,0,0) | |
double dx1 = dx0 - 1 - SQUISH_CONSTANT_3D; | |
double dy1 = dy0 - 0 - SQUISH_CONSTANT_3D; | |
double dz1 = dz0 - 0 - SQUISH_CONSTANT_3D; | |
double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1; | |
if (attn1 > 0) { | |
attn1 *= attn1; | |
value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, dx1, dy1, dz1); | |
} | |
//Contribution (0,1,0) | |
double dx2 = dx0 - 0 - SQUISH_CONSTANT_3D; | |
double dy2 = dy0 - 1 - SQUISH_CONSTANT_3D; | |
double dz2 = dz1; | |
double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2; | |
if (attn2 > 0) { | |
attn2 *= attn2; | |
value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, dx2, dy2, dz2); | |
} | |
//Contribution (0,0,1) | |
double dx3 = dx2; | |
double dy3 = dy1; | |
double dz3 = dz0 - 1 - SQUISH_CONSTANT_3D; | |
double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3; | |
if (attn3 > 0) { | |
attn3 *= attn3; | |
value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, dx3, dy3, dz3); | |
} | |
//Contribution (1,1,0) | |
double dx4 = dx0 - 1 - 2 * SQUISH_CONSTANT_3D; | |
double dy4 = dy0 - 1 - 2 * SQUISH_CONSTANT_3D; | |
double dz4 = dz0 - 0 - 2 * SQUISH_CONSTANT_3D; | |
double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4; | |
if (attn4 > 0) { | |
attn4 *= attn4; | |
value += attn4 * attn4 * extrapolate(xsb + 1, ysb + 1, zsb + 0, dx4, dy4, dz4); | |
} | |
//Contribution (1,0,1) | |
double dx5 = dx4; | |
double dy5 = dy0 - 0 - 2 * SQUISH_CONSTANT_3D; | |
double dz5 = dz0 - 1 - 2 * SQUISH_CONSTANT_3D; | |
double attn5 = 2 - dx5 * dx5 - dy5 * dy5 - dz5 * dz5; | |
if (attn5 > 0) { | |
attn5 *= attn5; | |
value += attn5 * attn5 * extrapolate(xsb + 1, ysb + 0, zsb + 1, dx5, dy5, dz5); | |
} | |
//Contribution (0,1,1) | |
double dx6 = dx0 - 0 - 2 * SQUISH_CONSTANT_3D; | |
double dy6 = dy4; | |
double dz6 = dz5; | |
double attn6 = 2 - dx6 * dx6 - dy6 * dy6 - dz6 * dz6; | |
if (attn6 > 0) { | |
attn6 *= attn6; | |
value += attn6 * attn6 * extrapolate(xsb + 0, ysb + 1, zsb + 1, dx6, dy6, dz6); | |
} | |
} | |
//First extra vertex | |
double attn_ext0 = 2 - dx_ext0 * dx_ext0 - dy_ext0 * dy_ext0 - dz_ext0 * dz_ext0; | |
if (attn_ext0 > 0) | |
{ | |
attn_ext0 *= attn_ext0; | |
value += attn_ext0 * attn_ext0 * extrapolate(xsv_ext0, ysv_ext0, zsv_ext0, dx_ext0, dy_ext0, dz_ext0); | |
} | |
//Second extra vertex | |
double attn_ext1 = 2 - dx_ext1 * dx_ext1 - dy_ext1 * dy_ext1 - dz_ext1 * dz_ext1; | |
if (attn_ext1 > 0) | |
{ | |
attn_ext1 *= attn_ext1; | |
value += attn_ext1 * attn_ext1 * extrapolate(xsv_ext1, ysv_ext1, zsv_ext1, dx_ext1, dy_ext1, dz_ext1); | |
} | |
return value / NORM_CONSTANT_3D; | |
} | |
//4D OpenSimplex Noise. | |
public double eval(double x, double y, double z, double w) { | |
//Place input coordinates on simplectic honeycomb. | |
double stretchOffset = (x + y + z + w) * STRETCH_CONSTANT_4D; | |
double xs = x + stretchOffset; | |
double ys = y + stretchOffset; | |
double zs = z + stretchOffset; | |
double ws = w + stretchOffset; | |
//Floor to get simplectic honeycomb coordinates of rhombo-hypercube super-cell origin. | |
int xsb = fastFloor(xs); | |
int ysb = fastFloor(ys); | |
int zsb = fastFloor(zs); | |
int wsb = fastFloor(ws); | |
//Skew out to get actual coordinates of stretched rhombo-hypercube origin. We'll need these later. | |
double squishOffset = (xsb + ysb + zsb + wsb) * SQUISH_CONSTANT_4D; | |
double xb = xsb + squishOffset; | |
double yb = ysb + squishOffset; | |
double zb = zsb + squishOffset; | |
double wb = wsb + squishOffset; | |
//Compute simplectic honeycomb coordinates relative to rhombo-hypercube origin. | |
double xins = xs - xsb; | |
double yins = ys - ysb; | |
double zins = zs - zsb; | |
double wins = ws - wsb; | |
//Sum those together to get a value that determines which region we're in. | |
double inSum = xins + yins + zins + wins; | |
//Positions relative to origin point. | |
double dx0 = x - xb; | |
double dy0 = y - yb; | |
double dz0 = z - zb; | |
double dw0 = w - wb; | |
//We'll be defining these inside the next block and using them afterwards. | |
double dx_ext0, dy_ext0, dz_ext0, dw_ext0; | |
double dx_ext1, dy_ext1, dz_ext1, dw_ext1; | |
double dx_ext2, dy_ext2, dz_ext2, dw_ext2; | |
int xsv_ext0, ysv_ext0, zsv_ext0, wsv_ext0; | |
int xsv_ext1, ysv_ext1, zsv_ext1, wsv_ext1; | |
int xsv_ext2, ysv_ext2, zsv_ext2, wsv_ext2; | |
double value = 0; | |
if (inSum <= 1) { //We're inside the pentachoron (4-Simplex) at (0,0,0,0) | |
//Determine which two of (0,0,0,1), (0,0,1,0), (0,1,0,0), (1,0,0,0) are closest. | |
byte aPoint = 0x01; | |
double aScore = xins; | |
byte bPoint = 0x02; | |
double bScore = yins; | |
if (aScore >= bScore && zins > bScore) { | |
bScore = zins; | |
bPoint = 0x04; | |
} else if (aScore < bScore && zins > aScore) { | |
aScore = zins; | |
aPoint = 0x04; | |
} | |
if (aScore >= bScore && wins > bScore) { | |
bScore = wins; | |
bPoint = 0x08; | |
} else if (aScore < bScore && wins > aScore) { | |
aScore = wins; | |
aPoint = 0x08; | |
} | |
//Now we determine the three lattice points not part of the pentachoron that may contribute. | |
//This depends on the closest two pentachoron vertices, including (0,0,0,0) | |
double uins = 1 - inSum; | |
if (uins > aScore || uins > bScore) { //(0,0,0,0) is one of the closest two pentachoron vertices. | |
byte c = (bScore > aScore ? bPoint : aPoint); //Our other closest vertex is the closest out of a and b. | |
if ((c & 0x01) == 0) { | |
xsv_ext0 = xsb - 1; | |
xsv_ext1 = xsv_ext2 = xsb; | |
dx_ext0 = dx0 + 1; | |
dx_ext1 = dx_ext2 = dx0; | |
} else { | |
xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb + 1; | |
dx_ext0 = dx_ext1 = dx_ext2 = dx0 - 1; | |
} | |
if ((c & 0x02) == 0) { | |
ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb; | |
dy_ext0 = dy_ext1 = dy_ext2 = dy0; | |
if ((c & 0x01) == 0x01) { | |
ysv_ext0 -= 1; | |
dy_ext0 += 1; | |
} else { | |
ysv_ext1 -= 1; | |
dy_ext1 += 1; | |
} | |
} else { | |
ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1; | |
dy_ext0 = dy_ext1 = dy_ext2 = dy0 - 1; | |
} | |
if ((c & 0x04) == 0) { | |
zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb; | |
dz_ext0 = dz_ext1 = dz_ext2 = dz0; | |
if ((c & 0x03) != 0) { | |
if ((c & 0x03) == 0x03) { | |
zsv_ext0 -= 1; | |
dz_ext0 += 1; | |
} else { | |
zsv_ext1 -= 1; | |
dz_ext1 += 1; | |
} | |
} else { | |
zsv_ext2 -= 1; | |
dz_ext2 += 1; | |
} | |
} else { | |
zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1; | |
dz_ext0 = dz_ext1 = dz_ext2 = dz0 - 1; | |
} | |
if ((c & 0x08) == 0) { | |
wsv_ext0 = wsv_ext1 = wsb; | |
wsv_ext2 = wsb - 1; | |
dw_ext0 = dw_ext1 = dw0; | |
dw_ext2 = dw0 + 1; | |
} else { | |
wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb + 1; | |
dw_ext0 = dw_ext1 = dw_ext2 = dw0 - 1; | |
} | |
} else { //(0,0,0,0) is not one of the closest two pentachoron vertices. | |
byte c = (byte)(aPoint | bPoint); //Our three extra vertices are determined by the closest two. | |
if ((c & 0x01) == 0) { | |
xsv_ext0 = xsv_ext2 = xsb; | |
xsv_ext1 = xsb - 1; | |
dx_ext0 = dx0 - 2 * SQUISH_CONSTANT_4D; | |
dx_ext1 = dx0 + 1 - SQUISH_CONSTANT_4D; | |
dx_ext2 = dx0 - SQUISH_CONSTANT_4D; | |
} else { | |
xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb + 1; | |
dx_ext0 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
dx_ext1 = dx_ext2 = dx0 - 1 - SQUISH_CONSTANT_4D; | |
} | |
if ((c & 0x02) == 0) { | |
ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb; | |
dy_ext0 = dy0 - 2 * SQUISH_CONSTANT_4D; | |
dy_ext1 = dy_ext2 = dy0 - SQUISH_CONSTANT_4D; | |
if ((c & 0x01) == 0x01) { | |
ysv_ext1 -= 1; | |
dy_ext1 += 1; | |
} else { | |
ysv_ext2 -= 1; | |
dy_ext2 += 1; | |
} | |
} else { | |
ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1; | |
dy_ext0 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
dy_ext1 = dy_ext2 = dy0 - 1 - SQUISH_CONSTANT_4D; | |
} | |
if ((c & 0x04) == 0) { | |
zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb; | |
dz_ext0 = dz0 - 2 * SQUISH_CONSTANT_4D; | |
dz_ext1 = dz_ext2 = dz0 - SQUISH_CONSTANT_4D; | |
if ((c & 0x03) == 0x03) { | |
zsv_ext1 -= 1; | |
dz_ext1 += 1; | |
} else { | |
zsv_ext2 -= 1; | |
dz_ext2 += 1; | |
} | |
} else { | |
zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1; | |
dz_ext0 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
dz_ext1 = dz_ext2 = dz0 - 1 - SQUISH_CONSTANT_4D; | |
} | |
if ((c & 0x08) == 0) { | |
wsv_ext0 = wsv_ext1 = wsb; | |
wsv_ext2 = wsb - 1; | |
dw_ext0 = dw0 - 2 * SQUISH_CONSTANT_4D; | |
dw_ext1 = dw0 - SQUISH_CONSTANT_4D; | |
dw_ext2 = dw0 + 1 - SQUISH_CONSTANT_4D; | |
} else { | |
wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb + 1; | |
dw_ext0 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
dw_ext1 = dw_ext2 = dw0 - 1 - SQUISH_CONSTANT_4D; | |
} | |
} | |
//Contribution (0,0,0,0) | |
double attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0 - dw0 * dw0; | |
if (attn0 > 0) { | |
attn0 *= attn0; | |
value += attn0 * attn0 * extrapolate(xsb + 0, ysb + 0, zsb + 0, wsb + 0, dx0, dy0, dz0, dw0); | |
} | |
//Contribution (1,0,0,0) | |
double dx1 = dx0 - 1 - SQUISH_CONSTANT_4D; | |
double dy1 = dy0 - 0 - SQUISH_CONSTANT_4D; | |
double dz1 = dz0 - 0 - SQUISH_CONSTANT_4D; | |
double dw1 = dw0 - 0 - SQUISH_CONSTANT_4D; | |
double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1; | |
if (attn1 > 0) { | |
attn1 *= attn1; | |
value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 0, dx1, dy1, dz1, dw1); | |
} | |
//Contribution (0,1,0,0) | |
double dx2 = dx0 - 0 - SQUISH_CONSTANT_4D; | |
double dy2 = dy0 - 1 - SQUISH_CONSTANT_4D; | |
double dz2 = dz1; | |
double dw2 = dw1; | |
double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2; | |
if (attn2 > 0) { | |
attn2 *= attn2; | |
value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 0, dx2, dy2, dz2, dw2); | |
} | |
//Contribution (0,0,1,0) | |
double dx3 = dx2; | |
double dy3 = dy1; | |
double dz3 = dz0 - 1 - SQUISH_CONSTANT_4D; | |
double dw3 = dw1; | |
double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3; | |
if (attn3 > 0) { | |
attn3 *= attn3; | |
value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 0, dx3, dy3, dz3, dw3); | |
} | |
//Contribution (0,0,0,1) | |
double dx4 = dx2; | |
double dy4 = dy1; | |
double dz4 = dz1; | |
double dw4 = dw0 - 1 - SQUISH_CONSTANT_4D; | |
double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4; | |
if (attn4 > 0) { | |
attn4 *= attn4; | |
value += attn4 * attn4 * extrapolate(xsb + 0, ysb + 0, zsb + 0, wsb + 1, dx4, dy4, dz4, dw4); | |
} | |
} else if (inSum >= 3) { //We're inside the pentachoron (4-Simplex) at (1,1,1,1) | |
//Determine which two of (1,1,1,0), (1,1,0,1), (1,0,1,1), (0,1,1,1) are closest. | |
byte aPoint = 0x0E; | |
double aScore = xins; | |
byte bPoint = 0x0D; | |
double bScore = yins; | |
if (aScore <= bScore && zins < bScore) { | |
bScore = zins; | |
bPoint = 0x0B; | |
} else if (aScore > bScore && zins < aScore) { | |
aScore = zins; | |
aPoint = 0x0B; | |
} | |
if (aScore <= bScore && wins < bScore) { | |
bScore = wins; | |
bPoint = 0x07; | |
} else if (aScore > bScore && wins < aScore) { | |
aScore = wins; | |
aPoint = 0x07; | |
} | |
//Now we determine the three lattice points not part of the pentachoron that may contribute. | |
//This depends on the closest two pentachoron vertices, including (0,0,0,0) | |
double uins = 4 - inSum; | |
if (uins < aScore || uins < bScore) { //(1,1,1,1) is one of the closest two pentachoron vertices. | |
byte c = (bScore < aScore ? bPoint : aPoint); //Our other closest vertex is the closest out of a and b. | |
if ((c & 0x01) != 0) { | |
xsv_ext0 = xsb + 2; | |
xsv_ext1 = xsv_ext2 = xsb + 1; | |
dx_ext0 = dx0 - 2 - 4 * SQUISH_CONSTANT_4D; | |
dx_ext1 = dx_ext2 = dx0 - 1 - 4 * SQUISH_CONSTANT_4D; | |
} else { | |
xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb; | |
dx_ext0 = dx_ext1 = dx_ext2 = dx0 - 4 * SQUISH_CONSTANT_4D; | |
} | |
if ((c & 0x02) != 0) { | |
ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1; | |
dy_ext0 = dy_ext1 = dy_ext2 = dy0 - 1 - 4 * SQUISH_CONSTANT_4D; | |
if ((c & 0x01) != 0) { | |
ysv_ext1 += 1; | |
dy_ext1 -= 1; | |
} else { | |
ysv_ext0 += 1; | |
dy_ext0 -= 1; | |
} | |
} else { | |
ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb; | |
dy_ext0 = dy_ext1 = dy_ext2 = dy0 - 4 * SQUISH_CONSTANT_4D; | |
} | |
if ((c & 0x04) != 0) { | |
zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1; | |
dz_ext0 = dz_ext1 = dz_ext2 = dz0 - 1 - 4 * SQUISH_CONSTANT_4D; | |
if ((c & 0x03) != 0x03) { | |
if ((c & 0x03) == 0) { | |
zsv_ext0 += 1; | |
dz_ext0 -= 1; | |
} else { | |
zsv_ext1 += 1; | |
dz_ext1 -= 1; | |
} | |
} else { | |
zsv_ext2 += 1; | |
dz_ext2 -= 1; | |
} | |
} else { | |
zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb; | |
dz_ext0 = dz_ext1 = dz_ext2 = dz0 - 4 * SQUISH_CONSTANT_4D; | |
} | |
if ((c & 0x08) != 0) { | |
wsv_ext0 = wsv_ext1 = wsb + 1; | |
wsv_ext2 = wsb + 2; | |
dw_ext0 = dw_ext1 = dw0 - 1 - 4 * SQUISH_CONSTANT_4D; | |
dw_ext2 = dw0 - 2 - 4 * SQUISH_CONSTANT_4D; | |
} else { | |
wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb; | |
dw_ext0 = dw_ext1 = dw_ext2 = dw0 - 4 * SQUISH_CONSTANT_4D; | |
} | |
} else { //(1,1,1,1) is not one of the closest two pentachoron vertices. | |
byte c = (byte)(aPoint & bPoint); //Our three extra vertices are determined by the closest two. | |
if ((c & 0x01) != 0) { | |
xsv_ext0 = xsv_ext2 = xsb + 1; | |
xsv_ext1 = xsb + 2; | |
dx_ext0 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
dx_ext1 = dx0 - 2 - 3 * SQUISH_CONSTANT_4D; | |
dx_ext2 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; | |
} else { | |
xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb; | |
dx_ext0 = dx0 - 2 * SQUISH_CONSTANT_4D; | |
dx_ext1 = dx_ext2 = dx0 - 3 * SQUISH_CONSTANT_4D; | |
} | |
if ((c & 0x02) != 0) { | |
ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1; | |
dy_ext0 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
dy_ext1 = dy_ext2 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; | |
if ((c & 0x01) != 0) { | |
ysv_ext2 += 1; | |
dy_ext2 -= 1; | |
} else { | |
ysv_ext1 += 1; | |
dy_ext1 -= 1; | |
} | |
} else { | |
ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb; | |
dy_ext0 = dy0 - 2 * SQUISH_CONSTANT_4D; | |
dy_ext1 = dy_ext2 = dy0 - 3 * SQUISH_CONSTANT_4D; | |
} | |
if ((c & 0x04) != 0) { | |
zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1; | |
dz_ext0 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
dz_ext1 = dz_ext2 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; | |
if ((c & 0x03) != 0) { | |
zsv_ext2 += 1; | |
dz_ext2 -= 1; | |
} else { | |
zsv_ext1 += 1; | |
dz_ext1 -= 1; | |
} | |
} else { | |
zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb; | |
dz_ext0 = dz0 - 2 * SQUISH_CONSTANT_4D; | |
dz_ext1 = dz_ext2 = dz0 - 3 * SQUISH_CONSTANT_4D; | |
} | |
if ((c & 0x08) != 0) { | |
wsv_ext0 = wsv_ext1 = wsb + 1; | |
wsv_ext2 = wsb + 2; | |
dw_ext0 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
dw_ext1 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; | |
dw_ext2 = dw0 - 2 - 3 * SQUISH_CONSTANT_4D; | |
} else { | |
wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb; | |
dw_ext0 = dw0 - 2 * SQUISH_CONSTANT_4D; | |
dw_ext1 = dw_ext2 = dw0 - 3 * SQUISH_CONSTANT_4D; | |
} | |
} | |
//Contribution (1,1,1,0) | |
double dx4 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; | |
double dy4 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; | |
double dz4 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; | |
double dw4 = dw0 - 3 * SQUISH_CONSTANT_4D; | |
double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4; | |
if (attn4 > 0) { | |
attn4 *= attn4; | |
value += attn4 * attn4 * extrapolate(xsb + 1, ysb + 1, zsb + 1, wsb + 0, dx4, dy4, dz4, dw4); | |
} | |
//Contribution (1,1,0,1) | |
double dx3 = dx4; | |
double dy3 = dy4; | |
double dz3 = dz0 - 3 * SQUISH_CONSTANT_4D; | |
double dw3 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; | |
double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3; | |
if (attn3 > 0) { | |
attn3 *= attn3; | |
value += attn3 * attn3 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 1, dx3, dy3, dz3, dw3); | |
} | |
//Contribution (1,0,1,1) | |
double dx2 = dx4; | |
double dy2 = dy0 - 3 * SQUISH_CONSTANT_4D; | |
double dz2 = dz4; | |
double dw2 = dw3; | |
double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2; | |
if (attn2 > 0) { | |
attn2 *= attn2; | |
value += attn2 * attn2 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 1, dx2, dy2, dz2, dw2); | |
} | |
//Contribution (0,1,1,1) | |
double dx1 = dx0 - 3 * SQUISH_CONSTANT_4D; | |
double dz1 = dz4; | |
double dy1 = dy4; | |
double dw1 = dw3; | |
double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1; | |
if (attn1 > 0) { | |
attn1 *= attn1; | |
value += attn1 * attn1 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 1, dx1, dy1, dz1, dw1); | |
} | |
//Contribution (1,1,1,1) | |
dx0 = dx0 - 1 - 4 * SQUISH_CONSTANT_4D; | |
dy0 = dy0 - 1 - 4 * SQUISH_CONSTANT_4D; | |
dz0 = dz0 - 1 - 4 * SQUISH_CONSTANT_4D; | |
dw0 = dw0 - 1 - 4 * SQUISH_CONSTANT_4D; | |
double attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0 - dw0 * dw0; | |
if (attn0 > 0) { | |
attn0 *= attn0; | |
value += attn0 * attn0 * extrapolate(xsb + 1, ysb + 1, zsb + 1, wsb + 1, dx0, dy0, dz0, dw0); | |
} | |
} else if (inSum <= 2) { //We're inside the first dispentachoron (Rectified 4-Simplex) | |
double aScore; | |
byte aPoint; | |
boolean aIsBiggerSide = true; | |
double bScore; | |
byte bPoint; | |
boolean bIsBiggerSide = true; | |
//Decide between (1,1,0,0) and (0,0,1,1) | |
if (xins + yins > zins + wins) { | |
aScore = xins + yins; | |
aPoint = 0x03; | |
} else { | |
aScore = zins + wins; | |
aPoint = 0x0C; | |
} | |
//Decide between (1,0,1,0) and (0,1,0,1) | |
if (xins + zins > yins + wins) { | |
bScore = xins + zins; | |
bPoint = 0x05; | |
} else { | |
bScore = yins + wins; | |
bPoint = 0x0A; | |
} | |
//Closer between (1,0,0,1) and (0,1,1,0) will replace the further of a and b, if closer. | |
if (xins + wins > yins + zins) { | |
double score = xins + wins; | |
if (aScore >= bScore && score > bScore) { | |
bScore = score; | |
bPoint = 0x09; | |
} else if (aScore < bScore && score > aScore) { | |
aScore = score; | |
aPoint = 0x09; | |
} | |
} else { | |
double score = yins + zins; | |
if (aScore >= bScore && score > bScore) { | |
bScore = score; | |
bPoint = 0x06; | |
} else if (aScore < bScore && score > aScore) { | |
aScore = score; | |
aPoint = 0x06; | |
} | |
} | |
//Decide if (1,0,0,0) is closer. | |
double p1 = 2 - inSum + xins; | |
if (aScore >= bScore && p1 > bScore) { | |
bScore = p1; | |
bPoint = 0x01; | |
bIsBiggerSide = false; | |
} else if (aScore < bScore && p1 > aScore) { | |
aScore = p1; | |
aPoint = 0x01; | |
aIsBiggerSide = false; | |
} | |
//Decide if (0,1,0,0) is closer. | |
double p2 = 2 - inSum + yins; | |
if (aScore >= bScore && p2 > bScore) { | |
bScore = p2; | |
bPoint = 0x02; | |
bIsBiggerSide = false; | |
} else if (aScore < bScore && p2 > aScore) { | |
aScore = p2; | |
aPoint = 0x02; | |
aIsBiggerSide = false; | |
} | |
//Decide if (0,0,1,0) is closer. | |
double p3 = 2 - inSum + zins; | |
if (aScore >= bScore && p3 > bScore) { | |
bScore = p3; | |
bPoint = 0x04; | |
bIsBiggerSide = false; | |
} else if (aScore < bScore && p3 > aScore) { | |
aScore = p3; | |
aPoint = 0x04; | |
aIsBiggerSide = false; | |
} | |
//Decide if (0,0,0,1) is closer. | |
double p4 = 2 - inSum + wins; | |
if (aScore >= bScore && p4 > bScore) { | |
bScore = p4; | |
bPoint = 0x08; | |
bIsBiggerSide = false; | |
} else if (aScore < bScore && p4 > aScore) { | |
aScore = p4; | |
aPoint = 0x08; | |
aIsBiggerSide = false; | |
} | |
//Where each of the two closest points are determines how the extra three vertices are calculated. | |
if (aIsBiggerSide == bIsBiggerSide) { | |
if (aIsBiggerSide) { //Both closest points on the bigger side | |
byte c1 = (byte)(aPoint | bPoint); | |
byte c2 = (byte)(aPoint & bPoint); | |
if ((c1 & 0x01) == 0) { | |
xsv_ext0 = xsb; | |
xsv_ext1 = xsb - 1; | |
dx_ext0 = dx0 - 3 * SQUISH_CONSTANT_4D; | |
dx_ext1 = dx0 + 1 - 2 * SQUISH_CONSTANT_4D; | |
} else { | |
xsv_ext0 = xsv_ext1 = xsb + 1; | |
dx_ext0 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; | |
dx_ext1 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
} | |
if ((c1 & 0x02) == 0) { | |
ysv_ext0 = ysb; | |
ysv_ext1 = ysb - 1; | |
dy_ext0 = dy0 - 3 * SQUISH_CONSTANT_4D; | |
dy_ext1 = dy0 + 1 - 2 * SQUISH_CONSTANT_4D; | |
} else { | |
ysv_ext0 = ysv_ext1 = ysb + 1; | |
dy_ext0 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; | |
dy_ext1 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
} | |
if ((c1 & 0x04) == 0) { | |
zsv_ext0 = zsb; | |
zsv_ext1 = zsb - 1; | |
dz_ext0 = dz0 - 3 * SQUISH_CONSTANT_4D; | |
dz_ext1 = dz0 + 1 - 2 * SQUISH_CONSTANT_4D; | |
} else { | |
zsv_ext0 = zsv_ext1 = zsb + 1; | |
dz_ext0 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; | |
dz_ext1 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
} | |
if ((c1 & 0x08) == 0) { | |
wsv_ext0 = wsb; | |
wsv_ext1 = wsb - 1; | |
dw_ext0 = dw0 - 3 * SQUISH_CONSTANT_4D; | |
dw_ext1 = dw0 + 1 - 2 * SQUISH_CONSTANT_4D; | |
} else { | |
wsv_ext0 = wsv_ext1 = wsb + 1; | |
dw_ext0 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; | |
dw_ext1 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
} | |
//One combination is a permutation of (0,0,0,2) based on c2 | |
xsv_ext2 = xsb; | |
ysv_ext2 = ysb; | |
zsv_ext2 = zsb; | |
wsv_ext2 = wsb; | |
dx_ext2 = dx0 - 2 * SQUISH_CONSTANT_4D; | |
dy_ext2 = dy0 - 2 * SQUISH_CONSTANT_4D; | |
dz_ext2 = dz0 - 2 * SQUISH_CONSTANT_4D; | |
dw_ext2 = dw0 - 2 * SQUISH_CONSTANT_4D; | |
if ((c2 & 0x01) != 0) { | |
xsv_ext2 += 2; | |
dx_ext2 -= 2; | |
} else if ((c2 & 0x02) != 0) { | |
ysv_ext2 += 2; | |
dy_ext2 -= 2; | |
} else if ((c2 & 0x04) != 0) { | |
zsv_ext2 += 2; | |
dz_ext2 -= 2; | |
} else { | |
wsv_ext2 += 2; | |
dw_ext2 -= 2; | |
} | |
} else { //Both closest points on the smaller side | |
//One of the two extra points is (0,0,0,0) | |
xsv_ext2 = xsb; | |
ysv_ext2 = ysb; | |
zsv_ext2 = zsb; | |
wsv_ext2 = wsb; | |
dx_ext2 = dx0; | |
dy_ext2 = dy0; | |
dz_ext2 = dz0; | |
dw_ext2 = dw0; | |
//Other two points are based on the omitted axes. | |
byte c = (byte)(aPoint | bPoint); | |
if ((c & 0x01) == 0) { | |
xsv_ext0 = xsb - 1; | |
xsv_ext1 = xsb; | |
dx_ext0 = dx0 + 1 - SQUISH_CONSTANT_4D; | |
dx_ext1 = dx0 - SQUISH_CONSTANT_4D; | |
} else { | |
xsv_ext0 = xsv_ext1 = xsb + 1; | |
dx_ext0 = dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_4D; | |
} | |
if ((c & 0x02) == 0) { | |
ysv_ext0 = ysv_ext1 = ysb; | |
dy_ext0 = dy_ext1 = dy0 - SQUISH_CONSTANT_4D; | |
if ((c & 0x01) == 0x01) | |
{ | |
ysv_ext0 -= 1; | |
dy_ext0 += 1; | |
} else { | |
ysv_ext1 -= 1; | |
dy_ext1 += 1; | |
} | |
} else { | |
ysv_ext0 = ysv_ext1 = ysb + 1; | |
dy_ext0 = dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_4D; | |
} | |
if ((c & 0x04) == 0) { | |
zsv_ext0 = zsv_ext1 = zsb; | |
dz_ext0 = dz_ext1 = dz0 - SQUISH_CONSTANT_4D; | |
if ((c & 0x03) == 0x03) | |
{ | |
zsv_ext0 -= 1; | |
dz_ext0 += 1; | |
} else { | |
zsv_ext1 -= 1; | |
dz_ext1 += 1; | |
} | |
} else { | |
zsv_ext0 = zsv_ext1 = zsb + 1; | |
dz_ext0 = dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_4D; | |
} | |
if ((c & 0x08) == 0) | |
{ | |
wsv_ext0 = wsb; | |
wsv_ext1 = wsb - 1; | |
dw_ext0 = dw0 - SQUISH_CONSTANT_4D; | |
dw_ext1 = dw0 + 1 - SQUISH_CONSTANT_4D; | |
} else { | |
wsv_ext0 = wsv_ext1 = wsb + 1; | |
dw_ext0 = dw_ext1 = dw0 - 1 - SQUISH_CONSTANT_4D; | |
} | |
} | |
} else { //One point on each "side" | |
byte c1, c2; | |
if (aIsBiggerSide) { | |
c1 = aPoint; | |
c2 = bPoint; | |
} else { | |
c1 = bPoint; | |
c2 = aPoint; | |
} | |
//Two contributions are the bigger-sided point with each 0 replaced with -1. | |
if ((c1 & 0x01) == 0) { | |
xsv_ext0 = xsb - 1; | |
xsv_ext1 = xsb; | |
dx_ext0 = dx0 + 1 - SQUISH_CONSTANT_4D; | |
dx_ext1 = dx0 - SQUISH_CONSTANT_4D; | |
} else { | |
xsv_ext0 = xsv_ext1 = xsb + 1; | |
dx_ext0 = dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_4D; | |
} | |
if ((c1 & 0x02) == 0) { | |
ysv_ext0 = ysv_ext1 = ysb; | |
dy_ext0 = dy_ext1 = dy0 - SQUISH_CONSTANT_4D; | |
if ((c1 & 0x01) == 0x01) { | |
ysv_ext0 -= 1; | |
dy_ext0 += 1; | |
} else { | |
ysv_ext1 -= 1; | |
dy_ext1 += 1; | |
} | |
} else { | |
ysv_ext0 = ysv_ext1 = ysb + 1; | |
dy_ext0 = dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_4D; | |
} | |
if ((c1 & 0x04) == 0) { | |
zsv_ext0 = zsv_ext1 = zsb; | |
dz_ext0 = dz_ext1 = dz0 - SQUISH_CONSTANT_4D; | |
if ((c1 & 0x03) == 0x03) { | |
zsv_ext0 -= 1; | |
dz_ext0 += 1; | |
} else { | |
zsv_ext1 -= 1; | |
dz_ext1 += 1; | |
} | |
} else { | |
zsv_ext0 = zsv_ext1 = zsb + 1; | |
dz_ext0 = dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_4D; | |
} | |
if ((c1 & 0x08) == 0) { | |
wsv_ext0 = wsb; | |
wsv_ext1 = wsb - 1; | |
dw_ext0 = dw0 - SQUISH_CONSTANT_4D; | |
dw_ext1 = dw0 + 1 - SQUISH_CONSTANT_4D; | |
} else { | |
wsv_ext0 = wsv_ext1 = wsb + 1; | |
dw_ext0 = dw_ext1 = dw0 - 1 - SQUISH_CONSTANT_4D; | |
} | |
//One contribution is a permutation of (0,0,0,2) based on the smaller-sided point | |
xsv_ext2 = xsb; | |
ysv_ext2 = ysb; | |
zsv_ext2 = zsb; | |
wsv_ext2 = wsb; | |
dx_ext2 = dx0 - 2 * SQUISH_CONSTANT_4D; | |
dy_ext2 = dy0 - 2 * SQUISH_CONSTANT_4D; | |
dz_ext2 = dz0 - 2 * SQUISH_CONSTANT_4D; | |
dw_ext2 = dw0 - 2 * SQUISH_CONSTANT_4D; | |
if ((c2 & 0x01) != 0) { | |
xsv_ext2 += 2; | |
dx_ext2 -= 2; | |
} else if ((c2 & 0x02) != 0) { | |
ysv_ext2 += 2; | |
dy_ext2 -= 2; | |
} else if ((c2 & 0x04) != 0) { | |
zsv_ext2 += 2; | |
dz_ext2 -= 2; | |
} else { | |
wsv_ext2 += 2; | |
dw_ext2 -= 2; | |
} | |
} | |
//Contribution (1,0,0,0) | |
double dx1 = dx0 - 1 - SQUISH_CONSTANT_4D; | |
double dy1 = dy0 - 0 - SQUISH_CONSTANT_4D; | |
double dz1 = dz0 - 0 - SQUISH_CONSTANT_4D; | |
double dw1 = dw0 - 0 - SQUISH_CONSTANT_4D; | |
double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1; | |
if (attn1 > 0) { | |
attn1 *= attn1; | |
value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 0, dx1, dy1, dz1, dw1); | |
} | |
//Contribution (0,1,0,0) | |
double dx2 = dx0 - 0 - SQUISH_CONSTANT_4D; | |
double dy2 = dy0 - 1 - SQUISH_CONSTANT_4D; | |
double dz2 = dz1; | |
double dw2 = dw1; | |
double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2; | |
if (attn2 > 0) { | |
attn2 *= attn2; | |
value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 0, dx2, dy2, dz2, dw2); | |
} | |
//Contribution (0,0,1,0) | |
double dx3 = dx2; | |
double dy3 = dy1; | |
double dz3 = dz0 - 1 - SQUISH_CONSTANT_4D; | |
double dw3 = dw1; | |
double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3; | |
if (attn3 > 0) { | |
attn3 *= attn3; | |
value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 0, dx3, dy3, dz3, dw3); | |
} | |
//Contribution (0,0,0,1) | |
double dx4 = dx2; | |
double dy4 = dy1; | |
double dz4 = dz1; | |
double dw4 = dw0 - 1 - SQUISH_CONSTANT_4D; | |
double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4; | |
if (attn4 > 0) { | |
attn4 *= attn4; | |
value += attn4 * attn4 * extrapolate(xsb + 0, ysb + 0, zsb + 0, wsb + 1, dx4, dy4, dz4, dw4); | |
} | |
//Contribution (1,1,0,0) | |
double dx5 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
double dy5 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
double dz5 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; | |
double dw5 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; | |
double attn5 = 2 - dx5 * dx5 - dy5 * dy5 - dz5 * dz5 - dw5 * dw5; | |
if (attn5 > 0) { | |
attn5 *= attn5; | |
value += attn5 * attn5 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 0, dx5, dy5, dz5, dw5); | |
} | |
//Contribution (1,0,1,0) | |
double dx6 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
double dy6 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; | |
double dz6 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
double dw6 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; | |
double attn6 = 2 - dx6 * dx6 - dy6 * dy6 - dz6 * dz6 - dw6 * dw6; | |
if (attn6 > 0) { | |
attn6 *= attn6; | |
value += attn6 * attn6 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 0, dx6, dy6, dz6, dw6); | |
} | |
//Contribution (1,0,0,1) | |
double dx7 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
double dy7 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; | |
double dz7 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; | |
double dw7 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
double attn7 = 2 - dx7 * dx7 - dy7 * dy7 - dz7 * dz7 - dw7 * dw7; | |
if (attn7 > 0) { | |
attn7 *= attn7; | |
value += attn7 * attn7 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 1, dx7, dy7, dz7, dw7); | |
} | |
//Contribution (0,1,1,0) | |
double dx8 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; | |
double dy8 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
double dz8 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
double dw8 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; | |
double attn8 = 2 - dx8 * dx8 - dy8 * dy8 - dz8 * dz8 - dw8 * dw8; | |
if (attn8 > 0) { | |
attn8 *= attn8; | |
value += attn8 * attn8 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 0, dx8, dy8, dz8, dw8); | |
} | |
//Contribution (0,1,0,1) | |
double dx9 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; | |
double dy9 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
double dz9 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; | |
double dw9 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
double attn9 = 2 - dx9 * dx9 - dy9 * dy9 - dz9 * dz9 - dw9 * dw9; | |
if (attn9 > 0) { | |
attn9 *= attn9; | |
value += attn9 * attn9 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 1, dx9, dy9, dz9, dw9); | |
} | |
//Contribution (0,0,1,1) | |
double dx10 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; | |
double dy10 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; | |
double dz10 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
double dw10 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
double attn10 = 2 - dx10 * dx10 - dy10 * dy10 - dz10 * dz10 - dw10 * dw10; | |
if (attn10 > 0) { | |
attn10 *= attn10; | |
value += attn10 * attn10 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 1, dx10, dy10, dz10, dw10); | |
} | |
} else { //We're inside the second dispentachoron (Rectified 4-Simplex) | |
double aScore; | |
byte aPoint; | |
boolean aIsBiggerSide = true; | |
double bScore; | |
byte bPoint; | |
boolean bIsBiggerSide = true; | |
//Decide between (0,0,1,1) and (1,1,0,0) | |
if (xins + yins < zins + wins) { | |
aScore = xins + yins; | |
aPoint = 0x0C; | |
} else { | |
aScore = zins + wins; | |
aPoint = 0x03; | |
} | |
//Decide between (0,1,0,1) and (1,0,1,0) | |
if (xins + zins < yins + wins) { | |
bScore = xins + zins; | |
bPoint = 0x0A; | |
} else { | |
bScore = yins + wins; | |
bPoint = 0x05; | |
} | |
//Closer between (0,1,1,0) and (1,0,0,1) will replace the further of a and b, if closer. | |
if (xins + wins < yins + zins) { | |
double score = xins + wins; | |
if (aScore <= bScore && score < bScore) { | |
bScore = score; | |
bPoint = 0x06; | |
} else if (aScore > bScore && score < aScore) { | |
aScore = score; | |
aPoint = 0x06; | |
} | |
} else { | |
double score = yins + zins; | |
if (aScore <= bScore && score < bScore) { | |
bScore = score; | |
bPoint = 0x09; | |
} else if (aScore > bScore && score < aScore) { | |
aScore = score; | |
aPoint = 0x09; | |
} | |
} | |
//Decide if (0,1,1,1) is closer. | |
double p1 = 3 - inSum + xins; | |
if (aScore <= bScore && p1 < bScore) { | |
bScore = p1; | |
bPoint = 0x0E; | |
bIsBiggerSide = false; | |
} else if (aScore > bScore && p1 < aScore) { | |
aScore = p1; | |
aPoint = 0x0E; | |
aIsBiggerSide = false; | |
} | |
//Decide if (1,0,1,1) is closer. | |
double p2 = 3 - inSum + yins; | |
if (aScore <= bScore && p2 < bScore) { | |
bScore = p2; | |
bPoint = 0x0D; | |
bIsBiggerSide = false; | |
} else if (aScore > bScore && p2 < aScore) { | |
aScore = p2; | |
aPoint = 0x0D; | |
aIsBiggerSide = false; | |
} | |
//Decide if (1,1,0,1) is closer. | |
double p3 = 3 - inSum + zins; | |
if (aScore <= bScore && p3 < bScore) { | |
bScore = p3; | |
bPoint = 0x0B; | |
bIsBiggerSide = false; | |
} else if (aScore > bScore && p3 < aScore) { | |
aScore = p3; | |
aPoint = 0x0B; | |
aIsBiggerSide = false; | |
} | |
//Decide if (1,1,1,0) is closer. | |
double p4 = 3 - inSum + wins; | |
if (aScore <= bScore && p4 < bScore) { | |
bScore = p4; | |
bPoint = 0x07; | |
bIsBiggerSide = false; | |
} else if (aScore > bScore && p4 < aScore) { | |
aScore = p4; | |
aPoint = 0x07; | |
aIsBiggerSide = false; | |
} | |
//Where each of the two closest points are determines how the extra three vertices are calculated. | |
if (aIsBiggerSide == bIsBiggerSide) { | |
if (aIsBiggerSide) { //Both closest points on the bigger side | |
byte c1 = (byte)(aPoint & bPoint); | |
byte c2 = (byte)(aPoint | bPoint); | |
//Two contributions are permutations of (0,0,0,1) and (0,0,0,2) based on c1 | |
xsv_ext0 = xsv_ext1 = xsb; | |
ysv_ext0 = ysv_ext1 = ysb; | |
zsv_ext0 = zsv_ext1 = zsb; | |
wsv_ext0 = wsv_ext1 = wsb; | |
dx_ext0 = dx0 - SQUISH_CONSTANT_4D; | |
dy_ext0 = dy0 - SQUISH_CONSTANT_4D; | |
dz_ext0 = dz0 - SQUISH_CONSTANT_4D; | |
dw_ext0 = dw0 - SQUISH_CONSTANT_4D; | |
dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_4D; | |
dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_4D; | |
dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_4D; | |
dw_ext1 = dw0 - 2 * SQUISH_CONSTANT_4D; | |
if ((c1 & 0x01) != 0) { | |
xsv_ext0 += 1; | |
dx_ext0 -= 1; | |
xsv_ext1 += 2; | |
dx_ext1 -= 2; | |
} else if ((c1 & 0x02) != 0) { | |
ysv_ext0 += 1; | |
dy_ext0 -= 1; | |
ysv_ext1 += 2; | |
dy_ext1 -= 2; | |
} else if ((c1 & 0x04) != 0) { | |
zsv_ext0 += 1; | |
dz_ext0 -= 1; | |
zsv_ext1 += 2; | |
dz_ext1 -= 2; | |
} else { | |
wsv_ext0 += 1; | |
dw_ext0 -= 1; | |
wsv_ext1 += 2; | |
dw_ext1 -= 2; | |
} | |
//One contribution is a permutation of (1,1,1,-1) based on c2 | |
xsv_ext2 = xsb + 1; | |
ysv_ext2 = ysb + 1; | |
zsv_ext2 = zsb + 1; | |
wsv_ext2 = wsb + 1; | |
dx_ext2 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
dy_ext2 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
dz_ext2 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
dw_ext2 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
if ((c2 & 0x01) == 0) { | |
xsv_ext2 -= 2; | |
dx_ext2 += 2; | |
} else if ((c2 & 0x02) == 0) { | |
ysv_ext2 -= 2; | |
dy_ext2 += 2; | |
} else if ((c2 & 0x04) == 0) { | |
zsv_ext2 -= 2; | |
dz_ext2 += 2; | |
} else { | |
wsv_ext2 -= 2; | |
dw_ext2 += 2; | |
} | |
} else { //Both closest points on the smaller side | |
//One of the two extra points is (1,1,1,1) | |
xsv_ext2 = xsb + 1; | |
ysv_ext2 = ysb + 1; | |
zsv_ext2 = zsb + 1; | |
wsv_ext2 = wsb + 1; | |
dx_ext2 = dx0 - 1 - 4 * SQUISH_CONSTANT_4D; | |
dy_ext2 = dy0 - 1 - 4 * SQUISH_CONSTANT_4D; | |
dz_ext2 = dz0 - 1 - 4 * SQUISH_CONSTANT_4D; | |
dw_ext2 = dw0 - 1 - 4 * SQUISH_CONSTANT_4D; | |
//Other two points are based on the shared axes. | |
byte c = (byte)(aPoint & bPoint); | |
if ((c & 0x01) != 0) { | |
xsv_ext0 = xsb + 2; | |
xsv_ext1 = xsb + 1; | |
dx_ext0 = dx0 - 2 - 3 * SQUISH_CONSTANT_4D; | |
dx_ext1 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; | |
} else { | |
xsv_ext0 = xsv_ext1 = xsb; | |
dx_ext0 = dx_ext1 = dx0 - 3 * SQUISH_CONSTANT_4D; | |
} | |
if ((c & 0x02) != 0) { | |
ysv_ext0 = ysv_ext1 = ysb + 1; | |
dy_ext0 = dy_ext1 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; | |
if ((c & 0x01) == 0) | |
{ | |
ysv_ext0 += 1; | |
dy_ext0 -= 1; | |
} else { | |
ysv_ext1 += 1; | |
dy_ext1 -= 1; | |
} | |
} else { | |
ysv_ext0 = ysv_ext1 = ysb; | |
dy_ext0 = dy_ext1 = dy0 - 3 * SQUISH_CONSTANT_4D; | |
} | |
if ((c & 0x04) != 0) { | |
zsv_ext0 = zsv_ext1 = zsb + 1; | |
dz_ext0 = dz_ext1 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; | |
if ((c & 0x03) == 0) | |
{ | |
zsv_ext0 += 1; | |
dz_ext0 -= 1; | |
} else { | |
zsv_ext1 += 1; | |
dz_ext1 -= 1; | |
} | |
} else { | |
zsv_ext0 = zsv_ext1 = zsb; | |
dz_ext0 = dz_ext1 = dz0 - 3 * SQUISH_CONSTANT_4D; | |
} | |
if ((c & 0x08) != 0) | |
{ | |
wsv_ext0 = wsb + 1; | |
wsv_ext1 = wsb + 2; | |
dw_ext0 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; | |
dw_ext1 = dw0 - 2 - 3 * SQUISH_CONSTANT_4D; | |
} else { | |
wsv_ext0 = wsv_ext1 = wsb; | |
dw_ext0 = dw_ext1 = dw0 - 3 * SQUISH_CONSTANT_4D; | |
} | |
} | |
} else { //One point on each "side" | |
byte c1, c2; | |
if (aIsBiggerSide) { | |
c1 = aPoint; | |
c2 = bPoint; | |
} else { | |
c1 = bPoint; | |
c2 = aPoint; | |
} | |
//Two contributions are the bigger-sided point with each 1 replaced with 2. | |
if ((c1 & 0x01) != 0) { | |
xsv_ext0 = xsb + 2; | |
xsv_ext1 = xsb + 1; | |
dx_ext0 = dx0 - 2 - 3 * SQUISH_CONSTANT_4D; | |
dx_ext1 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; | |
} else { | |
xsv_ext0 = xsv_ext1 = xsb; | |
dx_ext0 = dx_ext1 = dx0 - 3 * SQUISH_CONSTANT_4D; | |
} | |
if ((c1 & 0x02) != 0) { | |
ysv_ext0 = ysv_ext1 = ysb + 1; | |
dy_ext0 = dy_ext1 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; | |
if ((c1 & 0x01) == 0) { | |
ysv_ext0 += 1; | |
dy_ext0 -= 1; | |
} else { | |
ysv_ext1 += 1; | |
dy_ext1 -= 1; | |
} | |
} else { | |
ysv_ext0 = ysv_ext1 = ysb; | |
dy_ext0 = dy_ext1 = dy0 - 3 * SQUISH_CONSTANT_4D; | |
} | |
if ((c1 & 0x04) != 0) { | |
zsv_ext0 = zsv_ext1 = zsb + 1; | |
dz_ext0 = dz_ext1 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; | |
if ((c1 & 0x03) == 0) { | |
zsv_ext0 += 1; | |
dz_ext0 -= 1; | |
} else { | |
zsv_ext1 += 1; | |
dz_ext1 -= 1; | |
} | |
} else { | |
zsv_ext0 = zsv_ext1 = zsb; | |
dz_ext0 = dz_ext1 = dz0 - 3 * SQUISH_CONSTANT_4D; | |
} | |
if ((c1 & 0x08) != 0) { | |
wsv_ext0 = wsb + 1; | |
wsv_ext1 = wsb + 2; | |
dw_ext0 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; | |
dw_ext1 = dw0 - 2 - 3 * SQUISH_CONSTANT_4D; | |
} else { | |
wsv_ext0 = wsv_ext1 = wsb; | |
dw_ext0 = dw_ext1 = dw0 - 3 * SQUISH_CONSTANT_4D; | |
} | |
//One contribution is a permutation of (1,1,1,-1) based on the smaller-sided point | |
xsv_ext2 = xsb + 1; | |
ysv_ext2 = ysb + 1; | |
zsv_ext2 = zsb + 1; | |
wsv_ext2 = wsb + 1; | |
dx_ext2 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
dy_ext2 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
dz_ext2 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
dw_ext2 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
if ((c2 & 0x01) == 0) { | |
xsv_ext2 -= 2; | |
dx_ext2 += 2; | |
} else if ((c2 & 0x02) == 0) { | |
ysv_ext2 -= 2; | |
dy_ext2 += 2; | |
} else if ((c2 & 0x04) == 0) { | |
zsv_ext2 -= 2; | |
dz_ext2 += 2; | |
} else { | |
wsv_ext2 -= 2; | |
dw_ext2 += 2; | |
} | |
} | |
//Contribution (1,1,1,0) | |
double dx4 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; | |
double dy4 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; | |
double dz4 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; | |
double dw4 = dw0 - 3 * SQUISH_CONSTANT_4D; | |
double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4; | |
if (attn4 > 0) { | |
attn4 *= attn4; | |
value += attn4 * attn4 * extrapolate(xsb + 1, ysb + 1, zsb + 1, wsb + 0, dx4, dy4, dz4, dw4); | |
} | |
//Contribution (1,1,0,1) | |
double dx3 = dx4; | |
double dy3 = dy4; | |
double dz3 = dz0 - 3 * SQUISH_CONSTANT_4D; | |
double dw3 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; | |
double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3; | |
if (attn3 > 0) { | |
attn3 *= attn3; | |
value += attn3 * attn3 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 1, dx3, dy3, dz3, dw3); | |
} | |
//Contribution (1,0,1,1) | |
double dx2 = dx4; | |
double dy2 = dy0 - 3 * SQUISH_CONSTANT_4D; | |
double dz2 = dz4; | |
double dw2 = dw3; | |
double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2; | |
if (attn2 > 0) { | |
attn2 *= attn2; | |
value += attn2 * attn2 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 1, dx2, dy2, dz2, dw2); | |
} | |
//Contribution (0,1,1,1) | |
double dx1 = dx0 - 3 * SQUISH_CONSTANT_4D; | |
double dz1 = dz4; | |
double dy1 = dy4; | |
double dw1 = dw3; | |
double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1; | |
if (attn1 > 0) { | |
attn1 *= attn1; | |
value += attn1 * attn1 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 1, dx1, dy1, dz1, dw1); | |
} | |
//Contribution (1,1,0,0) | |
double dx5 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
double dy5 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
double dz5 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; | |
double dw5 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; | |
double attn5 = 2 - dx5 * dx5 - dy5 * dy5 - dz5 * dz5 - dw5 * dw5; | |
if (attn5 > 0) { | |
attn5 *= attn5; | |
value += attn5 * attn5 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 0, dx5, dy5, dz5, dw5); | |
} | |
//Contribution (1,0,1,0) | |
double dx6 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
double dy6 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; | |
double dz6 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
double dw6 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; | |
double attn6 = 2 - dx6 * dx6 - dy6 * dy6 - dz6 * dz6 - dw6 * dw6; | |
if (attn6 > 0) { | |
attn6 *= attn6; | |
value += attn6 * attn6 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 0, dx6, dy6, dz6, dw6); | |
} | |
//Contribution (1,0,0,1) | |
double dx7 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
double dy7 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; | |
double dz7 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; | |
double dw7 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
double attn7 = 2 - dx7 * dx7 - dy7 * dy7 - dz7 * dz7 - dw7 * dw7; | |
if (attn7 > 0) { | |
attn7 *= attn7; | |
value += attn7 * attn7 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 1, dx7, dy7, dz7, dw7); | |
} | |
//Contribution (0,1,1,0) | |
double dx8 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; | |
double dy8 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
double dz8 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
double dw8 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; | |
double attn8 = 2 - dx8 * dx8 - dy8 * dy8 - dz8 * dz8 - dw8 * dw8; | |
if (attn8 > 0) { | |
attn8 *= attn8; | |
value += attn8 * attn8 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 0, dx8, dy8, dz8, dw8); | |
} | |
//Contribution (0,1,0,1) | |
double dx9 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; | |
double dy9 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
double dz9 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; | |
double dw9 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
double attn9 = 2 - dx9 * dx9 - dy9 * dy9 - dz9 * dz9 - dw9 * dw9; | |
if (attn9 > 0) { | |
attn9 *= attn9; | |
value += attn9 * attn9 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 1, dx9, dy9, dz9, dw9); | |
} | |
//Contribution (0,0,1,1) | |
double dx10 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; | |
double dy10 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; | |
double dz10 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
double dw10 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; | |
double attn10 = 2 - dx10 * dx10 - dy10 * dy10 - dz10 * dz10 - dw10 * dw10; | |
if (attn10 > 0) { | |
attn10 *= attn10; | |
value += attn10 * attn10 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 1, dx10, dy10, dz10, dw10); | |
} | |
} | |
//First extra vertex | |
double attn_ext0 = 2 - dx_ext0 * dx_ext0 - dy_ext0 * dy_ext0 - dz_ext0 * dz_ext0 - dw_ext0 * dw_ext0; | |
if (attn_ext0 > 0) | |
{ | |
attn_ext0 *= attn_ext0; | |
value += attn_ext0 * attn_ext0 * extrapolate(xsv_ext0, ysv_ext0, zsv_ext0, wsv_ext0, dx_ext0, dy_ext0, dz_ext0, dw_ext0); | |
} | |
//Second extra vertex | |
double attn_ext1 = 2 - dx_ext1 * dx_ext1 - dy_ext1 * dy_ext1 - dz_ext1 * dz_ext1 - dw_ext1 * dw_ext1; | |
if (attn_ext1 > 0) | |
{ | |
attn_ext1 *= attn_ext1; | |
value += attn_ext1 * attn_ext1 * extrapolate(xsv_ext1, ysv_ext1, zsv_ext1, wsv_ext1, dx_ext1, dy_ext1, dz_ext1, dw_ext1); | |
} | |
//Third extra vertex | |
double attn_ext2 = 2 - dx_ext2 * dx_ext2 - dy_ext2 * dy_ext2 - dz_ext2 * dz_ext2 - dw_ext2 * dw_ext2; | |
if (attn_ext2 > 0) | |
{ | |
attn_ext2 *= attn_ext2; | |
value += attn_ext2 * attn_ext2 * extrapolate(xsv_ext2, ysv_ext2, zsv_ext2, wsv_ext2, dx_ext2, dy_ext2, dz_ext2, dw_ext2); | |
} | |
return value / NORM_CONSTANT_4D; | |
} | |
private double extrapolate(int xsb, int ysb, double dx, double dy) | |
{ | |
int index = perm[(perm[xsb & 0xFF] + ysb) & 0xFF] & 0x0E; | |
return gradients2D[index] * dx | |
+ gradients2D[index + 1] * dy; | |
} | |
private double extrapolate(int xsb, int ysb, int zsb, double dx, double dy, double dz) | |
{ | |
int index = permGradIndex3D[(perm[(perm[xsb & 0xFF] + ysb) & 0xFF] + zsb) & 0xFF]; | |
return gradients3D[index] * dx | |
+ gradients3D[index + 1] * dy | |
+ gradients3D[index + 2] * dz; | |
} | |
private double extrapolate(int xsb, int ysb, int zsb, int wsb, double dx, double dy, double dz, double dw) | |
{ | |
int index = perm[(perm[(perm[(perm[xsb & 0xFF] + ysb) & 0xFF] + zsb) & 0xFF] + wsb) & 0xFF] & 0xFC; | |
return gradients4D[index] * dx | |
+ gradients4D[index + 1] * dy | |
+ gradients4D[index + 2] * dz | |
+ gradients4D[index + 3] * dw; | |
} | |
private static int fastFloor(double x) { | |
int xi = (int)x; | |
return x < xi ? xi - 1 : xi; | |
} | |
//Gradients for 2D. They approximate the directions to the | |
//vertices of an octagon from the center. | |
private static byte[] gradients2D = new byte[] { | |
5, 2, 2, 5, | |
-5, 2, -2, 5, | |
5, -2, 2, -5, | |
-5, -2, -2, -5, | |
}; | |
//Gradients for 3D. They approximate the directions to the | |
//vertices of a rhombicuboctahedron from the center, skewed so | |
//that the triangular and square facets can be inscribed inside | |
//circles of the same radius. | |
private static byte[] gradients3D = new byte[] { | |
-11, 4, 4, -4, 11, 4, -4, 4, 11, | |
11, 4, 4, 4, 11, 4, 4, 4, 11, | |
-11, -4, 4, -4, -11, 4, -4, -4, 11, | |
11, -4, 4, 4, -11, 4, 4, -4, 11, | |
-11, 4, -4, -4, 11, -4, -4, 4, -11, | |
11, 4, -4, 4, 11, -4, 4, 4, -11, | |
-11, -4, -4, -4, -11, -4, -4, -4, -11, | |
11, -4, -4, 4, -11, -4, 4, -4, -11, | |
}; | |
//Gradients for 4D. They approximate the directions to the | |
//vertices of a disprismatotesseractihexadecachoron from the center, | |
//skewed so that the tetrahedral and cubic facets can be inscribed inside | |
//spheres of the same radius. | |
private static byte[] gradients4D = new byte[] { | |
3, 1, 1, 1, 1, 3, 1, 1, 1, 1, 3, 1, 1, 1, 1, 3, | |
-3, 1, 1, 1, -1, 3, 1, 1, -1, 1, 3, 1, -1, 1, 1, 3, | |
3, -1, 1, 1, 1, -3, 1, 1, 1, -1, 3, 1, 1, -1, 1, 3, | |
-3, -1, 1, 1, -1, -3, 1, 1, -1, -1, 3, 1, -1, -1, 1, 3, | |
3, 1, -1, 1, 1, 3, -1, 1, 1, 1, -3, 1, 1, 1, -1, 3, | |
-3, 1, -1, 1, -1, 3, -1, 1, -1, 1, -3, 1, -1, 1, -1, 3, | |
3, -1, -1, 1, 1, -3, -1, 1, 1, -1, -3, 1, 1, -1, -1, 3, | |
-3, -1, -1, 1, -1, -3, -1, 1, -1, -1, -3, 1, -1, -1, -1, 3, | |
3, 1, 1, -1, 1, 3, 1, -1, 1, 1, 3, -1, 1, 1, 1, -3, | |
-3, 1, 1, -1, -1, 3, 1, -1, -1, 1, 3, -1, -1, 1, 1, -3, | |
3, -1, 1, -1, 1, -3, 1, -1, 1, -1, 3, -1, 1, -1, 1, -3, | |
-3, -1, 1, -1, -1, -3, 1, -1, -1, -1, 3, -1, -1, -1, 1, -3, | |
3, 1, -1, -1, 1, 3, -1, -1, 1, 1, -3, -1, 1, 1, -1, -3, | |
-3, 1, -1, -1, -1, 3, -1, -1, -1, 1, -3, -1, -1, 1, -1, -3, | |
3, -1, -1, -1, 1, -3, -1, -1, 1, -1, -3, -1, 1, -1, -1, -3, | |
-3, -1, -1, -1, -1, -3, -1, -1, -1, -1, -3, -1, -1, -1, -1, -3, | |
}; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import javafx.geometry.Point3D; | |
import java.awt.*; | |
public class RenderBlock { | |
//renderblock holds nodes and face connection data, the data put here has already been rotated according to the camera. | |
private int[][] faces; | |
private Point3D[] nodes; | |
public RenderBlock(int[][] faces, Point3D[] nodes) { | |
this.faces = faces; | |
this.nodes = nodes; | |
} | |
public int[][] getFaces() { | |
return faces; | |
} | |
public void setFaces(int[][] faces) { | |
this.faces = faces; | |
} | |
public Point3D[] getNodes() { | |
return nodes; | |
} | |
public void setNodes(Point3D[] nodes) { | |
this.nodes = nodes; | |
} | |
public boolean isInside(double x, double y, double z){ | |
double minX = nodes[0].getX(); | |
double minY = nodes[0].getY(); | |
double minZ = nodes[0].getZ(); | |
double maxX = nodes[0].getX(); | |
double maxY = nodes[0].getY(); | |
double maxZ = nodes[0].getZ(); | |
for(Point3D p : nodes){ | |
if(p.getX() < minX) | |
minX = p.getX(); | |
if(p.getY() > maxX) | |
maxX = p.getX(); | |
if(p.getY() < minY) | |
minY = p.getY(); | |
if(p.getY() > maxY) | |
maxY = p.getY(); | |
if(p.getZ() < minZ) | |
minZ = p.getZ(); | |
if(p.getZ() > maxZ) | |
maxZ = p.getZ(); | |
} | |
if(minX <= x && maxX >= x){ | |
if(minY <= y && maxY >= y){ | |
if(minZ <= z && maxZ >= z){ | |
return true; | |
} | |
} | |
} | |
return false; | |
// return new Point3D(minX,minY,minZ).distance(x,y,z) <= 20; | |
} | |
public Color getColor(){ | |
return Color.WHITE; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import javafx.geometry.Point3D; | |
import java.awt.*; | |
import java.util.ArrayList; | |
import java.util.List; | |
public class Renderer { | |
private List<Cube> cubes = new ArrayList<>(); | |
private List<RenderBlock> renderingBlocks = new ArrayList<>(); | |
private Camera camera; | |
public Renderer(Camera camera){ | |
this.camera = camera; | |
instance = this; | |
for(int x = -2000; x<=2000; x+=0){ | |
for(int z = -2000; z<=2000; z+=0){ | |
if(Math.random() <= 0.005){ | |
double height = Math.random() * 500; | |
for(int y = 0; y<=(int)height; y++){ | |
double width = 100 / height * (height - y); | |
cubes.add(new Cube(x, y * 10, z, width, 10)); | |
} | |
} | |
cubes.add(new Cube(x,1,z,Math.random() * 25,Math.random() * 100)); | |
z += Math.random() * 100; | |
} | |
x += Math.random() * 200; | |
} | |
// Cube cube = new Cube(1,1,15,10,10); | |
// cubes.add(cube); | |
camera.setSpeed(5); | |
} | |
private static Renderer instance = null; | |
public static Renderer getInstance(){ | |
return instance; | |
} | |
public void updateRenderBlocks(){ | |
renderingBlocks.clear(); | |
for(Cube cube : cubes){ | |
renderingBlocks.add(cube.getRenderBlock(camera)); | |
} | |
} | |
public List<RenderBlock> getRenderingBlocks() { | |
return renderingBlocks; | |
} | |
/* | |
So the way this works is that there is a "screen" at Z=1 and I want to find the point of intersection between that plane at Z = 1 and the vector stemming from the camera to the target point | |
*/ | |
public List<Cube> getCubes() { | |
return cubes; | |
} | |
public void render(Graphics g){ | |
g.setColor(Color.BLACK); | |
for(RenderBlock b : renderingBlocks){ | |
int[][] faces = b.getFaces(); | |
Point3D[] nodes = b.getNodes(); | |
int[] x = new int[faces.length * 2]; | |
int[] y = new int[faces.length * 2]; | |
int index = 0; | |
for(int n = 0; n<faces.length; n++){ | |
int[] edges = faces[n]; | |
Point3D node0 = nodes[edges[0]]; | |
Point3D node1 = nodes[edges[1]]; | |
double focalLength = 1; | |
double x1 = (node0.getX() + camera.getX()) * focalLength * 1 + 250; | |
double x2 = (node1.getX() + camera.getX()) * focalLength * 1 + 250; | |
double y1 = (node0.getY() + camera.getY()) * focalLength * 1 + 250; | |
double y2 = (node1.getY() + camera.getY()) * focalLength * 1 + 250; | |
if(CoordinateUtilities.isVisible(node0, camera.getFov()) || CoordinateUtilities.isVisible(node1, camera.getFov()) ) | |
{ | |
double[] node0Points = CoordinateUtilities.map3DTo2DScreen(node0.getX(),node0.getY(),node0.getZ(), 10, camera.getFov()); | |
double[] node1Points = CoordinateUtilities.map3DTo2DScreen(node1.getX(),node1.getY(),node1.getZ(), 10, camera.getFov()); | |
double f = 3 / 5.0; | |
x1 = node0Points[0] * f + 250 ; | |
y1 = -node0Points[1] * f + 250; | |
x2 = node1Points[0] * f + 250; | |
y2 = -node1Points[1] * f + 250; | |
g.drawLine((int)(x1), (int)(y1), (int)(x2), (int)(y2)); | |
x[index] = (int)x1; | |
x[index + 1] = (int)x2; | |
y[index] = (int)y1; | |
y[index + 1] = (int)y2; | |
index+=2; | |
// g.fillPolygon(new int[]{(int)x1, (int)x2}, new int[]{(int)y1,(int)y2}, 2); | |
} | |
} | |
// g.fillPolygon(x, y, x.length); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment