简体   繁体   English

3D透视2D旋转缺乏精度

[英]3D coordinate rotation lacking Precision in perspective 2D

So I wrote a Program to draw and display a 3D cube, using these simple conversion formula's as used in isometric graphs: 所以我编写了一个程序来绘制和显示一个3D立方体,使用等轴测图中使用的这些简单的转换公式:

x2 = x*cos(30) - y*cos(30)
y2 = x*sin(30) + y*sin(30) + z

The coordinate conversion is fine and everything comes out in perspective. 坐标转换很好,一切都是透视。

The Issue is rotating, Large degree rotations messes up all the coordinates and gives me an entire shape. 问题是旋转,大程度的旋转扰乱了所有的坐标并给了我一个完整的形状。 And rotating at small degrees many many times, (ie 1000 1degree rotation or more) reduces the size of the cube. 并且以很小的角度旋转许多次(即,1000度旋转或更多旋转)减小了立方体的尺寸。

public void rotateX(double dg) //cube is shrinking along y and z  
{
    y = (y*Math.cos(dg)-z*Math.sin(dg));  
    z = (y*Math.sin(dg)+z*Math.cos(dg));  
}
public void rotateY(double dg) //cube is shrinking along x and z  
{  
    x = x*Math.cos(dg)-z*Math.sin(dg);  
    z = x*Math.sin(dg)+z*Math.cos(dg);  
}  
public void rotateZ(double dg) //cube is shrinking along x and y  
{  
    x = x*Math.cos(dg)-y*Math.sin(dg);  
    y = x*Math.sin(dg)+y*Math.cos(dg);  
}

How can i solve this lack of precision of cos and sin after multiple uses?? 多次使用后,我怎样才能解决cos和sin精度的缺失?

Here's the entire code written in 3 seperat classes: 这是用3个seperat类编写的整个代码:
Main class: 主要课程:

import java.awt.*;
import javax.swing.*;
import java.util.Random;
public class Frame extends JFrame
{
    private Random rnd = new Random();
    private cubeGUI cube;
    public Frame()
    {
        super();
    }

    public void paint(Graphics g)
    {
        cube = new cubeGUI(75,300.0,300.0);
        cube.convertall();
        double dg = 0.5; // The Smaller the degree, the less the error after long rotations.
        int sl = 5;
        int turns, axe;  
        while (1 == 1)
        {
            turns = rnd.nextInt(200)-100;
            axe = rnd.nextInt(3);
            for(int i = 0; i<turns; i++)
            {
                switch (axe)
                {
                    case 0: cube.rotatx(dg); break;
                    case 1: cube.rotaty(dg); break;
                    case 2: cube.rotatz(dg); break;
                }
                g.clearRect(0,0,600,600);
                g.drawLine(cube.a.x2,cube.a.y2,cube.b.x2,cube.b.y2);
                g.drawLine(cube.a.x2,cube.a.y2,cube.c.x2,cube.c.y2);
                g.drawLine(cube.c.x2,cube.c.y2,cube.d.x2,cube.d.y2);
                g.drawLine(cube.b.x2,cube.b.y2,cube.d.x2,cube.d.y2);
                g.drawLine(cube.e.x2,cube.e.y2,cube.f.x2,cube.f.y2);
                g.drawLine(cube.e.x2,cube.e.y2,cube.g.x2,cube.g.y2);
                g.drawLine(cube.g.x2,cube.g.y2,cube.h.x2,cube.h.y2);
                g.drawLine(cube.f.x2,cube.f.y2,cube.h.x2,cube.h.y2);
                g.drawLine(cube.a.x2,cube.a.y2,cube.e.x2,cube.e.y2);
                g.drawLine(cube.b.x2,cube.b.y2,cube.f.x2,cube.f.y2);
                g.drawLine(cube.c.x2,cube.c.y2,cube.g.x2,cube.g.y2);
                g.drawLine(cube.d.x2,cube.d.y2,cube.h.x2,cube.h.y2);
                try
                {
                    Thread.sleep(sl); //Rotation Speed, In relation with Angle of rotation.
                } catch(InterruptedException ex)
                {
                    Thread.currentThread().interrupt();
                }
            }
        }
}
public static void main(String[] args)
{
    Frame cube = new Frame();
        cube.setSize(600,600);
        cube.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        cube.setVisible(true);
    }
}

cube class: 立方体类:

