填充四边形



我有一些代码可以渲染一个立方体,并在按下箭头键时旋转它。

现在我试图填充立方体的一侧,起初效果很好。

但是在我观察了一会儿之后,我注意到,如果我以一定角度旋转立方体,应该填充的表面表现得非常奇怪。

法典:

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);}
}

你的"关键"问题是你的多边形点的顺序......

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点是1265的顺序,但你的y点是12 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);

现在,看看在AWT中绘画和摆动和执行自定义绘画。 强烈建议不要覆盖paint(或update),尤其是在处理顶级容器时。有很多原因,双重缓冲是其中之一,而且,0x0实际上是在帧边框下,这通常是出乎意料的。

请记住,绘画

是为了绘画,在绘制周期中,您永远不应该修改 UI 的状态,并且您永远不应该直接或间接地从绘制方法中调用repaint,当您这样做时,您可能会很快耗尽 CPU,并且您的程序将变得无响应。

如果需要持续检查输入状态并更新 UI,请考虑改用 Swing Timer

默认情况下,Swing 组件是双缓冲的,它也不会像从JFrame扩展那样将您锁定在单一使用中。

您还应该避免使用KeyListener,主要是因为它们在需要键盘焦点时变化无常。通常,键绑定 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();
        }
    }
}

最新更新