From 637108266597a325800fea0cc0805f695fd03490 Mon Sep 17 00:00:00 2001 From: Quentin Legot Date: Wed, 10 Mar 2021 11:51:06 +0100 Subject: [PATCH] First implementation of L-System in 3D --- src/lsystem/engine/Element.java | 6 +-- src/lsystem/screen/AbstractCanvas.java | 12 ++++-- src/lsystem/screen/gl3d/GLEventListener.java | 41 +++++++++----------- src/lsystem/screen/main/Listener.java | 10 +++-- src/lsystem/screen/main/Tab.java | 15 +++---- 5 files changed, 42 insertions(+), 42 deletions(-) diff --git a/src/lsystem/engine/Element.java b/src/lsystem/engine/Element.java index 8e7c9fe..a1941cf 100644 --- a/src/lsystem/engine/Element.java +++ b/src/lsystem/engine/Element.java @@ -6,17 +6,17 @@ public class Element { public final ElementProperties property; public final Element parent; - public final float[] values; + public final float[] rotation; public final LinkedList children = new LinkedList<>(); public Element(ElementProperties property, Element parent) { this(property, parent, new float[]{0f, 0f, 0f}); } - public Element(ElementProperties property, Element parent, float[] values) { + public Element(ElementProperties property, Element parent, float[] rotation) { this.property = property; this.parent = parent; - this.values = values; + this.rotation = rotation; } } diff --git a/src/lsystem/screen/AbstractCanvas.java b/src/lsystem/screen/AbstractCanvas.java index 6cdf589..0c3917d 100644 --- a/src/lsystem/screen/AbstractCanvas.java +++ b/src/lsystem/screen/AbstractCanvas.java @@ -19,7 +19,7 @@ import java.util.List; public abstract class AbstractCanvas { - private Element lsystem; + private Element lSystem; public State parsedState = State.FINISH_OR_NULL; public JFrame frame; protected FPSAnimator animator; @@ -41,7 +41,7 @@ public abstract class AbstractCanvas { public void windowClosing(WindowEvent e) { frame.dispose(); setVisible(false); - lsystem = null; + lSystem = null; parsedState = State.FINISH_OR_NULL; System.gc(); } @@ -61,9 +61,13 @@ public abstract class AbstractCanvas { frame.setVisible(bl); } - public void setLsystem(String axiom, List> rules, int iterations) { + public Element getLSystem() { + return lSystem; + } + + public void setLSystem(String axiom, List> rules, int iterations) { parsedState = State.LOAD; - this.lsystem = Parser.parse(Rewrite.rewrite(axiom, rules, iterations)); + this.lSystem = Parser.parse(Rewrite.rewrite(axiom, rules, iterations)); parsedState = State.FINISH_OR_NULL; } diff --git a/src/lsystem/screen/gl3d/GLEventListener.java b/src/lsystem/screen/gl3d/GLEventListener.java index e5e0112..6292ab1 100644 --- a/src/lsystem/screen/gl3d/GLEventListener.java +++ b/src/lsystem/screen/gl3d/GLEventListener.java @@ -4,6 +4,7 @@ import com.jogamp.opengl.GL2; import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.glu.GLU; import com.jogamp.opengl.util.gl2.GLUT; +import lsystem.engine.Element; import lsystem.utils.Pair; import java.util.LinkedList; @@ -18,8 +19,6 @@ public class GLEventListener implements com.jogamp.opengl.GLEventListener { private final float[] light_0_position = {1000f, 1000f, 1000f, 1f}; private final float[] material_specular = {0.8f, 0.8f, 0.8f, 0.8f}; - - private float angle = 0f; private final LinkedList> prismPosition = new LinkedList<>(); private final GLU glu; @@ -89,35 +88,33 @@ public class GLEventListener implements com.jogamp.opengl.GLEventListener { gl.glTranslatef(0, 0, 0); DrawHelper.placeCamera(gl, canvas); glu.gluLookAt(canvas.camera[0], canvas.camera[1], canvas.camera[2], canvas.camera[0], canvas.camera[1], canvas.camera[2] - 1, 0f, 1f, 0f); - gl.glPushMatrix(); - gl.glTranslatef(0f, 0f, -4f); - gl.glRotatef(angle, 0f, 1f, 0f); - gl.glColor3f(1.0f, 0.0f, 1.0f); - glut.glutSolidSphere(2f, 20, 20); + gl.glRotatef(90f, -1f, 0f, 0f); + displayLSystem(gl, glut, canvas.getLSystem()); gl.glPopMatrix(); - gl.glPushMatrix(); - gl.glTranslatef(2f, 0.75f, 1.25f); - gl.glRotatef(angle, 0f, 1f, 0f); - gl.glColor3f(0.5f, 0.0f, 1.0f); - glut.glutSolidSphere(0.75f, 20, 20); - gl.glPopMatrix(); - - gl.glPushMatrix(); - gl.glColor3f(1f, 1f, 1f); - DrawHelper.drawRectangularPrism(gl, -3f, 0f, -2f, -2.5f, 1.5f, -1.5f); - glut.glutSolidCylinder(0.25f, 1.5f, 15, 2); - gl.glPopMatrix(); - - angle = (angle + 0.1f) % 360; - DrawHelper.drawAxes(gl, glut); DrawHelper.drawDebugInformation(gl, glut, canvas); gl.glFlush(); fps++; } + private void displayLSystem(GL2 gl, GLUT glut, Element element) { + gl.glPushMatrix(); + gl.glRotatef(element.rotation[0] * 360 , 1f, 0f, 0f); + gl.glRotatef(element.rotation[1] * 360, 0f, 1f, 0f); + gl.glRotatef((element.rotation[0] + element.rotation[1]) * 360, 0f, 0f, 1f); + gl.glTranslated(-Math.sin(element.rotation[0]), -Math.sin(element.rotation[1]), -Math.sin(element.rotation[0] + element.rotation[1])); + gl.glBegin(GL2.GL_LINES); + glut.glutSolidCylinder(0.25f, 1f, 20, 20); + gl.glEnd(); + gl.glTranslatef(0f, 0f, 1f); + for(Element child : element.children) { + displayLSystem(gl, glut, child); + } + gl.glPopMatrix(); + } + @Override public void reshape(GLAutoDrawable glAutoDrawable, int x, int y, int width, int height) { GL2 gl = glAutoDrawable.getGL().getGL2(); diff --git a/src/lsystem/screen/main/Listener.java b/src/lsystem/screen/main/Listener.java index f2edcda..d0b3008 100644 --- a/src/lsystem/screen/main/Listener.java +++ b/src/lsystem/screen/main/Listener.java @@ -17,6 +17,7 @@ public class Listener implements ActionListener, KeyListener { Integer index; String type; Integer nbAxioms; + Thread parserThread = null; public Listener(MainFrame frame, Integer index, String type, Tab tab){ this.tab = tab; @@ -25,6 +26,7 @@ public class Listener implements ActionListener, KeyListener { this.type = type; nbAxioms = 0; } + @Override public void actionPerformed(ActionEvent e) { switch (type) { @@ -51,14 +53,16 @@ public class Listener implements ActionListener, KeyListener { if(Main.joglFrame.frame.isVisible()) { openDialog("Veuillez fermer la fenêtre 3D avant de lancer une nouvelle génération"); } else if(Main.joglFrame.parsedState == AbstractCanvas.State.LOAD) { + openDialog("Une génération est actuellement en cours, impossible d'en relancer un autre"); openDialog("Une génération est actuellement en cours, impossible d'en relancer un autre"); } else if (!parser.isCorrect()) { openDialog("Vos règles ou votre axiome ne sont pas correctement écrites, veuillez recommencer"); } else { - new Thread(() -> { - Main.joglFrame.setLsystem(axiom, parser.parseRules(), tab.getNbIterations()); + parserThread = new Thread(() -> { + Main.joglFrame.setLSystem(axiom, parser.parseRules(), tab.getNbIterations()); Main.joglFrame.setVisible(true); - }).start(); + }); + parserThread.start(); } break; diff --git a/src/lsystem/screen/main/Tab.java b/src/lsystem/screen/main/Tab.java index 2c9f9df..2a5100e 100644 --- a/src/lsystem/screen/main/Tab.java +++ b/src/lsystem/screen/main/Tab.java @@ -2,8 +2,7 @@ package lsystem.screen.main; import javax.swing.*; import java.awt.*; -import java.util.ArrayList; -import java.util.List; +import java.util.Arrays; public class Tab extends JPanel{ @@ -102,12 +101,12 @@ public class Tab extends JPanel{ public JTextField getTextField(byte i){ return (i == 0) ? axiomeField : rulesField; } - public void changeList(String stringToAdd, JTextArea list,int nbAxioms) { - if(nbAxioms>0) + public void changeList(String stringToAdd, JTextArea list, int nbAxioms) { + if(nbAxioms > 0) JOptionPane.showMessageDialog(null, "Nombre maximal d'axiomes créés"); else { list.append(stringToAdd); - if (stringToAdd == ";") + if (stringToAdd.equals(";")) nbAxioms++; } @@ -118,14 +117,10 @@ public class Tab extends JPanel{ return str; } public java.util.List getRules(){ - List list = new ArrayList<>(); String str = rulesList.getText(); str = str.substring(10).replaceAll(";", ""); String[] strsplit = str.split("\n"); - for(int y = 0;y