Я попросил AI исправить его, но они не смогли найти проблему.
Другая проблема заключается в том, что добавленное тело не появляется, где мышь и получает ускорение.
Код: Выделить всё
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;
import javax.swing.*;
public class NBodySimulator3D extends JFrame {
private static final long serialVersionUID = 1L;
private SimulationPanel simulationPanel;
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
NBodySimulator3D sim = new NBodySimulator3D();
sim.setVisible(true);
});
}
public NBodySimulator3D() {
setTitle("N-Body Simulator 3D");
setSize(1200, 800);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout());
simulationPanel = new SimulationPanel(); // {
SimulationPanel.Body b = simulationPanel.getSelectedBody();
if (b != null) {
massField.setText(String.format("%.4f", b.mass));
posX.setText(String.format("%.4f", b.position.x));
posY.setText(String.format("%.4f", b.position.y));
posZ.setText(String.format("%.4f", b.position.z));
velX.setText(String.format("%.4f", b.velocity.x));
velY.setText(String.format("%.4f", b.velocity.y));
velZ.setText(String.format("%.4f", b.velocity.z));
}
});
editorUpdateTimer.start();
// Update bei Button-Klick
updateButton.addActionListener(ev -> {
SimulationPanel.Body b = simulationPanel.getSelectedBody();
if (b != null) {
try {
double m = Double.parseDouble(massField.getText());
double px = Double.parseDouble(posX.getText());
double py = Double.parseDouble(posY.getText());
double pz = Double.parseDouble(posZ.getText());
double vx = Double.parseDouble(velX.getText());
double vy = Double.parseDouble(velY.getText());
double vz = Double.parseDouble(velZ.getText());
b.mass = m;
b.radius = Math.cbrt(m) * 0.5;
b.position = new SimulationPanel.Vector3(px, py, pz);
b.velocity = new SimulationPanel.Vector3(vx, vy, vz);
} catch (NumberFormatException ignored) {
}
}
});
timeWarpSlider.addChangeListener(e -> simulationPanel.setTimeWarp(timeWarpSlider.getValue() / 10.0));
pauseButton.addActionListener(e -> {
simulationPanel.togglePause();
pauseButton.setText(simulationPanel.isPaused() ? "Play" : "Pause");
});
}
static class SimulationPanel extends JPanel implements ActionListener, MouseListener, MouseMotionListener, KeyListener {
private static final long serialVersionUID = 2L;
private final javax.swing.Timer timer = new javax.swing.Timer(16, this);
private final List bodies = Collections.synchronizedList(new ArrayList());
private Body selectedBody = null;
private Vector3 cameraPosition = new Vector3(0, 0, 50);
private double cameraYaw = 0;
private double cameraPitch = 0;
private boolean paused = false;
private double timeWarp = 1.0;
private Point dragStartPoint = null;
private Vector3 dragStartWorld = null;
private boolean draggingVelocity = false;
private final long trailDuration = 10_000;
private final Set pressedKeys = new HashSet();
public SimulationPanel() {
setBackground(Color.BLACK);
setFocusable(true);
SwingUtilities.invokeLater(() -> requestFocusInWindow());
requestFocusInWindow(); // 0) continue;
double e = 1.0;
double velNorm = -(1 + e) * velAlongNormal;
velNorm /= (1 / a.mass) + (1 / b.mass);
Vector3 impulse = normal.multiply(velNorm);
a.velocity = a.velocity.subtract(impulse.multiply(1 / a.mass));
b.velocity = b.velocity.add(impulse.multiply(1 / b.mass));
double overlap = minDist - dist;
a.position = a.position.subtract(normal.multiply(overlap * (b.mass / (a.mass + b.mass))));
b.position = b.position.add(normal.multiply(overlap * (a.mass / (a.mass + b.mass))));
}
}
}
}
}
private void updatePositions(double dt) {
synchronized (bodies) {
for (Body b : bodies) {
Vector3 accel = b.force.multiply(1.0 / b.mass);
b.velocity = b.velocity.add(accel.multiply(dt));
b.position = b.position.add(b.velocity.multiply(dt));
}
}
}
private void moveCamera() {
double speed = 0.8 * timeWarp;
Vector3 forward = getCameraForward();
Vector3 right = getCameraRight();
Vector3 up = new Vector3(0, 1, 0);
if (pressedKeys.contains(KeyEvent.VK_W)) cameraPosition = cameraPosition.add(forward.multiply(speed));
if (pressedKeys.contains(KeyEvent.VK_S)) cameraPosition = cameraPosition.subtract(forward.multiply(speed));
if (pressedKeys.contains(KeyEvent.VK_A)) cameraPosition = cameraPosition.subtract(right.multiply(speed));
if (pressedKeys.contains(KeyEvent.VK_D)) cameraPosition = cameraPosition.add(right.multiply(speed));
if (pressedKeys.contains(KeyEvent.VK_SHIFT)) cameraPosition = cameraPosition.add(up.multiply(speed));
if (pressedKeys.contains(KeyEvent.VK_CONTROL)) cameraPosition = cameraPosition.subtract(up.multiply(speed));
}
private Vector3 getCameraForward() {
double cosPitch = Math.cos(cameraPitch);
double sinPitch = Math.sin(cameraPitch);
double cosYaw = Math.cos(cameraYaw);
double sinYaw = Math.sin(cameraYaw);
return new Vector3(cosPitch * sinYaw, sinPitch, cosPitch * cosYaw).normalize();
}
private Vector3 getCameraRight() {
return getCameraForward().cross(new Vector3(0, 1, 0)).normalize();
}
private Vector3 getCameraUp() {
return getCameraRight().cross(getCameraForward()).normalize();
}
private Point lastMouse;
private boolean rotating = false;
@Override
public void mousePressed(MouseEvent e) {
requestFocusInWindow();
if (SwingUtilities.isLeftMouseButton(e)) {
dragStartPoint = e.getPoint();
dragStartWorld = screenToWorld(e.getX(), e.getY());
draggingVelocity = false;
} else if (SwingUtilities.isRightMouseButton(e)) {
lastMouse = e.getPoint();
rotating = true;
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e) && dragStartPoint != null) {
Point dragEnd = e.getPoint();
Vector3 dragEndWorld = screenToWorld(dragEnd.x, dragEnd.y);
Vector3 velocity = dragEndWorld.subtract(dragStartWorld).multiply(0.5);
String massStr = JOptionPane.showInputDialog(this, "Masse des Körpers:", "100");
if (massStr != null) {
try {
double mass = Double.parseDouble(massStr);
Body newBody = new Body(dragStartWorld, velocity, mass);
synchronized (bodies) {
bodies.add(newBody);
}
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(this, "Ungültige Eingabe für Masse.");
}
}
dragStartPoint = null;
dragStartWorld = null;
draggingVelocity = false;
} else if (SwingUtilities.isRightMouseButton(e)) {
rotating = false;
}
}
@Override
public void mouseDragged(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e) && rotating) {
int dx = e.getX() - lastMouse.x;
int dy = e.getY() - lastMouse.y;
cameraYaw += dx * 0.01;
cameraPitch -= dy * 0.01;
cameraPitch = Math.max(-Math.PI / 2 + 0.01, Math.min(Math.PI / 2 - 0.01, cameraPitch));
lastMouse = e.getPoint();
}
}
@Override
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
Vector3 world = screenToWorld(e.getX(), e.getY());
Body found = findBodyNear(world, e.getPoint());
selectedBody = found;
if (found != null) {
selectedBody = found;
} else {
selectedBody = null;
}
repaint();
}
}
private Body findBodyNear(Vector3 pos, Point screenPoint) {
System.out.println("findBodyNear aufgerufen mit screenPoint: " + screenPoint);
synchronized (bodies) {
for (Body b : bodies) {
Point p = projectToScreen(b.position);
System.out.println("Body screen pos: " + p + ", Maus: " + screenPoint + ", Abstand: " + p.distance(screenPoint));
if (p.distance(screenPoint) < 15) {
return b;
}
}
}
return null;
}
private Vector3 screenToWorld(int x, int y) {
// Ray von Kamera in Richtung Mausposition
double aspectRatio = (double) getWidth() / getHeight();
double scale = 1.0; // oder passe das an für Zoom/FOV
double screenX = ((x - getWidth() / 2.0) / (getWidth() / 2.0)) * aspectRatio * scale;
double screenY = -((y - getHeight() / 2.0) / (getHeight() / 2.0)) * scale;
Vector3 forward = getCameraForward();
Vector3 right = getCameraRight();
Vector3 up = getCameraUp();
Vector3 rayDir = forward
.add(right.multiply(screenX))
.add(up.multiply(screenY))
.normalize();
Vector3 origin = cameraPosition;
// Strahl-Schnitt mit der Z=0-Ebene (XY-Ebene)
double t = -origin.z / rayDir.z;
if (Double.isNaN(t) || Double.isInfinite(t) || t < 0) {
return origin; // Keine sinnvolle Schnittstelle → fallback
}
return origin.add(rayDir.multiply(t));
}
@Override public void mouseMoved(MouseEvent e) {}
@Override public void mouseEntered(MouseEvent e) {}
@Override public void mouseExited(MouseEvent e) {}
@Override public void keyPressed(KeyEvent e) { pressedKeys.add(e.getKeyCode()); }
@Override public void keyReleased(KeyEvent e) { pressedKeys.remove(e.getKeyCode()); }
@Override public void keyTyped(KeyEvent e) {}
static class Body {
Vector3 position, velocity, force;
double mass, radius;
Deque trail = new ArrayDeque();
Body(Vector3 pos, Vector3 vel, double m) {
this.position = pos;
this.velocity = vel;
this.mass = m;
this.radius = Math.cbrt(m) * 0.5;
this.force = new Vector3(0, 0, 0);
}
}
static class Vector3 {
double x, y, z;
Vector3(double x, double y, double z) { this.x = x; this.y = y; this.z = z; }
Vector3 add(Vector3 o) { return new Vector3(x + o.x, y + o.y, z + o.z); }
Vector3 subtract(Vector3 o) { return new Vector3(x - o.x, y - o.y, z - o.z); }
Vector3 multiply(double scalar) { return new Vector3(x * scalar, y * scalar, z * scalar); }
double dot(Vector3 o) { return x * o.x + y * o.y + z * o.z; }
Vector3 cross(Vector3 o) {
return new Vector3(
y * o.z - z * o.y,
z * o.x - x * o.z,
x * o.y - y * o.x
);
}
double length() { return Math.sqrt(x * x + y * y + z * z); }
Vector3 normalize() {
double len = length();
return len == 0 ? new Vector3(0, 0, 0) : multiply(1 / len);
}
}
static class TrailPoint {
Vector3 position;
long time;
TrailPoint(Vector3 p, long t) {
this.position = p;
this.time = t;
}
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/796 ... -work-java