在Java中不使用OpenGL绘制立方体的问题求助
Hey there! Let's walk through fixing your Java cube drawing code step by step. The main issues stem from Java's strict type system, differences in how data structures work compared to Lua, and some syntax/typo errors. Here's how to get it working:
Key Issues & Fixes
Use Proper Point Classes Instead of Arrays
In Lua, you can use tables with named fields likex,y,z, but Java arrays don't support that. Create simplePoint3DandPoint2Dclasses to hold coordinates—this will eliminate the "can't find x/y/z" errors.Fix Math Function Typos
Math.cozis a typo; it should beMath.cos. Also, usedoublefor angle calculations sinceMath.sin/Math.cosreturn doubles, avoiding integer precision issues.Correct List/Array Usage
Your parameter types (likeArrayList points[]) are incorrect. Use generic lists (List<Point3D>) to store points, and iterate over them properly with for loops instead of while loops with index decrements.Pass Graphics Context to Cube's Paint Method
YourCube.paint()method needs access to theGraphicsobject from the JPanel to draw lines. Pass it as a parameter when calling the method.Fix Point Initialization
You were callingMake3dPointbut not adding the returned points to yourpointsArray. Initialize the list properly and add each cube vertex to it.Adjust Rotation Math & Coordinate Transformation
Correct the rotation logic to use proper 3D rotation formulas, and ensure the perspective scaling uses floating-point division to avoid distorted results.
Corrected Code
Main Class
package Main; import java.awt.Color; import java.awt.Graphics; import javax.swing.JPanel; import javax.swing.JFrame; public class Main extends JPanel { public static void main(String[] args) { int width = 800; int height = 600; String title = "3D Cube"; JFrame display = new JFrame(title); display.setSize(width, height); display.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); display.setContentPane(new Main()); display.setVisible(true); } public Main() { setBackground(Color.black); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); // Always call this first to clear the panel Cube cube = new Cube(); cube.paint(g); // Pass the Graphics object to the cube's paint method } }
Cube Class
package Main; import java.awt.Color; import java.awt.Graphics; import java.util.ArrayList; import java.util.List; public class Cube { private static class Point3D { double x, y, z; Point3D(double x, double y, double z) { this.x = x; this.y = y; this.z = z; } } private static class Point2D { int x, y; Point2D(int x, int y) { this.x = x; this.y = y; } } private final int focalLength = 300; private final List<Point3D> pointsArray; private Point3D cubeAxisRotation; private final double userX = -0.01; private final double userY = 0.01; public Cube() { // Initialize cube vertices (8 points in 3D space) pointsArray = new ArrayList<>(); pointsArray.add(new Point3D(-50, -50, -50)); pointsArray.add(new Point3D(50, -50, -50)); pointsArray.add(new Point3D(50, -50, 50)); pointsArray.add(new Point3D(-50, -50, 50)); pointsArray.add(new Point3D(-50, 50, -50)); pointsArray.add(new Point3D(50, 50, -50)); pointsArray.add(new Point3D(50, 50, 50)); pointsArray.add(new Point3D(-50, 50, 50)); cubeAxisRotation = new Point3D(0, 0, 0); } private Point2D make2dPoint(double x, double y) { // Offset to center the cube in the window return new Point2D((int) x + 400, (int) y + 300); } private List<Point2D> trans3dTo2d(List<Point3D> points, Point3D rotations) { List<Point2D> transformedPoints = new ArrayList<>(); double cx = Math.cos(rotations.x); double sx = Math.sin(rotations.x); double cy = Math.cos(rotations.y); double sy = Math.sin(rotations.y); double cz = Math.cos(rotations.z); double sz = Math.sin(rotations.z); for (Point3D p : points) { double x = p.x; double y = p.y; double z = p.z; // Rotate around X axis double rotatedY = cx * y - sx * z; double rotatedZ = sx * y + cx * z; // Rotate around Y axis double rotatedX = cy * x + sy * rotatedZ; rotatedZ = -sy * x + cy * rotatedZ; // Rotate around Z axis double finalX = cz * rotatedX - sz * rotatedY; double finalY = sz * rotatedX + cz * rotatedY; // Apply perspective projection double scaleRatio = focalLength / (focalLength + rotatedZ); int screenX = (int) (finalX * scaleRatio); int screenY = (int) (finalY * scaleRatio); transformedPoints.add(make2dPoint(screenX, screenY)); } return transformedPoints; } public void paint(Graphics g) { // Update rotation angles cubeAxisRotation.x += userX; cubeAxisRotation.y += userY; List<Point2D> sp = trans3dTo2d(pointsArray, cubeAxisRotation); // Draw bottom face (green) g.setColor(Color.green); drawLine(g, sp.get(0), sp.get(1)); drawLine(g, sp.get(1), sp.get(2)); drawLine(g, sp.get(2), sp.get(3)); drawLine(g, sp.get(3), sp.get(0)); // Draw top face (red) g.setColor(Color.red); drawLine(g, sp.get(4), sp.get(5)); drawLine(g, sp.get(5), sp.get(6)); drawLine(g, sp.get(6), sp.get(7)); drawLine(g, sp.get(7), sp.get(4)); // Draw front/back vertical lines (white) g.setColor(Color.white); drawLine(g, sp.get(0), sp.get(4)); drawLine(g, sp.get(1), sp.get(5)); // Draw left/right vertical lines (blue) g.setColor(Color.blue); drawLine(g, sp.get(2), sp.get(6)); drawLine(g, sp.get(3), sp.get(7)); } private void drawLine(Graphics g, Point2D p1, Point2D p2) { g.drawLine(p1.x, p1.y, p2.x, p2.y); } }
Explanation of Changes
- Point Classes:
Point3DandPoint2Dmake it easy to access coordinates with.x,.y,.z. - Rotation Math: Corrected the rotation order and formulas to properly apply X, Y, Z rotations.
- Perspective Scaling: Used
doublefor calculations to avoid integer division errors. - List Initialization: Properly added all 8 cube vertices to
pointsArray. - Graphics Context: Passed the
Graphicsobject from the JPanel to the Cube's paint method so it can draw lines. - 0-Indexing: Java lists are 0-indexed, so adjusted all line drawing to use
get(0)instead ofsp[1].
This code should display a rotating 3D cube in a black window. Run the Main class, and you'll see the cube spinning smoothly!
内容的提问来源于stack exchange,提问作者Benzaboy

