2016-03-20 184 views
0

我有一些呈現立方體的代碼,並在按下箭頭鍵時將其旋轉。填充四邊形

現在我試圖填充立方體的一面,起初工作得很好。

但是當我觀察到它後,我注意到,如果我以某個角度旋轉立方體,那麼應該填充的表面的行爲非常奇怪。

代碼:

import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Image; 
import java.awt.RenderingHints; 
import java.awt.event.KeyEvent; 
import java.awt.event.KeyListener; 

import javax.swing.JFrame; 

public class Cube extends JFrame { 
double p[][] = new double[9][4]; 

int x=1, y=2, z=3; 

boolean xRotUp = false; 
boolean yRotRight = false; 
boolean xRotDown = false; 
boolean yRotLeft = false; 

double px, py, pz; 

double angle_x = 0.02; 
double angle_y = 0.0150; 
double angle_z = 0.010; 


public Cube() { 
    setSize(500,500); 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    setVisible(true); 

    addKeyListener(new KeyListener() { 

     @Override 
     public void keyTyped(KeyEvent e) { 

     } 

     @Override 
     public void keyReleased(KeyEvent e) { 
      switch (e.getKeyCode()) { 
      case 37: 
       yRotLeft = false; 
       break; 
      case 38: 
       xRotUp = false; 
       break; 
      case 39: 
       yRotRight = false; 
       break; 
      case 40: 
       xRotDown = false; 
       break; 
     } 
     } 

     @Override 
     public void keyPressed(KeyEvent e) { 
      switch (e.getKeyCode()) { 
       case 37: 
        if (!yRotRight) { 
        yRotLeft = true; 
        } else { 
         yRotRight = false; 
        } 
        break; 
       case 38: 
        if (!xRotDown) { 
        xRotUp = true; 
        } else { 
         xRotDown = false; 
        } 
        break; 
       case 39: 
        if (!yRotLeft) { 
        yRotRight = true; 
        } else { 
         yRotLeft = false; 
        } 
        break; 
       case 40: 
        if (!xRotUp) { 
        xRotDown = true; 
        } else { 
         xRotUp = false; 
        } 
        break; 
      } 
     } 
    }); 
} 

public void rotate() { 
    for (int i=0; i<9;i++) { 
     px = p[i][x]; 
     py = p[i][y]; 
     pz = p[i][z]; 
     if (xRotUp) { 
      p[i][y] = py*Math.cos(angle_x)-pz*Math.sin(angle_x); 
      p[i][z] = py*Math.sin(angle_x)+pz*Math.cos(angle_x); 

      py = p[i][y]; 
      pz = p[i][z]; 
     } 

     if (xRotDown) { 
      p[i][y] = py*Math.cos(-angle_x)-pz*Math.sin(-angle_x); 
       p[i][z] = py*Math.sin(-angle_x)+pz*Math.cos(-angle_x); 

       py = p[i][y]; 
       pz = p[i][z]; 
     } 

     if (yRotRight) { 
      p[i][x] = px*Math.cos(angle_y)+pz*Math.sin(angle_y); 
      p[i][z] =-px*Math.sin(angle_y)+pz*Math.cos(angle_y); 

      px = p[i][x]; 
     } 

     if (yRotLeft) { 
      p[i][x] = px*Math.cos(-angle_y)+pz*Math.sin(-angle_y); 
      p[i][z] =-px*Math.sin(-angle_y)+pz*Math.cos(-angle_y); 

      px = p[i][x]; 
     } 
    } 
} 

public void init() { 
    setBackground(new Color(0,0,0)); 

    p[1][x] = -100; p[1][y] = -100; p[1][z] = -100; 
    p[2][x] = +100; p[2][y] = -100; p[2][z] = -100; 
    p[3][x] = +100; p[3][y] = -100; p[3][z] = +100; 
    p[4][x] = -100; p[4][y] = -100; p[4][z] = +100; 
    p[5][x] = -100; p[5][y] = +100; p[5][z] = -100; 
    p[6][x] = +100; p[6][y] = +100; p[6][z] = -100; 
    p[7][x] = +100; p[7][y] = +100; p[7][z] = +100; 
    p[8][x] = -100; p[8][y] = +100; p[8][z] = +100; 

    /*  8 - - - - - 7 
     /|  /| 
      5 - - - - - 6 | 
      | |  | | 
      | 4 - - - -|- 3 
      |/  |/
      1 - - - - - 2 
    */ 
} 

Image buffer; 
Graphics2D gBuffer; 

public void paint(Graphics g) { 
    if (buffer==null) { 
     buffer=createImage(this.getSize().width, this.getSize().height); 
     gBuffer=(Graphics2D)buffer.getGraphics(); 
    } 
    gBuffer.clearRect(0,0,this.getSize().width, this.getSize().height); 

    gBuffer.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 

    gBuffer.setColor(Color.LIGHT_GRAY); 
    gBuffer.drawLine((int)(p[4][x])+200,(int)(p[4][y])+200,(int)(p[6][x])+200,(int)(p[6][y])+200); 
    gBuffer.drawLine((int)(p[2][x])+200,(int)(p[2][y])+200,(int)(p[8][x])+200,(int)(p[8][y])+200); 
    gBuffer.drawLine((int)(p[1][x])+200,(int)(p[1][y])+200,(int)(p[7][x])+200,(int)(p[7][y])+200); 
    gBuffer.drawLine((int)(p[5][x])+200,(int)(p[5][y])+200,(int)(p[3][x])+200,(int)(p[3][y])+200); 

    gBuffer.setColor(Color.DARK_GRAY); 
    gBuffer.fillPolygon(new int[] { 
      (int)p[1][x]+200, 
      (int)p[2][x]+200, 
      (int)p[6][x]+200, 
      (int)p[5][x]+200}, 
       new int[] { 
      (int)p[1][y]+200, 
      (int)p[2][y]+200, 
      (int)p[5][y]+200, 
      (int)p[6][y]+200 
       } , 4); 
    gBuffer.setColor(Color.CYAN); 
    gBuffer.drawLine((int)(p[1][x])+200,(int)(p[1][y])+200,(int)(p[2][x])+200,(int)(p[2][y])+200); 
    gBuffer.drawLine((int)(p[2][x])+200,(int)(p[2][y])+200,(int)(p[3][x])+200,(int)(p[3][y])+200); 
    gBuffer.drawLine((int)(p[3][x])+200,(int)(p[3][y])+200,(int)(p[4][x])+200,(int)(p[4][y])+200); 
    gBuffer.drawLine((int)(p[4][x])+200,(int)(p[4][y])+200,(int)(p[1][x])+200,(int)(p[1][y])+200); 
    gBuffer.drawLine((int)(p[5][x])+200,(int)(p[5][y])+200,(int)(p[6][x])+200,(int)(p[6][y])+200); 
    gBuffer.drawLine((int)(p[6][x])+200,(int)(p[6][y])+200,(int)(p[7][x])+200,(int)(p[7][y])+200); 
    gBuffer.setColor(Color.RED); 
    gBuffer.drawLine((int)(p[7][x])+200,(int)(p[7][y])+200,(int)(p[8][x])+200,(int)(p[8][y])+200); 
    gBuffer.setColor(Color.CYAN); 
    gBuffer.drawLine((int)(p[8][x])+200,(int)(p[8][y])+200,(int)(p[5][x])+200,(int)(p[5][y])+200); 
    gBuffer.drawLine((int)(p[1][x])+200,(int)(p[1][y])+200,(int)(p[5][x])+200,(int)(p[5][y])+200); 
    gBuffer.drawLine((int)(p[2][x])+200,(int)(p[2][y])+200,(int)(p[6][x])+200,(int)(p[6][y])+200); 
    gBuffer.drawLine((int)(p[3][x])+200,(int)(p[3][y])+200,(int)(p[7][x])+200,(int)(p[7][y])+200); 
    gBuffer.setColor(Color.BLUE); 
    gBuffer.drawLine((int)(p[4][x])+200,(int)(p[4][y])+200,(int)(p[8][x])+200,(int)(p[8][y])+200); 

    g.drawImage (buffer, 0, 0, this); 
    try {Thread.sleep(20);} 
    catch (InterruptedException e) {} 



    //for (int i=1;i<9;i++) { 
     // Rotation um z-Achse 

     //p[i][x] = px*Math.cos(angle_z)-py*Math.sin(angle_z); 
     //p[i][y] = py*Math.cos(angle_z)+px*Math.sin(angle_z); 
    // } 

    rotate(); 

    repaint(); 
} 

public void update(Graphics g) {paint(g);} 
} 
+0

