/*
* Copyright (c) 2015 Chris Newland.
* Licensed under https://github.com/chriswhocodes/demofx/blob/master/LICENSE-BSD
*/
package xplayer.visualizer.model;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import application.tools.InfoTool;
import javafx.scene.image.Image;
/**
* The Class Sprite3D.
*/
public class Sprite3D {
/**
* The Class Point3D.
*/
// Point 3D
class Point3D {
/** The x. */
private double x;
/** The y. */
private double y;
/** The z. */
private double z;
/**
* Instantiates a new point 3 D.
*
* @param x the x
* @param y the y
* @param z the z
*/
public Point3D(double x, double y, double z) {
super();
this.x = x;
this.y = y;
this.z = z;
}
/**
* Gets the x.
*
* @return the x
*/
public double getX() {
return x;
}
/**
* Gets the y.
*
* @return the y
*/
public double getY() {
return y;
}
/**
* Gets the z.
*
* @return the z
*/
public double getZ() {
return z;
}
}
/**
* The Enum Shape3D.
*/
public enum Shape3D {
/** The ring. */
RING,
/** The tube. */
TUBE,
/** The cube. */
CUBE,
/** The sphere. */
SPHERE
}
/** The render list. */
private List<Point3D> renderList;
/** The points. */
private List<Point3D> points;
/** The roll. */
private double roll;
/** The pitch. */
private double pitch;
/** The yaw. */
private double yaw;
/** The roll inc. */
private double rollInc;
/** The pitch inc. */
private double pitchInc;
/** The yaw inc. */
private double yawInc;
/** The x offset. */
private double xOffset;
/** The y offset. */
private double yOffset;
/** The z offset. */
private double zOffset;
/** The zoom. */
private double zoom;
/** The background. */
//private Image background;
/** The image ball. */
private Image imageBall;
/** The z comparator. */
private Comparator<Point3D> zComparator = (p1 , p2) -> Double.compare(p2.z, p1.z);
private VisualizerDrawer visualizerDrawer;
Image[] images = { InfoTool.getImageFromResourcesFolder("star1.png") , InfoTool.getImageFromResourcesFolder("star2.png") ,
InfoTool.getImageFromResourcesFolder("star3.png") , InfoTool.getImageFromResourcesFolder("star4.png") ,
InfoTool.getImageFromResourcesFolder("star5.png") };
/**
* Instantiates a new sprite 3 D.
*
* @param gc the gc
*/
public Sprite3D(VisualizerDrawer visualizerDrawer, Shape3D shape) {
// super(gc);
this.visualizerDrawer = visualizerDrawer;
//background = new Image(getClass().getResourceAsStream(InfoTool.images + "trapNation.jpg"));
customInitialise(shape, -1, -1);
}
// @Override
// protected void initialise() {
// imageBall = new
// Image(getClass().getResourceAsStream("/resources/earth.png"));
// }
/**
* Custom initialise.
*
* @param shape the shape
* @param startMillis the start millis
* @param stopMillis the stop millis
*/
private void customInitialise(Shape3D shape , long startMillis , long stopMillis) {
// this.effectStartMillis = startMillis;
// this.effectStopMillis = stopMillis;
switch (shape) {
case CUBE:
points = makeCube(12, 3.0);
break;
case RING:
points = makeRing(48, 2.0);
break;
case SPHERE:
points = makeSphere(5.0, 50);
break;
case TUBE:
points = makeTube(48, 1.0, 16, 3.0);
break;
default:
break;
}
// itemCount = points.size();
renderList = new ArrayList<>(points.size());
}
/**
* Make cube.
*
* @param balls the balls
* @param side the side
* @return the list
*/
private List<Point3D> makeCube(int balls , double side) {
zoom = 250;
rollInc = 1.0;
pitchInc = 0.5;
yawInc = 1.5;
zOffset = 4;
List<Point3D> result = new ArrayList<>();
double gap = 1.0 / ( balls / 2 - 1 );
double halfSide = side / 2.0;
for (double x = -halfSide; x <= halfSide; x += gap) {
for (double y = -halfSide; y <= halfSide; y += gap) {
for (double z = -halfSide; z <= halfSide; z += gap) {
result.add(new Point3D(x, y, z));
}
}
}
return result;
}
/**
* Make ring.
*
* @param balls the balls
* @param radius the radius
* @return the list
*/
private List<Point3D> makeRing(double balls , double radius) {
zoom = 100;
rollInc = 1.0;
pitchInc = 0.5;
yawInc = 1.5;
zOffset = 2.5;
List<Point3D> result = new ArrayList<>();
for (double a = 0; a < 360; a += 360.0 / balls) {
double x = radius * Math.sin(Math.toRadians(a));// precalc.sin(a);
double y = radius * Math.cos(Math.toRadians(a));// precalc.cos(a);
result.add(new Point3D(x, y, 0));
}
return result;
}
/**
* Make tube.
*
* @param ballsPerRing the balls per ring
* @param radius the radius
* @param rows the rows
* @param length the length
* @return the list
*/
private List<Point3D> makeTube(double ballsPerRing , double radius , int rows , double length) {
zoom = 300;
rollInc = 1.0;
pitchInc = 0.5;
yawInc = 1.5;
zOffset = 4.5;
List<Point3D> result = new ArrayList<>();
double gap = rows == 1 ? 1 : ( 1.0 / ( rows - 1 ) );
double halfSide = length / 2.0;
for (double z = -halfSide; z <= halfSide; z += gap) {
for (double a = 0; a < 360; a += 360.0 / ballsPerRing) {
double x = radius * Math.sin(Math.toRadians(a));// precalc.sin(a);
double y = radius * Math.cos(Math.toRadians(a));// precalc.cos(a);
result.add(new Point3D(x, y, z));
}
}
return result;
}
/**
* Make sphere.
*
* @param maxRadius the max radius
* @param rings the rings
* @return the list
*/
private List<Point3D> makeSphere(double maxRadius , double rings) {
zoom = 100;
rollInc = 0.5;
pitchInc = 0.5;
yawInc = 0.5;
zOffset = 5.5;
List<Point3D> result = new ArrayList<>();
double zAngle = 0.0;
double zInc = 180 / rings;
for (double r = 0; r <= rings; r++) {
double z = maxRadius * Math.cos(Math.toRadians(zAngle));
zAngle += zInc;
double radius = maxRadius * Math.sin(Math.toRadians( ( r / rings ) * 180));
double ballsInLayer = Math.floor(radius * 16.0);
double angleGap = 360.0 / ballsInLayer;
for (double a = 0; a < 360; a += angleGap) {
double x = radius * Math.sin(Math.toRadians(a));// precalc.sin(a);
double y = radius * Math.cos(Math.toRadians(a));// precalc.cos(a);
result.add(new Point3D(x, y, z));
}
}
return result;
}
/**
* Draws the sprite.
*
* @param width the width
* @param height the height
* @param band the band
*/
public void draw() {
float[] pSample = visualizerDrawer.stereoMerge(visualizerDrawer.pLeftChannel, visualizerDrawer.pRightChannel);
float[] array = visualizerDrawer.returnBandsArray(pSample, 3);
//gc.clearRect(0, 0, width, height);
//gc.setStroke(Color.WHITE);
//gc.drawImage(background, 0, 0, width, height);
visualizerDrawer.drawBackgroundImage();
visualizerDrawer.drawForegroundImage(array);
roll += rollInc;
pitch += pitchInc;
yaw += yawInc;
renderList.clear();
for (int i = 0; i < array.length; i++) {
array[i] = Math.abs(array[i]);
array[i] *= 100.00;
}
for (int i = 0; i < points.size(); i++) {
Point3D point = points.get(i);
renderList.add(transform(point, roll, pitch, yaw, xOffset, yOffset, zOffset, array));
}
zSort(renderList);
//System.out.println(array[0])
if (array[1] <= 15)
imageBall = images[0];
else if (array[1] <= 25)
imageBall = images[1];
else if (array[1] <= 35)
imageBall = images[2];
else if (array[1] <= 45)
imageBall = images[3];
else
imageBall = images[4];
for (int i = 0; i < renderList.size(); i++) {
Point3D point = renderList.get(i);
drawPoint(point, visualizerDrawer.getVisualizerWidth(), visualizerDrawer.getVisualizerHeight());
}
}
/**
* Z sort.
*
* @param points the points
*/
private final void zSort(List<Point3D> points) {
Collections.sort(points, zComparator);
}
/**
* Cos.
*
* @param degrees the degrees
* @return the double
*/
public double cos(double degrees) {
return Math.cos(Math.toRadians(degrees));
}
/**
* Sin.
*
* @param degrees the degrees
* @return the double
*/
public double sin(double degrees) {
return Math.sin(Math.toRadians(degrees));
}
/**
* Transform.
*
* @param orig the orig
* @param pitch the pitch
* @param yaw the yaw
* @param roll the roll
* @param translateX the translate X
* @param translateY the translate Y
* @param translateZ the translate Z
* @param band the band
* @return the point 3 D
*/
private final Point3D transform(Point3D orig , double pitch , double yaw , double roll , double translateX , double translateY ,
double translateZ , float[] bands) {
// rotate around Z axis (roll)
double newX = orig.x * cos(bands[0]) - orig.y * sin(roll);
double newY = orig.x + sin(bands[0]) + orig.y * cos(roll);
double newZ = orig.z;
// rotate around X axis (pitch)
double newY2 = newY + cos(bands[1]) - newZ * sin(pitch);
double newZ2 = newY * sin(bands[1]) + newZ * cos(pitch);
double newX2 = newX;
// rotate around Y axis (yaw)
double newZ3 = newZ2 * cos(bands[2]) - newX2 * sin(yaw);
double newX3 = newZ2 * sin(bands[2]) + newX2 * cos(yaw);
double newY3 = newY2;
// double newX = orig.x * cos(roll) - orig.y * sin(roll);
// double newY = orig.x + sin(roll) + orig.y * cos(roll);
// double newZ = orig.z;
//
// // rotate around X axis (pitch)
// double newY2 = newY + cos(pitch) - newZ * sin(pitch);
// double newZ2 = newY * sin(pitch) + newZ * cos(pitch);
// double newX2 = newX;
//
// // rotate around Y axis (yaw)
// double newZ3 = newZ2 * cos(yaw) - newX2 * sin(yaw);
// double newX3 = newZ2 * sin(yaw) + newX2 * cos(yaw);
// double newY3 = newY2;
// translate
newX3 += translateX;
newY3 += translateY;
newZ3 += translateZ;
return new Point3D(newX3, newY3, newZ3);
}
/**
* Draw point.
*
* @param point the point
* @param width the width
* @param height the height
*/
private final void drawPoint(Point3D point , double width , double height) {
double x = width / 2 + point.x / point.z * zoom;
double y = height / 2 + point.y / point.z * zoom;
double ballSize = 24 / point.z;
visualizerDrawer.gc.drawImage(imageBall, x, y, ballSize, ballSize);
}
}