2015-06-02 239 views
0

我创建了一个简单的应用程序,其目的是在2D平面上显示假想在3D平面上的点(这些点的类型为Vector,写在下面)。该类使用相机的XYZ坐标和矢量的XYZ坐标,并使用该信息快速将矢量XYZ坐标转换为XY坐标。如何在2D平面上投影3D?

这个问题中唯一需要的类是下面给出的Vector类。所有其他使用的类都被省略,因为它们实质上是激发鼠标移动并重新绘制框架。

- 我担心的是,随着相机的移动,矢量点跳转,好像我使用的公式完全不可靠。 these公式(透视投影下的公式)是否完全不正确?这些公式的使用可以在我的set2D方法中找到。我是否在做一些完全错误的事情,跳过步骤,或者我可能会错误地将公式翻译成代码?

谢谢!

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


public class Vector 
{ 
    private int cX, cY, cZ; //Camera Coordinates 
    private int aX, aY, aZ; //Object Coordinates 

    private double bX, bY; //3D to 2D Plane Coordinates 

    public Vector(int aX, int aY, int aZ, int cX, int cY, int cZ) 
    { 
     this.aX = aX; 
     this.aY = aY; 
     this.aZ = aZ; 

     this.cX = cX; 
     this.cY = cY; 
     this.cY = cZ; 

     set2D(); 
    } 

    //SETS 
    public void setCameraX(int cX) 
    { 
     this.cX = cX; 
     set2D(); 
    } 

    public void setCameraY(int cY) 
    { 
     this.cY = cY; 
     set2D(); 
    } 

    public void setCameraZ(int cZ) 
    { 
     this.cZ = cZ; 
     set2D(); 
    } 

    public void setCameraXYZ(int cX, int cY, int cZ) 
    { 
     setCameraX(cX); 
     setCameraY(cY); 
     setCameraZ(cZ); 
    } 

    public void setObjX(int x) 
    { 
     this.aX = x; 
    } 

    public void setObjY(int y) 
    { 
     this.aY = y; 
    } 

    public void setObjZ(int z) 
    { 
     this.aZ = z; 
    } 

    public void setObjXYZ(int x, int y, int z) 
    { 
     this.aX = x; 
     this.aY = y; 
     this.aZ = z; 
    } 

    public void set2D() 
    { 
     //--- 
     //the viewer's position relative to the display surface which goes through point C representing the camera. 
     double eX = aX - cX; 
     double eY = aY - cY; 
     double eZ = aZ - cZ; 
     //---- 

     double cosX = Math.cos(eX); 
     double cosY = Math.cos(eY); 
     double cosZ = Math.cos(eZ); 

     double sinX = Math.sin(eX); 
     double sinY = Math.sin(eY); 
     double sinZ = Math.sin(eZ); 

     //--- 
     //The position of point A with respect to a coordinate system defined by the camera, with origin in C and rotated by Theta with respect to the initial coordinate system. 
     double dX = ((cosY*sinZ*eY) + (cosY*cosZ*eX)) - (sinY * eZ); 
    double dY = ((sinX*cosY*eZ) + (sinX*sinY*sinZ*eY) + (sinX*sinY*cosZ*eX)) + ((cosX*cosZ*eY) - (cosX*sinZ*eX)); 
    double dZ = ((cosX*cosY*eZ) + (cosX*sinY*sinZ*eY) + (cosX*sinY*cosZ*eX)) - ((-sinX*cosZ*eY) - (-sinX*sinZ*eX)); 
     //---   

     //--- 
     //The 2D projection coordinates of the 3D object 
     bX = (int)(((eZ/dZ) * dX) - eX); 
     bY = (int)(((eZ/dZ) * dY) - eY); 
     //--- 

     System.out.println(bX + " " + bY); 
    } 

    //GETS 
    public int getCameraX() 
    { 
     return cX; 
    } 

    public int getCameraY() 
    { 
     return cY; 
    } 

    public int getCameraZ() 
    { 
     return cZ; 
    } 

    public int getObjX() 
    { 
     return aX; 
    } 

    public int getObjY() 
    { 
     return aY; 
    } 

    public int getObjZ() 
    { 
     return aY; 
    } 

    public int get2DX() 
    { 
     return (int)bX; 
    } 

    public int get2DY() 
    { 
     return (int)bY; 
    } 

    //DRAW 
    public void draw(Graphics g) 
    { 
     g.setColor(Color.red); 
     g.fillOval((int)bX, (int)bY, 3, 3); 
    } 

    //TO STRING 
    public String toString() 
    { 
     return (aX + " " + aY + " " + aZ); 
    } 
} 

回答

1

代码以下行不与您正在使用的公式一致:

double dZ = ((cosX*cosY*eZ) + (cosX*sinY*sinZ*eY) + (cosX*sinY*cosZ*eX)) - ((-sinX*cosZ*eY) - (-sinX*sinZ*eX)); 

通知部分- ((-sinX*cosZ*eY) - (-sinX*sinZ*eX))

这应该是- ((sinX*cosZ*eY) - (sinX*sinZ*eX))

,因为如果你拿sinX并乘以它,-ve标志停留在外面。但是,如果您多次使用-sinX,那么括号外的符号应该为+ ve。

+0

谢谢@Akash Pradhan。你的修复纠正了一些不安。但是,当我移动相机(cX,cY,cZ)时,这些点仍然非常奇怪。在同一个Z轴上(即:{20,20,1},{40,20,1},{40,40,1},{20,40,1})创建一个正方形会产生非常奇怪的点坐标返回。即使移动相机点,该形状也很少表示直线。有什么建议么? – Andrew