你能對你的意思是「行爲怪異」的詳細說明什麼?你期望它看起來像什麼,它實際上是什麼樣子?有很多代碼,更多的細節將幫助人們縮小可能的錯誤。 – paisanco

+0

是的那些多邊形伸出來 - 你想讓我們做你的幾何? – gpasch

+0

@paisanco像_gpasch_已經說過一個多邊形是突出的。有時它也會旋轉並創建多個三角形 – Clyme

回答

1

你 「關鍵」 問題是你的多邊形點的順序...

gBuffer.fillPolygon(new int[]{ 
    (int) p[1][x] + 200, 
    (int) p[2][x] + 200, 
    (int) p[6][x] + 200, 
    (int) p[5][x] + 200}, 
     new int[]{ 
      (int) p[1][y] + 200, 
      (int) p[2][y] + 200, 
      (int) p[5][y] + 200, 
      (int) p[6][y] + 200 
     }, 4); 

你的X點是在1順序,265 ,但是你的y點大小順序爲1,2,5,6,這是不對的

它應該是...

gBuffer.fillPolygon(new int[]{ 
    (int) p[1][x] + 200, 
    (int) p[2][x] + 200, 
    (int) p[6][x] + 200, 
    (int) p[5][x] + 200}, 
     new int[]{ 
      (int) p[1][y] + 200, 
      (int) p[2][y] + 200, 
      (int) p[6][y] + 200, 
      (int) p[5][y] + 200 
     }, 4); 