public class cubeGUI
{
    public Point center,a,b,c,d,e,f,g,h;
    private double x, y;
    public cubeGUI(int m, double x, double y)
    {
        this.x = x;
        this.y = y;
        a = new Point(-m,-m,-m);
        b = new Point(m,-m,-m);
        c = new Point(-m,m,-m);
        d = new Point(m,m,-m);
        e = new Point(-m,-m,m);
        f = new Point(m,-m,m);
        g = new Point(-m,m,m);
        h = new Point(m,m,m);
    }
    public void rotatx(double dg)
    {
        a.rotateX(Math.toRadians(dg));
        b.rotateX(Math.toRadians(dg));
        c.rotateX(Math.toRadians(dg));
        d.rotateX(Math.toRadians(dg));
        e.rotateX(Math.toRadians(dg));
        f.rotateX(Math.toRadians(dg));
        g.rotateX(Math.toRadians(dg));
        h.rotateX(Math.toRadians(dg));
        convertall();
    }
    public void rotaty(double dg)
    {
        a.rotateY(Math.toRadians(dg));
        b.rotateY(Math.toRadians(dg));
        c.rotateY(Math.toRadians(dg));
        d.rotateY(Math.toRadians(dg));
        e.rotateY(Math.toRadians(dg));
        f.rotateY(Math.toRadians(dg));
        g.rotateY(Math.toRadians(dg));
        h.rotateY(Math.toRadians(dg));
        convertall();
    }
    public void rotatz(double dg)
    {
        a.rotateZ(Math.toRadians(dg));
        b.rotateZ(Math.toRadians(dg));
        c.rotateZ(Math.toRadians(dg));
        d.rotateZ(Math.toRadians(dg));
        e.rotateZ(Math.toRadians(dg));
        f.rotateZ(Math.toRadians(dg));
        g.rotateZ(Math.toRadians(dg));
        h.rotateZ(Math.toRadians(dg));
        convertall();
    }
    public void convertall()
    {
        a.convert(x,y);
        b.convert(x,y);
        c.convert(x,y);
        d.convert(x,y);
        e.convert(x,y);
        f.convert(x,y);
        g.convert(x,y);
        h.convert(x,y);
    }
}

Point class (this calculates all coordinates): Point类(计算所有坐标):

public class Point
{
    private double x, y, z, F;
    public int x2, y2;
    public Point(double a, double b, double c)
    {
        x = a;
        y = b;
        z = c;
    }
    public int getX()
    {
        return (int)x;
    }
    public int getY()
    {
        return (int)y;
    }
    public int getZ()
    {
        return (int)z;
    }
    public void rotateX(double dg) //cube is shrinking along y and z
    {
        y = (y*Math.cos(dg)-z*Math.sin(dg));
        z = (y*Math.sin(dg)+z*Math.cos(dg));
    }
    public void rotateY(double dg) //cube is shrinking along x and z
    {
        x = x*Math.cos(dg)-z*Math.sin(dg);
        z = x*Math.sin(dg)+z*Math.cos(dg);
    }
    public void rotateZ(double dg) //cube is shrinking along x and y
    {
        x = x*Math.cos(dg)-y*Math.sin(dg);
        y = x*Math.sin(dg)+y*Math.cos(dg);
    }
    public void convert(double xx, double yy)
    {
        x2 = (int)(-(Math.cos(Math.toRadians(30))*x - Math.cos(Math.toRadians(30))*y) + xx);
        y2 = (int)(-(Math.sin(Math.toRadians(30))*x + Math.sin(Math.toRadians(30))*y + z) + yy);
    }
    public String toString()
    {
        return ("Y = " + y + ", Z = " + z);
    }
}

The usual approach is to represent the cube as a point configuration and a current transformation. 通常的方法是将多维数据集表示为点配置和当前转换。 When rotating, update the transformation but do not update the points themselves. 旋转时,更新转换但不更新点本身。 Only when point coordinates are needed (for rendering, displaying coordinate values, etc.) should the transformation be applied to the points. 只有在需要点坐标时(用于渲染,显示坐标值等),才应将变换应用于点。 The points themselves should never be modified. 这些点本身永远不应该被修改。

This will eliminate the errors that accumulate when many rotations are applied in sequence. 这将消除在按顺序应用多次旋转时累积的误差。 However, it is important that the transformation matrix be maintained as a rotation (determinant 1). 但是,重要的是将变换矩阵保持为旋转(行列式1)。 Otherwise the transformation will still introduce random artifacts (scaling, skewing, or other distortions). 否则,转换仍将引入随机伪像(缩放,偏斜或其他失真)。 Thus, after each rotation is applied, the transformation matrix should be renormalized so that it remains a pure transformation. 因此,在应用每个旋转之后,应该将变换矩阵重新归一化,以使其保持纯粹的变换。 The normalization can be as simple as dividing each entry by the determinant. 归一化可以像将每个条目除以行列式一样简单。

You use x, which is already changed: x = x*Math.cos(dg)-y*Math.sin(dg); 你使用的x已经改变了:x = x * Math.cos(dg)-y * Math.sin(dg);
y = x*Math.sin(dg)+y*Math.cos(dg); y = x * Math.sin(dg)+ y * Math.cos(dg);

it is right variant. 这是正确的变种。 double xx =x; double xx = x; x = x*Math.cos(dg)-y*Math.sin(dg); x = x * Math.cos(dg)-y * Math.sin(dg); y = xx*Math.sin(dg)+y*Math.cos(dg); y = xx * Math.sin(dg)+ y * Math.cos(dg);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM