1
\$\begingroup\$

I programmed a cube in java and calculated the x y and z position for it's rotation on the x,y and z axis but I'm finding it hard to display the z axis i've been trying to change the distance of the vectors with higher z values to be closer to the middle of the Screen or the (0,0) point but am finding this rather hard any tips? Thank you.

here's the code:

public class vert {
 //screen position
 int x;
 int y;
 int z;
 //real rot position
 int xr;
 int yr;
 int zr;

 public void rotate(int xpos,int ypos,int zpos,int rotx,int roty,int rotz) {

    //x,y
    //calculate the new rotation 
    double rx1 = Math.toDegrees(Math.atan2(ypos,xpos)) + rotx;
    //calculate the hypotenuse
    double hypx1 = Math.sqrt(xpos * xpos + ypos * ypos);
    //calculate x1 
    double posx1 = Math.cos(Math.toRadians(rx1)) * hypx1;
    int tointx1 = (int) Math.round(posx1);
    int x1 = tointx1;
    //calculate y1
    double posy1 = Math.sin(Math.toRadians(rx1)) * hypx1;
    int tointy1 = (int) Math.rint(posy1);
    int y1 = tointy1;

    //x,z
    //calculate the new rotation 
    double ry2 = Math.toDegrees(Math.atan2(zpos,x1)) + roty;
    //calculate the hypotenuse
    double hypy2 = Math.sqrt(x1 * x1 + zpos * zpos);
    //calculate x final
    double posx2 = Math.cos(Math.toRadians(ry2)) * hypy2;
    int tointx2 = (int) Math.round(posx2);
    int x2 = tointx2;
        //calculate z1
    double posz2 = Math.sin(Math.toRadians(ry2)) * hypy2;
    int tointz2 = (int) Math.rint(posz2);
    int z1 = tointz2;

    //y,z
    //calculate the new rotation 
    double rz3 = Math.toDegrees(Math.atan2(z1,y1)) + rotz;
    //calculate the hypotenuse
    double hypz3 = Math.sqrt(y1 * y1 + z1 * z1);
    //calculate y final
    double posy3 = Math.cos(Math.toRadians(rz3)) * hypz3;   
    int tointy3 = (int) Math.round(posy3);  
    int y2 = tointy3;
    //calculate z final
    double posz3 = Math.sin(Math.toRadians(rz3)) * hypz3;   
    int tointz3 = (int) Math.rint(posz3);   
    int z2 = tointz3; 

    xr = x2;
    yr = y2;
    zr = z2 + 128;
 }

 public void perspective() {

    double pers = Screen.camfocallenght / zr;
    x = (int) Math.rint(xr * pers) + Screen.x;
    y = (int) Math.rint(yr * pers) + Screen.y;
 }
}

And here's the code that draws the cube onto screen:

import java.awt.Color;
import java.awt.Graphics;

import javax.swing.JComponent;
import javax.swing.JFrame;