現在,看看Painting in AWT and SwingPerforming Custom Painting。一般不推薦使用paint(或update),但特別是在處理頂級容器時。有很多原因,雙緩衝是其中之一,而且,0x0實際上是在框架邊界之下,這通常是意外的。請記住,繪畫是用於繪畫的,您不應該在繪畫週期中修改UI的狀態,也不應該直接或間接地從繪畫方法中調用repaint,當您這樣做時,很可能你會最大限度地快速處理你的CPU,你的程序將變得沒有反應。

如果你需要不斷地檢查輸入的狀態並更新UI,可以考慮使用一個Swing Timer代替

Swing組件都是雙默認情況下緩衝,它也不會限制你到像延伸的單次使用從JFrame呢。

你也應該避免使用KeyListener,主要是因爲它們在需要鍵盤焦點時變得反覆無常。一般來說,Key Bindings API將爲您提供一個更強大的API

例如...

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.RenderingHints; 
import java.awt.event.ActionEvent; 
import java.awt.event.KeyEvent; 
import javax.swing.AbstractAction; 
import javax.swing.Action; 
import javax.swing.ActionMap; 
import javax.swing.InputMap; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.KeyStroke; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class Cube extends JPanel { 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Test"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new Cube()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    double p[][] = new double[9][4]; 

    int x = 1, y = 2, z = 3; 

    public enum HorizontalRotation { 
     LEFT, 
     RIGHT, 
     NONE 
    } 
    public enum VerticalRotation { 
     UP, 
     DOWN, 
     NONE 
    } 

    private HorizontalRotation horizontalRotation = HorizontalRotation.NONE; 
    private VerticalRotation verticalRotation = VerticalRotation.NONE; 

// boolean xRotUp = false; 
// boolean yRotRight = false; 
// boolean xRotDown = false; 
// boolean yRotLeft = false; 

    double px, py, pz; 

    double angle_x = 0.02; 
    double angle_y = 0.0150; 
    double angle_z = 0.010; 

    public Cube() { 
     init(); 
     addKeyBinding("Left", KeyEvent.VK_LEFT, HorizontalRotation.LEFT); 
     addKeyBinding("Right", KeyEvent.VK_RIGHT, HorizontalRotation.RIGHT); 
     addKeyBinding("Up", KeyEvent.VK_UP, VerticalRotation.UP); 
     addKeyBinding("Down", KeyEvent.VK_DOWN, VerticalRotation.DOWN); 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(400, 400); 
    } 

    protected void addKeyBinding(String name, int keyCode, HorizontalRotation rotation) { 
     addKeyBinding(name + ".pressed", KeyStroke.getKeyStroke(keyCode, 0, false), new HorizontalRotationAction(rotation)); 
     addKeyBinding(name + ".released", KeyStroke.getKeyStroke(keyCode, 0, true), new HorizontalRotationAction(HorizontalRotation.NONE)); 
    } 

    protected void addKeyBinding(String name, int keyCode, VerticalRotation rotation) { 
     addKeyBinding(name + ".pressed", KeyStroke.getKeyStroke(keyCode, 0, false), new VerticalRotationAction(rotation)); 
     addKeyBinding(name + ".released", KeyStroke.getKeyStroke(keyCode, 0, true), new VerticalRotationAction(VerticalRotation.NONE)); 
    } 

    protected void addKeyBinding(String name, KeyStroke keyStroke, Action action) { 
     InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW); 
     ActionMap am = getActionMap(); 

     im.put(keyStroke, name); 
     am.put(name, action); 
    } 

    public void rotate() { 
     for (int i = 0; i < 9; i++) { 
      px = p[i][x]; 
      py = p[i][y]; 
      pz = p[i][z]; 
      if (verticalRotation == VerticalRotation.UP) { 
       p[i][y] = py * Math.cos(angle_x) - pz * Math.sin(angle_x); 
       p[i][z] = py * Math.sin(angle_x) + pz * Math.cos(angle_x); 

       py = p[i][y]; 
       pz = p[i][z]; 
      } else if (verticalRotation == VerticalRotation.DOWN) { 
       p[i][y] = py * Math.cos(-angle_x) - pz * Math.sin(-angle_x); 
       p[i][z] = py * Math.sin(-angle_x) + pz * Math.cos(-angle_x); 

       py = p[i][y]; 
       pz = p[i][z]; 
      } 

      if (horizontalRotation == HorizontalRotation.RIGHT) { 
       p[i][x] = px * Math.cos(angle_y) + pz * Math.sin(angle_y); 
       p[i][z] = -px * Math.sin(angle_y) + pz * Math.cos(angle_y); 

       px = p[i][x]; 
      } else if (horizontalRotation == HorizontalRotation.LEFT) { 
       p[i][x] = px * Math.cos(-angle_y) + pz * Math.sin(-angle_y); 
       p[i][z] = -px * Math.sin(-angle_y) + pz * Math.cos(-angle_y); 

       px = p[i][x]; 
      } 
     } 
     repaint(); 
    } 

    public void init() { 
     setBackground(new Color(0, 0, 0)); 

     p[1][x] = -100; 
     p[1][y] = -100; 
     p[1][z] = -100; 
     p[2][x] = +100; 
     p[2][y] = -100; 
     p[2][z] = -100; 
     p[3][x] = +100; 
     p[3][y] = -100; 
     p[3][z] = +100; 
     p[4][x] = -100; 
     p[4][y] = -100; 
     p[4][z] = +100; 
     p[5][x] = -100; 
     p[5][y] = +100; 
     p[5][z] = -100; 
     p[6][x] = +100; 
     p[6][y] = +100; 
     p[6][z] = -100; 
     p[7][x] = +100; 
     p[7][y] = +100; 
     p[7][z] = +100; 
     p[8][x] = -100; 
     p[8][y] = +100; 
     p[8][z] = +100; 

     /*  8 - - - - - 7 
        /|  /| 
        5 - - - - - 6 | 
        | |  | | 
        | 4 - - - -|- 3 
        |/  |/
        1 - - - - - 2 
     */ 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D gBuffer = (Graphics2D) g.create(); 

     gBuffer.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 

     gBuffer.setColor(Color.LIGHT_GRAY); 
     gBuffer.drawLine((int) (p[4][x]) + 200, (int) (p[4][y]) + 200, (int) (p[6][x]) + 200, (int) (p[6][y]) + 200); 
     gBuffer.drawLine((int) (p[2][x]) + 200, (int) (p[2][y]) + 200, (int) (p[8][x]) + 200, (int) (p[8][y]) + 200); 
     gBuffer.drawLine((int) (p[1][x]) + 200, (int) (p[1][y]) + 200, (int) (p[7][x]) + 200, (int) (p[7][y]) + 200); 
     gBuffer.drawLine((int) (p[5][x]) + 200, (int) (p[5][y]) + 200, (int) (p[3][x]) + 200, (int) (p[3][y]) + 200); 

     gBuffer.setColor(Color.DARK_GRAY); 
     gBuffer.fillPolygon(new int[]{ 
      (int) p[1][x] + 200, 
      (int) p[2][x] + 200, 
      (int) p[6][x] + 200, 
      (int) p[5][x] + 200}, 
       new int[]{ 
        (int) p[1][y] + 200, 
        (int) p[2][y] + 200, 
        (int) p[6][y] + 200, 
        (int) p[5][y] + 200 
       }, 4); 
     gBuffer.setColor(Color.CYAN); 
     gBuffer.drawLine((int) (p[1][x]) + 200, (int) (p[1][y]) + 200, (int) (p[2][x]) + 200, (int) (p[2][y]) + 200); 
     gBuffer.drawLine((int) (p[2][x]) + 200, (int) (p[2][y]) + 200, (int) (p[3][x]) + 200, (int) (p[3][y]) + 200); 
     gBuffer.drawLine((int) (p[3][x]) + 200, (int) (p[3][y]) + 200, (int) (p[4][x]) + 200, (int) (p[4][y]) + 200); 
     gBuffer.drawLine((int) (p[4][x]) + 200, (int) (p[4][y]) + 200, (int) (p[1][x]) + 200, (int) (p[1][y]) + 200); 
     gBuffer.drawLine((int) (p[5][x]) + 200, (int) (p[5][y]) + 200, (int) (p[6][x]) + 200, (int) (p[6][y]) + 200); 
     gBuffer.drawLine((int) (p[6][x]) + 200, (int) (p[6][y]) + 200, (int) (p[7][x]) + 200, (int) (p[7][y]) + 200); 
     gBuffer.setColor(Color.RED); 
     gBuffer.drawLine((int) (p[7][x]) + 200, (int) (p[7][y]) + 200, (int) (p[8][x]) + 200, (int) (p[8][y]) + 200); 
     gBuffer.setColor(Color.CYAN); 
     gBuffer.drawLine((int) (p[8][x]) + 200, (int) (p[8][y]) + 200, (int) (p[5][x]) + 200, (int) (p[5][y]) + 200); 
     gBuffer.drawLine((int) (p[1][x]) + 200, (int) (p[1][y]) + 200, (int) (p[5][x]) + 200, (int) (p[5][y]) + 200); 
     gBuffer.drawLine((int) (p[2][x]) + 200, (int) (p[2][y]) + 200, (int) (p[6][x]) + 200, (int) (p[6][y]) + 200); 
     gBuffer.drawLine((int) (p[3][x]) + 200, (int) (p[3][y]) + 200, (int) (p[7][x]) + 200, (int) (p[7][y]) + 200); 
     gBuffer.setColor(Color.BLUE); 
     gBuffer.drawLine((int) (p[4][x]) + 200, (int) (p[4][y]) + 200, (int) (p[8][x]) + 200, (int) (p[8][y]) + 200); 
     gBuffer.dispose(); 
    } 

    protected class HorizontalRotationAction extends AbstractAction { 

     private HorizontalRotation rotation; 

     public HorizontalRotationAction(HorizontalRotation rotation) { 
      this.rotation = rotation; 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      horizontalRotation = rotation; 
      rotate(); 
     } 

    } 

    protected class VerticalRotationAction extends AbstractAction { 

     private VerticalRotation rotation; 

     public VerticalRotationAction(VerticalRotation rotation) { 
      this.rotation = rotation; 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      verticalRotation = rotation; 
      rotate(); 
     } 

    } 

} 
+0

非常感謝:D有趣的是,一個亂七八糟的數字可以改變程序的整個功能。 – Clyme