I am trying to create a 3D game engine. I am using the triangle rasterizing technique so I have a list of lines (that make up triangles) in my CanvasPanel
class and each time that paintComponent()
is called it goes through all the lines and displays them on the screen. The problem is in my main loop, since I want to remove all lines in order to update the scene but when I call it it's being called while the paintComponent()
method is still running so I get a ConcurrentModificationException
. I tried having a loop going that checks if it has finished drawing and only then clear the lines list but for some reason it works only when adding a print statement, otherwise it stops working after a few seconds. What should I do to make sure the timing is right?
Relevant code in Main
:
import javax.swing.*;
import java.awt.*;
public class Main
{
public static int width = 1280, height = 720;
public static void main(String[] args)
{
JFrame window = new JFrame("3D Game");
CanvasPanel canvas = new CanvasPanel(width, height);
window.setLayout(new FlowLayout());
window.getContentPane().add(canvas);
window.pack();
window.setVisible(true);
window.setResizable(false);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Some irrelevant calculations
while (true) // Main loop
{
// Some irrelevant calculations
for (float[][] triangle: cubeMesh)
{
// Here I'm adding lines to the lines list.
}
canvas.repaint(); // update canvas
// My attempt at making sure that clearing the lines list happens only after drawing
while (true)
{
if (!canvas.isDrawing()}
{
// Only works if I print something
break;
}
}
canvas.clearLines(); // here is the problematic line
}
}
}
Relevant code in CanvasPanel
:
public class CanvasPanel extends JPanel
{
BufferedImage canvas;
JLabel label;
private ArrayList<Line> lines;
private boolean drawing;
public CanvasPanel(int width, int height)
{
canvas = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
label = new JLabel(new ImageIcon(canvas));
lines = new ArrayList<>();
add(label);
drawing = false;
}
public boolean isDrawing()
{
return drawing;
}
public void clearLines()
{
lines.clear();
}
@Override
protected void paintComponent(Graphics g)
{
drawing = true;
super.paintComponent(g);
g.setColor(Color.black);
g.fillRect(0, 0, getWidth(), getHeight());
for (Line line: lines)
{
g.setColor(line.color);
g.drawLine(line.x1, line.y1, line.x2, line.y2);
}
drawing = false;
}
public void addLine(int x1, int y1, int x2, int y2, Color color)
{
lines.add(new Line(x1, y1, x2, y2, color));
}