public class Screen extends JComponent{

private static final long serialVersionUID = 1L;

static int height = 400;
static int width = 600;

static double camfocallenght = 100;

static int y = height / 2;
static int x = width / 2;

int movex = 0;
int movey = 0;
int movez = -100;

int a = 0;
int b = 0;
int c = 0;

vert[] v = new vert[12];

public void paint(Graphics g) {

    v[0] = new vert();
    v[0].rotate(movex + 45,movey + -45,movez + 45, a, b, c);
    v[1] = new vert();
    v[1].rotate(movex + 45,movey + 45,movez + 45, a, b, c);
    v[2] = new vert();
    v[2].rotate(movex + -45,movey + 45,movez + 45, a, b, c);
    v[3] = new vert(); 
    v[3].rotate(movex + -45,movey + -45,movez + 45, a, b, c);

    v[4] = new vert();
    v[4].rotate(movex + 45,movey + -45,movez + -45, a, b, c);
    v[5] = new vert();
    v[5].rotate(movex + 45,movey + 45,movez + -45, a, b, c);
    v[6] = new vert();
    v[6].rotate(movex + -45,movey + 45,movez + -45, a, b, c);
    v[7] = new vert();
    v[7].rotate(movex + -45,movey + -45,movez + -45, a, b, c);

    v[0].perspective();
    v[1].perspective();
    v[2].perspective();
    v[3].perspective();
    v[4].perspective();
    v[5].perspective();
    v[6].perspective();
    v[7].perspective();

    g.setColor(Color.green);

    g.drawLine( v[4].x, v[4].y, v[5].x, v[5].y);
    g.drawLine( v[6].x, v[6].y, v[7].x, v[7].y);
    g.drawLine( v[5].x, v[5].y, v[6].x, v[6].y);
    g.drawLine( v[7].x, v[7].y, v[4].x, v[4].y);

    g.setColor(Color.RED);

    g.drawLine(v[0].x, v[0].y, v[4].x, v[4].y);
    g.drawLine(v[1].x, v[1].y, v[5].x, v[5].y);
    g.drawLine(v[2].x, v[2].y, v[6].x, v[6].y);
    g.drawLine(v[3].x, v[3].y, v[7].x, v[7].y);

    g.setColor(Color.CYAN);

    g.drawLine( v[0].x, v[0].y, v[1].x, v[1].y);
    g.drawLine( v[2].x, v[2].y, v[3].x, v[3].y);
    g.drawLine( v[1].x, v[1].y, v[2].x, v[2].y);
    g.drawLine( v[3].x, v[3].y, v[0].x, v[0].y);

    String ShowZ = Integer.toString(v[1].xr);
    String Show4 = Integer.toString(v[4].x);
    String Showb = Integer.toString(b);

    g.drawString("x rotation:", 0, 10);
    g.drawString(Showb, 0, 22);
    g.drawString("z pos of vert 1:", 0, 30);
    g.drawString(ShowZ, 0, 42);
    g.drawString("x pos of vert 1 with perspective:", 0, 50);
    g.drawString(Show4, 0, 62);

    //a++;
    b++;
    //c++;

    try {
        Thread.sleep(100);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
 }

 public static void main(String[] args) {
    JFrame frame = new JFrame("Draw Line");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setSize(width, height);
    frame.setVisible(true);
    frame.getContentPane().add(new Screen());
    while (true) {
        frame.getContentPane().repaint();
    }
 } 
}
\$\endgroup\$
  • \$\begingroup\$ Ok,here's the graphics \$\endgroup\$ – ENR813 Feb 12 '18 at 17:49
  • \$\begingroup\$ I Guess no help in sight :( \$\endgroup\$ – ENR813 Feb 13 '18 at 9:08
  • \$\begingroup\$ I recommend starting here: en.wikipedia.org/wiki/3D_projection \$\endgroup\$ – CobaltHex Feb 13 '18 at 9:09
  • \$\begingroup\$ (And using matricies - It will make your math a lot cleaner) \$\endgroup\$ – CobaltHex Feb 13 '18 at 9:18
  • \$\begingroup\$ so I've been playing around with this but still couldn't get it to work any suggestions? \$\endgroup\$ – ENR813 Mar 27 '18 at 10:52
1
\$\begingroup\$

You just need to divide the x and y components by z. If you want to put the vanishing point "farther", then make the z component smaller (e.g. divide it by a constant). If you want to make the fov larger, then increase it by a constant.

\$\endgroup\$
  • \$\begingroup\$ Thanks tried that but got this as result: Exception in thread "AWT-EventQueue-0" java.lang.ArithmeticException \$\endgroup\$ – ENR813 Feb 13 '18 at 9:23
  • \$\begingroup\$ @ENR813 That clearly states what the problem is. Make sure you don't divide by zero \$\endgroup\$ – Bálint Feb 13 '18 at 9:25
  • \$\begingroup\$ the Cube collapsed into a plane with an x dont know why \$\endgroup\$ – ENR813 Feb 13 '18 at 10:16
  • \$\begingroup\$ @ENR how large can the z componebt be? \$\endgroup\$ – Bálint Feb 13 '18 at 10:17
  • \$\begingroup\$ I don't seem to be calculating the z component incorrectly \$\endgroup\$ – ENR813 Feb 13 '18 at 15:58
1
\$\begingroup\$

You will get a lot more of readability if you use matrices for this, then to find the new position of the vector, you just multiply the vector by the matrix.

This question is a bit old, but if you meant how to find the on-screen position based on the world position, then you need to multiply the world position by the perspective matrix:

mat4 perspective = mat4_perspective_fov(fov, width, height, near, far);
onscreen_pos = vec4_multiply_mat4(world_pos, perspective);

If you meant how to make a transition from orthographic to perspective (and vice-versa), you can linear interpolate two projection matrices:

mat4 perspective = mat4_perspective_fov(fov, width, height, near, far);
mat4 orthographic = mat4_ortho(left, right, bottom, top, near, far);
mat4 interpolated = mat4_lerp(perspective, ortho, 0.5);
onscreen_pos = vec4_multiply_mat4(world_pos, interpolated);

Then you will have a middle ground (0.5) between an orthographic and perspective projection.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.