i write the following code for a cube, that rotates on mouse motion,
but when i rotate the cube, or resize the Frame, the cube shrinks successively.
Is this the code or Frame, that is to be changed..
Pls Help,,
public class Cube extends javax.swing.JPanel implements MouseMotionListener {
int node0[] = {-100, -100, -100};
int node1[] = {-100, -100, 100};
int node2[] = {-100, 100, -100};
int node3[] = {-100, 100, 100};
int node4[] = {100, -100, -100};
int node5[] = { 100, -100, 100};
int node6[] = {100, 100, -100};
int node7[] = {100, 100, 100};
int nodes[][] = {node0, node1, node2, node3, node4, node5, node6, node7};
int edge0[] = {0, 1};
int edge1[] = {1, 3};
int edge2[] = {3, 2};
int edge3[] = {2, 0};
int edge4[] = {4, 5};
int edge5[] = {5, 7};
int edge6[] = {7, 6};
int edge7[] = {6, 4};
int edge8[] = {0, 4};
int edge9[] = {1, 5};
int edge10[] = {2, 6};
int edge11[] = {3, 7};
int edges[][] = {edge0, edge1, edge2, edge3, edge4, edge5, edge6, edge7, edge8, edge9, edge10, edge11};
// Rotate shape around the z-axis
public void rotateZ3D(int theta) {
double sinTheta = Math.sin(theta);
double cosTheta = Math.cos(theta);
for (int n=0; n<8; n++) {
int[] node = nodes[n];
int x = node[0];
int y = node[1];
node[0] = (int) (x * cosTheta - y * sinTheta);
node[1] = (int) (y * cosTheta + x * sinTheta);
}
};
public void rotateX3D(int theta) {
double sinTheta = Math.sin(theta);
double cosTheta = Math.cos(theta);
for (int n=0; n<8; n++) {
int[] node = nodes[n];
int y = node[1];
int z = node[2];
node[1] = (int) (y * cosTheta - z * sinTheta);
node[2] = (int) (z * cosTheta + y * sinTheta);
}
};
public void rotateY3D(int theta) {
double sinTheta = Math.sin(theta);
double cosTheta = Math.cos(theta);
for (int n=0; n<8; n++) {
int[] node = nodes[n];
int x = node[0];
int z = node[2];
node[0] = (int) (x * cosTheta - z * sinTheta);
node[2] = (int) (z * cosTheta + x * sinTheta);
}
};
public void paintComponent(Graphics g) {
super.paintComponent(g);
// Draw edges
g.translate(150, 150);
rotateZ3D(60);
rotateY3D(60);
rotateX3D(60);
for (int e=0; e<12; e++) {
int n0 = edges[e][0];
int n1 = edges[e][1];
int node0[] = nodes[n0];
int node1[] = nodes[n1];
g.drawLine(node0[0], node0[1], node1[0], node1[1]);
}
// Draw nodes
for (int n=0; n<8; n++) {
int node[] = nodes[n];
g.drawOval(node[0], node[1], 5,5);
g.drawString(n+"", node[0], node[1]);
}
};
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
JFrame j = new JFrame();
Cube p = new Cube();
j.add(p);
j.addMouseMotionListener(p);
j.setSize(500,500);
j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
j.show();
// TODO code application logic here
}
#Override
public void mouseDragged(MouseEvent me) {
int x0 = me.getX();
int y0 = me.getY();
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
Logger.getLogger(Cube.class.getName()).log(Level.SEVERE, null, ex);
}
int x1 = me.getX();
int y1 = me.getX();
rotateY3D(x1 - x0);
rotateX3D(y1 - y0);
repaint();
}
#Override
public void mouseMoved(MouseEvent me) {
}
}
suggest the solution code for it..
It's working fine , except that the cube is shrinking
You're storing the coordinates as ints.
Each time you do a rotation, you do a calculation which doesn't yield an integer; when you cast, you truncate the integer, rounding towards zero. Hence the shrinkage.
Use double instead, or, better, simply calculate a rotation matrix and apply that to the coordinates when you are rendering it.
Related
I have a cube and there is a need to add a 3D coordinate system to it.
There is an example my coordinate system with a cube should approximtely look like:
Unfortunately, my progress seems so far from this example:
Maybe, I can find out how to draw X and Y axis, but I have no idea how to add the Z axis.
So, how to build the right coordinate sytem?
My code:
import java.awt.*;
import static java.lang.Math.*;
import javax.swing.*;
public class Cube extends JPanel {
double[][] nodes = {{-1, -1, -1}, {-1, -1, 1}, {-1, 1, -1}, {-1, 1, 1},
{1, -1, -1}, {1, -1, 1}, {1, 1, -1}, {1, 1, 1}};
int[][] edges = {{0, 1}, {1, 3}, {3, 2}, {2, 0}, {4, 5}, {5, 7}, {7, 6},
{6, 4}, {0, 4}, {1, 5}, {2, 6}, {3, 7}};
public Cube() {
setPreferredSize(new Dimension(640, 640));
setBackground(Color.white);
scale(50);
rotateCube(Math.toRadians(60), Math.toRadians(10), Math.toRadians(0));
}
final void scale(double s) {
for (double[] node : nodes) {
node[0] *= s;
node[1] *= s;
node[2] *= s;
}
}
final void rotateCube(double angleX, double angleY, double angleZ) {
double sinX = sin(angleX);
double cosX = cos(angleX);
double sinY = sin(angleY);
double cosY = cos(angleY);
double sinZ = sin(angleZ);
double cosZ = cos(angleZ);
for (double[] node : nodes) {
double x = node[0];
double y = node[1];
double z = node[2];
node[0] = x * cosX - z * sinX;
node[2] = z * cosX + x * sinX;
z = node[2];
node[1] = y * cosY - z * sinY;
node[2] = y * sinY + z * cosY;
x = node[0];
y = node[1];
node[0] = x * cosZ + y * sinZ;
node[1] = y * cosZ - x * sinZ;
}
}
void drawCube(Graphics2D g) {
g.translate(getWidth() / 2, getHeight() / 2);
g.setColor(Color.BLACK);
for (int[] edge : edges) {
double[] xy1 = nodes[edge[0]];
double[] xy2 = nodes[edge[1]];
g.drawLine((int) round(xy1[0]), (int) round(xy1[1]),
(int) round(xy2[0]), (int) round(xy2[1]));
}
for (double[] node : nodes)
g.fillOval((int) round(node[0]) - 4, (int) round(node[1]) - 4, 8, 8);
}
void drawAxis(Graphics2D g) {
int x_c = getWidth() / 2;
int y_c = getHeight() / 2;
// X - axis
g.setColor(Color.green);
g.drawLine(round(x_c + 300), round(y_c), round(x_c), round(y_c));
// Y- axis
g.setColor(Color.blue);
g.drawLine(round(x_c), round(y_c), round(x_c), round(y_c) + 300);
}
#Override
public void paintComponent(Graphics gg) {
super.paintComponent(gg);
Graphics2D g = (Graphics2D) gg;
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
drawAxis(g);
drawCube(g);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setTitle("Rotating Cube");
f.setResizable(false);
f.add(new Cube(), BorderLayout.CENTER);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
I face some weird behavior after adding 3d content to my JavaFX application which contains a toolbar.
I created a small project that replicates this problem. In the main application, I use SubScene but the behavior is absolutely the same.
Here is what the application should look like(without toolbar)
After adding this single line
ToolBar toolBar = new ToolBar();
The content becomes like this
Here is the code
import java.util.*;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.DepthTest;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.SceneAntialiasing;
import javafx.scene.control.ToolBar;
import javafx.scene.input.ScrollEvent;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.CullFace;
import javafx.scene.shape.DrawMode;
import javafx.scene.shape.Line;
import javafx.scene.shape.MeshView;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.TriangleMesh;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
import javafx.util.Pair;
import org.apache.commons.math3.analysis.interpolation.PiecewiseBicubicSplineInterpolatingFunction;
public class Main extends Application {
double[] xMetricData = {1 * 1000, 10 * 1000, 20 * 1000, 30 * 1000, 40 * 1000};
double[] yMetricData = {1 * 1000, 10 * 1000, 20 * 1000, 30 * 1000, 40 * 1000, 50 * 1000};
double[][] fMetricData = {{25, 5, 10, 15, 30, 30}, {15, -5, 5, 15, 25, 25}, {35, 5, 15, 10, 15, 15}, {15, 25, 15, 25, 35, 35}, {20, 30, 25, 30, 40, 40}};
int size = 50;
int cubeSize = 100;
// variables for mouse interaction
private double mousePosX, mousePosY;
private double mouseOldX, mouseOldY;
private final Rotate rotateX = new Rotate(20, Rotate.X_AXIS);
private final Rotate rotateY = new Rotate(-45, Rotate.Y_AXIS);
#Override
public void start(Stage primaryStage) {
// create axis walls
Group cube = createCube(cubeSize);
// initial cube rotation
cube.getTransforms().addAll(rotateX, rotateY);
//ToolBar toolBar = new ToolBar();
// add objects to scene
StackPane root = new StackPane();
root.getChildren().add(cube);
TriangleMesh mesh = new TriangleMesh();
int xLength = 0, zLength = 0;
for (int x = (int)xMetricData[0]; x < xMetricData[xMetricData.length - 1]; x+= 1000)
{
zLength = 0;
for (int z = (int) yMetricData[0]; z < yMetricData[yMetricData.length - 1]; z+= 1000)
{
float y = (float) apacheInterpolation(x, z);
//System.out.println(x +"," + z + ", " + y);
mesh.getPoints().addAll(x / 1000.0f, y, z / 1000.0f);
zLength += 1;
}
xLength += 1;
}
for (float x = 0; x < xLength - 1; x++)
{
for (float y = 0; y < zLength - 1; y++)
{
float x0 = x / xLength;
float y0 = y / zLength;
float x1 = (x + 1) / xLength;
float y1 = (y + 1) / zLength;
mesh.getTexCoords().addAll( //
x0, y0, // 0, top-left
x0, y1, // 1, bottom-left
x1, y1, // 2, top-right
x1, y1 // 3, bottom-right
);
}
}
// faces
for (int x = 0; x < xLength - 1; x++)
{
for (int z = 0; z < zLength - 1; z++)
{
int tl = x * zLength + z; // top-left
int bl = x * zLength + z + 1; // bottom-left
int tr = (x + 1) * zLength + z; // top-right
int br = (x + 1) * zLength + z + 1; // bottom-right
int offset = (x * (zLength - 1) + z ) * 8 / 2; // div 2 because we have u AND v in the list
// working
mesh.getFaces().addAll(bl, offset + 1, tl, offset + 0, tr, offset + 2);
mesh.getFaces().addAll(tr, offset + 2, br, offset + 3, bl, offset + 1);
System.out.println(tl +", " + tr);
}
}
System.out.println(mesh.getPoints().size());
PhongMaterial material = new PhongMaterial();
//material.setDiffuseMap(diffuseMap);
material.setSpecularColor(Color.BLACK);
MeshView meshView = new MeshView(mesh);
// meshView.setTranslateX(-0.5 * size);
// meshView.setTranslateZ(-0.5 * size);
meshView.setMaterial(material);
meshView.setCullFace(CullFace.BACK);
meshView.setDrawMode(DrawMode.FILL);
meshView.setDepthTest(DepthTest.ENABLE);
cube.getChildren().addAll(meshView);
// scene
Scene scene = new Scene(root, 800, 700, true, SceneAntialiasing.BALANCED);
scene.setCamera(new PerspectiveCamera());
scene.setOnMousePressed(me -> {
mouseOldX = me.getSceneX();
mouseOldY = me.getSceneY();
});
scene.setOnMouseDragged(me -> {
mousePosX = me.getSceneX();
mousePosY = me.getSceneY();
rotateX.setAngle(rotateX.getAngle() - (mousePosY - mouseOldY));
rotateY.setAngle(rotateY.getAngle() + (mousePosX - mouseOldX));
mouseOldX = mousePosX;
mouseOldY = mousePosY;
});
makeZoomable(root);
primaryStage.setResizable(true);
primaryStage.setScene(scene);
primaryStage.show();
}
public static double getFirmwareOffset(List<int[]> matrix, int x, int y)
{
Comparator<Pair<Integer, Long>> idComparator = (p1, p2) -> (int) (p2.getKey() - p1.getValue());
Queue<Pair<Integer, Long>> integerPriorityQueue = new PriorityQueue<>(5, idComparator);
long minDistance = -1;
long sumDistance = 0;
for (int i = 0; i < matrix.size(); ++i)
{
long difX = (long)Math.abs(matrix.get(i)[0] - x);
long difY = (long)Math.abs(matrix.get(i)[1] - y);
// in case accuracy is not enough we coudl go back to the traditional formula
//long distance = sqrt(difX * difX + difY * difY);
long distance = difX + difY;
if (distance == 0)
return matrix.get(i)[2];
if (integerPriorityQueue.size() < 15)
{
integerPriorityQueue.add(new Pair<>(i, distance));
sumDistance += distance;
}
else
{
Pair<Integer, Long> top = integerPriorityQueue.peek();
if (top.getValue() > distance)
{
integerPriorityQueue.poll();
integerPriorityQueue.add(new Pair<>(i, distance));
sumDistance -= top.getValue();
sumDistance += distance;
}
}
if (minDistance == -1 || distance < minDistance)
minDistance = distance;
}
double sumRatios = 0;
List<Pair<Integer, Double>> ratios = new ArrayList<>();
while(integerPriorityQueue.size() > 0)
{
Pair<Integer, Long> entry = integerPriorityQueue.poll();
double ratio = (double)sumDistance / entry.getValue();
ratios.add(new Pair<>(entry.getKey(), ratio));
sumRatios += ratio;
}
if (sumRatios == 0)
return 0;
double offset = 0;
for (int i = 0; i < ratios.size(); ++i)
{
Pair<Integer, Double> entry = ratios.get(i);
offset += (matrix.get(entry.getKey())[2] * entry.getValue() / sumRatios);
}
return offset;
}
/**
* Axis wall
*/
public static class Axis extends Pane {
Rectangle wall;
public Axis(double size) {
// wall
// first the wall, then the lines => overlapping of lines over walls
// works
wall = new Rectangle(size, size);
getChildren().add(wall);
// grid
double zTranslate = 0;
double lineWidth = 1.0;
Color gridColor = Color.WHITE;
for (int y = 0; y <= size; y += size / 10) {
Line line = new Line(0, 0, size, 0);
line.setStroke(gridColor);
line.setFill(gridColor);
line.setTranslateY(y);
line.setTranslateZ(zTranslate);
line.setStrokeWidth(lineWidth);
getChildren().addAll(line);
}
for (int x = 0; x <= size; x += size / 10) {
Line line = new Line(0, 0, 0, size);
line.setStroke(gridColor);
line.setFill(gridColor);
line.setTranslateX(x);
line.setTranslateZ(zTranslate);
line.setStrokeWidth(lineWidth);
getChildren().addAll(line);
}
// labels
// TODO: for some reason the text makes the wall have an offset
// for( int y=0; y <= size; y+=size/10) {
//
// Text text = new Text( ""+y);
// text.setTranslateX(size + 10);
//
// text.setTranslateY(y);
// text.setTranslateZ(zTranslate);
//
// getChildren().addAll(text);
//
// }
}
public void setFill(Paint paint) {
wall.setFill(paint);
}
}
public void makeZoomable(StackPane control) {
final double MAX_SCALE = 20.0;
final double MIN_SCALE = 4;
control.setScaleX(MIN_SCALE);
control.setScaleY(MIN_SCALE);
control.addEventFilter(ScrollEvent.ANY, new EventHandler<ScrollEvent>() {
#Override
public void handle(ScrollEvent event) {
double delta = 1.2;
double scale = control.getScaleX();
if (event.getDeltaY() < 0) {
scale /= delta;
} else {
scale *= delta;
}
scale = clamp(scale, MIN_SCALE, MAX_SCALE);
control.setScaleX(scale);
control.setScaleY(scale);
event.consume();
}
});
}
/**
* Create axis walls
* #param size
* #return
*/
private Group createCube(int size) {
Group cube = new Group();
// size of the cube
Color color = Color.DARKCYAN;
List<Axis> cubeFaces = new ArrayList<>();
Axis r;
// back face
r = new Axis(size);
r.setFill(color.deriveColor(0.0, 1.0, (1 - 0.5 * 1), 1.0));
r.setTranslateX(-0.5 * size);
r.setTranslateY(-0.5 * size);
r.setTranslateZ(0.5 * size);
cubeFaces.add(r);
// bottom face
r = new Axis(size);
r.setFill(color.deriveColor(0.0, 1.0, (1 - 0.4 * 1), 1.0));
r.setTranslateX(-0.5 * size);
r.setTranslateY(0);
r.setRotationAxis(Rotate.X_AXIS);
r.setRotate(90);
cubeFaces.add(r);
// right face
r = new Axis(size);
r.setFill(color.deriveColor(0.0, 1.0, (1 - 0.3 * 1), 1.0));
r.setTranslateX(-1 * size);
r.setTranslateY(-0.5 * size);
r.setRotationAxis(Rotate.Y_AXIS);
r.setRotate(90);
// cubeFaces.add( r);
// left face
r = new Axis(size);
r.setFill(color.deriveColor(0.0, 1.0, (1 - 0.2 * 1), 1.0));
r.setTranslateX(0);
r.setTranslateY(-0.5 * size);
r.setRotationAxis(Rotate.Y_AXIS);
r.setRotate(90);
cubeFaces.add(r);
// top face
r = new Axis(size);
r.setFill(color.deriveColor(0.0, 1.0, (1 - 0.1 * 1), 1.0));
r.setTranslateX(-0.5 * size);
r.setTranslateY(-1 * size);
r.setRotationAxis(Rotate.X_AXIS);
r.setRotate(90);
// cubeFaces.add( r);
// front face
r = new Axis(size);
r.setFill(color.deriveColor(0.0, 1.0, (1 - 0.1 * 1), 1.0));
r.setTranslateX(-0.5 * size);
r.setTranslateY(-0.5 * size);
r.setTranslateZ(-0.5 * size);
// cubeFaces.add( r);
cube.getChildren().addAll(cubeFaces);
return cube;
}
public static double normalizeValue(double value, double min, double max, double newMin, double newMax) {
return (value - min) * (newMax - newMin) / (max - min) + newMin;
}
public static double clamp(double value, double min, double max) {
if (Double.compare(value, min) < 0)
return min;
if (Double.compare(value, max) > 0)
return max;
return value;
}
public static void main(String[] args) {
launch(args);
}
public double apacheInterpolation(float px, float py)
{
PiecewiseBicubicSplineInterpolatingFunction t = new PiecewiseBicubicSplineInterpolatingFunction(xMetricData, yMetricData, fMetricData);
return t.value(px, py);
}
}
UPD: After a bit investigation, any control leads to this behavior.
Use a SubScene and adjust the nearClip of the camera to the smallest possible value:
SubScene scene = new SubScene(root, 800, 700, true, SceneAntialiasing.BALANCED);
PerspectiveCamera camera = new PerspectiveCamera();
camera.setNearClip(Double.MIN_VALUE);
scene.setCamera(camera);
...
BorderPane sRoot = new BorderPane(scene);
sRoot.setTop(new ToolBar());
Scene mainScene = new Scene(sRoot);
primaryStage.setResizable(true);
primaryStage.setScene(mainScene);
primaryStage.show();
As #Fabian mentioned I continued experimenting with SubScene. The trick is not to use any Panes while adding 3d elements to a SubScene.
I'm trying to write an algorithm to satisfy this challenge. I've double, triple, and quadruple checked my logic, but I think I'm missing something obvious. This program should group each color next to similar colors, but it produces something more akin to noise.
This is sort of what I expect (taken from a similar answer):
And this is what I'm actually getting:
public class AllColors extends JFrame {
private static final int WIDTH = 256;
private static final int HEIGHT = 128;
private static long TOTAL_ITERATIONS = (WIDTH * HEIGHT) * 185000;
private static int VALUES_PER_CHANNEL =32;
private static int CHANNEL_DELTA = 256/VALUES_PER_CHANNEL;
static BufferedImage image;
private static final int SCALE = 5;
static int[][] kernel = { { 0, 0, 1, 0, 0 },
{ 0, 2, 3, 2, 0 },
{ 1, 3, 0, 3, 1 },
{ 0, 2, 3, 2, 0 },
{ 0, 0, 1, 0, 0 } };
public static void main(String[] args) {
AllColors f = new AllColors();
f.setTitle("All Colors");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
image = new BufferedImage(WIDTH * SCALE, HEIGHT * SCALE, BufferedImage.TYPE_3BYTE_BGR);
init();
//gui stuff
JPanel p = new JPanel(){
#Override
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.scale(SCALE, SCALE);
g2.drawImage(image, 0, 0, null);
}
};
p.setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
f.add(p);
f.pack();
f.setVisible(true);
group(p);
}
//makes an image of all colors
private static void init() {
int x = 0;
int y = 0;
for(int r = 0; r < VALUES_PER_CHANNEL; r+= 1){
for(int g = 0; g < VALUES_PER_CHANNEL; g+= 1){
for(int b = 0; b < VALUES_PER_CHANNEL; b+= 1){
x++;
if(x % WIDTH == 0){
y++;
x = 0;
}
if(y >= HEIGHT)
return;
image.setRGB(x, y, new Color(r*CHANNEL_DELTA,g*CHANNEL_DELTA,b*CHANNEL_DELTA).getRGB());
}
}
}
}
//group together similar pixels
private static void group(JPanel panel){
Random rand = new Random();
for(long i = 0; i < TOTAL_ITERATIONS; i++){
Point first = new Point(rand.nextInt(WIDTH), rand.nextInt(HEIGHT));
Point second = new Point(rand.nextInt(WIDTH), rand.nextInt(HEIGHT));
trySwitch(first, second);
if(i % (WIDTH * HEIGHT) == 0){
System.out.println(i / (WIDTH * HEIGHT));
panel.repaint();
}
}
}
private static void swap(Point first, Point second){
int temp = image.getRGB(second.x, second.y);
image.setRGB(second.x, second.y, image.getRGB(first.x, first.y));
image.setRGB(first.x, first.y, temp);
}
//get how similar the neighbors are
private static int getNeighborDelta(int imageX, int imageY){
Color center = new Color(image.getRGB(imageX, imageY));
int sum = 0;
for (int x = 0; x < kernel[0].length; x++)
{
for (int y = 0; y < kernel.length; y++)
{
int weight = kernel[x][y];
if (weight <= 0)
{
continue;
}
int xOffset = x - (kernel[0].length / 2);
int yOffset = y - (kernel.length / 2);
try{
sum += getDistance(new Color(image.getRGB(imageX + xOffset, imageY + yOffset)), center) * weight;
}catch(ArrayIndexOutOfBoundsException e){
//if out of image
}
}
}
return sum;
}
//switches if the neighbors will be more similar
private static void trySwitch(Point first, Point second){
double firstDistance = getNeighborDelta(first.x, first.y);
swap(first, second);
double secondDistance = getNeighborDelta(first.x, first.y);
if(secondDistance > firstDistance)
swap(first, second);
}
//get similarity between colors
private static double getDistance(Color one, Color two){
int r = Math.abs(two.getRed() - one.getRed());
int g = Math.abs(two.getGreen() - one.getGreen());
int b = Math.abs(two.getBlue() - one.getBlue());
return r + g + b;
}
}
I need to make perlin noise like in AS3.0:
bitmapData.perlinNoise(baseX, baseY, numOctaves,
randomSeed, stitch, fractalNoise, grayScale, offsets);
It's seamless noise:
I found a lot of material about it, but I can't make it like in my as3.0 image. Java code:
import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class Noise extends JPanel{
public static int octaves = 4;
public static int size = 128;
public static float[][][] noise = new float[size][size][octaves];
public static float[][] perlinnoise = new float[size][size];
public static float p = (float) 1/4;
public static Random gen = new Random();
public static float GenerateNoise() {
return gen.nextFloat();
}
public static float SmoothNoise(int x, int y, int z) {
try{
float corners = (noise[x - 1][y - 1][z] + noise[x + 1][y - 1][z] + noise[x - 1][y + 1][z] + noise[x + 1][y + 1][z]) / 16;
float sides = (noise[x - 1][y][z] + noise[x + 1][y][z] + noise[x][y - 1][z] + noise[x][y + 1][z]) / 8;
float center = noise[x][y][z] / 4;
return corners + sides + center;
}catch(Exception e) {
return 0;
}
}
public static float InterpolatedNoise(float x, float y, int pX, int pY, int pZ) {
int intX = (int) x;
int intY = (int) y;
float fracX = x - intX;
float fracY = y - intY;
float v1 = SmoothNoise(pX, pY, pZ);
float v2 = SmoothNoise(pX + 1, pY, pZ);
float v3 = SmoothNoise(pX, pY + 1, pZ);
float v4 = SmoothNoise(pX + 1, pY + 1, pZ);
float i1 = Interpolate(v1, v2, fracX);
float i2 = Interpolate(v3, v4, fracX);
return Interpolate(i1, i2, fracY);
}
public static float Interpolate(float a, float b, float x) {
float ft = (float) (x * 3.1415927);
float f = (float) ((1 - Math.cos(ft)) * 0.5);
return (float) (a * (1 - f) + b * f);
}
public static float Perlin2D(float x, float y, int posX, int posY, int posZ) {
float total = 0;
for(int i = 0; i < octaves; i++) {
double f = Math.pow(2, i);
double a = Math.pow(p, i);
total = (float) (total + InterpolatedNoise((float)(x * f), (float)(y * f), posX, posY, posZ) * a);
}
return total;
}
public static void main(String [] args) {
for(int z = 0; z < octaves; z++) {
for(int y = 0; y < size; y++) {
for(int x = 0; x < size; x++) {
noise[x][y][z] = GenerateNoise();
}
}
}
for(int z = 0; z < octaves; z++) {
for(int y = 0; y < size; y++) {
for(int x = 0; x < size; x++) {
perlinnoise[x][y] = Perlin2D(x / (size - 1), y / (size - 1), x, y, z) / octaves;
}
}
}
JFrame f = new JFrame("Perlin Noise");
f.setSize(400, 400);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new Noise());
f.setVisible(true);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
for(int y = 0; y < size; y++) {
for(int x = 0; x < size; x++) {
g.setColor(new Color(perlinnoise[x][y], perlinnoise[x][y], perlinnoise[x][y]));
g.fillRect(x * 2, y * 2, 2, 2);
}
}
repaint();
}
}
Help please!
The trick is, the Perlin noise does not use pseudo-random generator, it uses a function that takes an argument and returns predefined value for that argument, but when argument shifts by 1, the value jumps almost randomly. Check the sources for the permutation formulae, the init() method makes a permutation that then is used to make the entire noise.
I am trying to paint a cube on a JFrame.
Sounds simple, but lags a lot. The 7th and 8th lines usually flash pretty bad.
here is the code:
http://pastebin.com/ncDasST6
if someone can give me a hint or two on how to stop this lag from occurring, that would be great :D.
Originally was for Applet, but i wanted it to execute through a .jar file.
Also, any way to add an Applet to a JFrame?
I tried doing: add(new Rotational()); //name of JApplet it is based off of.
Thanks, Fire
Does this variant work to your expectation? There are a number of changes which I did not bother to document (as I was 'just playing' with the code). Do a diff. to reveal the extent and nature of the changes.
It shows no lag or rendering artifacts here at 700x700.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.GroupLayout.Alignment;
import javax.swing.border.EmptyBorder;
public class Square extends JPanel implements MouseListener,
MouseMotionListener {
private static final long serialVersionUID = 1L;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
JFrame f = new JFrame("Cube Rotational");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Square square = new Square();
square.setBorder(new EmptyBorder(5,5,5,5));
f.setContentPane(square);
f.pack();
f.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public Square() {
init();
setPreferredSize(new Dimension(700,700));
}
class Point3D {
public int x, y, z;
public Point3D(int X, int Y, int Z) {
x = X;
y = Y;
z = Z;
}
}
class Edge {
public int a, b;
public Edge(int A, int B) {
a = A;
b = B;
}
}
static int width, height;
static int mx, my;
static int azimuth = 45, elevation = 45;
static Point3D[] vertices;
static Edge[] edges;
public void init() {
width = 500;
height = 500;
vertices = new Point3D[8];
vertices[0] = new Point3D(-1, -1, -1);
vertices[1] = new Point3D(-1, -1, 1);
vertices[2] = new Point3D(-1, 1, -1);
vertices[3] = new Point3D(-1, 1, 1);
vertices[4] = new Point3D(1, 1, -1);
vertices[5] = new Point3D(1, 1, 1);
vertices[6] = new Point3D(1, -1, -1);
vertices[7] = new Point3D(1, -1, 1);
edges = new Edge[12];
edges[0] = new Edge(0, 1);
edges[1] = new Edge(0, 2);
edges[2] = new Edge(0, 6);
edges[3] = new Edge(1, 3);
edges[4] = new Edge(1, 7);
edges[5] = new Edge(2, 3);
edges[6] = new Edge(2, 4);
edges[7] = new Edge(3, 5);
edges[8] = new Edge(4, 5);
edges[9] = new Edge(4, 6);
edges[10] = new Edge(5, 7);
edges[11] = new Edge(6, 7);
setCursor(new Cursor(Cursor.HAND_CURSOR));
addMouseListener(this);
addMouseMotionListener(this);
setVisible(true);
}
void drawWireframe(Graphics g) {
double theta = Math.PI * azimuth / 180.0;
double phi = Math.PI * elevation / 180.0;
float cosT = (float) Math.cos(theta);
float sinT = (float) Math.sin(theta);
float cosP = (float) Math.cos(phi);
float sinP = (float) Math.sin(phi);
float cosTcosP = cosT * cosP;
float cosTsinP = cosT * sinP;
float sinTcosP = sinT * cosP;
float sinTsinP = sinT * sinP;
Point[] points;
points = new Point[vertices.length];
float scaleFactor = (getWidth() + getHeight()) / 8;
float near = (float) 6;
float nearToObj = 1.5f;
for (int j = 0; j < vertices.length; ++j) {
int x0 = vertices[j].x;
int y0 = vertices[j].y;
int z0 = vertices[j].z;
float x1 = cosT * x0 + sinT * z0;
float y1 = -sinTsinP * x0 + cosP * y0 + cosTsinP * z0;
float z1 = cosTcosP * z0 - sinTcosP * x0 - sinP * y0;
x1 = x1 * near / (z1 + near + nearToObj);
y1 = y1 * near / (z1 + near + nearToObj);
points[j] = new Point(
(int) (getWidth() / 2 + scaleFactor * x1 + 0.5),
(int) (getHeight() / 2 - scaleFactor * y1 + 0.5));
}
g.setColor(Color.black);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.white);
for (int j = 0; j < edges.length; ++j) {
int x1 = points[edges[j].a].x;
int x2 = points[edges[j].b].x;
int y1 = points[edges[j].a].y;
int y2 = points[edges[j].b].y;
((Graphics2D) g).setStroke(new BasicStroke(5));
g.drawLine(x1, y1, x2, y2);
}
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
mx = e.getX();
my = e.getY();
e.consume();
}
public void mouseReleased(MouseEvent e) {
}
public void mouseMoved(MouseEvent e) {
}
public void mouseDragged(MouseEvent e) {
int new_mx = e.getX();
int new_my = e.getY();
azimuth -= new_mx - mx;
azimuth %= 360;
elevation += new_my - my;
elevation %= 360;
repaint();
mx = new_mx;
my = new_my;
repaint();
e.consume();
}
#Override
public void paintComponent(Graphics g) {
drawWireframe(g);
}
}
Originally was for Applet, but i wanted it to execute through a .jar file.
Good idea converting an applet to something more sensible, but note that an applet can (and usually should) be packed into a Jar.
Also, any way to add an Applet to a JFrame?
This is possible, relatively easy with this code (barring mixing Swing (JFrame) & AWT (Applet) components), but not the best way to go. It is better to create a hybrid like (for example) the subway applet/application.
By moving the custom rendering from the frame to a JPanel, the code has been partially transformed into a hybrid, since the panel can be added to a frame or applet (or window or dialog, or another panel or..).