2015-06-02 238 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