<repository>
<id>svjatoslav.eu</id>
<name>Svjatoslav repository</name>
- <url>https://www2.svjatoslav.eu/maven/</url>
+ <url>https://www3.svjatoslav.eu/maven/</url>
</repository>
</repositories>
private static final double WAVE_FREQUENCY = 50d;
private static final double WAVE_AMPLITUDE = 50d;
private static final Color SQUARE_PLATE_COLOR = new Color("88F7");
+ private static final double GRAPH_SCALE = 50d;
private static void makeSquarePlate(final ShapeCollection shapeCollection,
final double y, final double x, final double z) {
}
}
- private static final double scale = 50d;
-
private static Graph getCosineGraph(final Point3D location) {
final List<Point2D> data = new ArrayList<>();
for (double x = 0; x < 20; x += 0.25) {
data.add(p);
}
- return new Graph(scale, data, "Cosine", location);
+ return new Graph(GRAPH_SCALE, data, "Cosine", location);
}
private static Graph getFormula1Graph(final Point3D location) {
data.add(p);
}
- return new Graph(scale, data, "y = sin(tan(x))", location);
+ return new Graph(GRAPH_SCALE, data, "y = sin(tan(x))", location);
}
private static Graph getFormula2Graph(final Point3D location) {
data.add(p);
}
- return new Graph(scale, data, "y = ( (10-x)^2 ) / 30", location);
+ return new Graph(GRAPH_SCALE, data, "y = ( (10-x)^2 ) / 30", location);
}
private static Graph getFormula3Graph(final Point3D location) {
data.add(p);
}
- return new Graph(scale, data, "y = sin(x/2) + sin(x/1.26)", location);
+ return new Graph(GRAPH_SCALE, data, "y = sin(x/2) + sin(x/1.26)", location);
}
private static Graph getSineGraph(final Point3D location) {
data.add(p);
}
- return new Graph(scale, data, "Sine", location);
+ return new Graph(GRAPH_SCALE, data, "Sine", location);
}
private static Graph getTangentGraph(final Point3D location) {
data.add(p);
}
- return new Graph(scale, data, "Tangent", location);
+ return new Graph(GRAPH_SCALE, data, "Tangent", location);
}
public static void main(final String[] args) {
import eu.svjatoslav.sixth.e3d.gui.ViewPanel;
import eu.svjatoslav.sixth.e3d.gui.humaninput.WorldNavigationUserInputTracker;
import eu.svjatoslav.sixth.e3d.math.Transform;
+import eu.svjatoslav.sixth.e3d.renderer.octree.IntegerPoint;
import eu.svjatoslav.sixth.e3d.renderer.octree.OctreeVolume;
import eu.svjatoslav.sixth.e3d.renderer.octree.raytracer.Camera;
import eu.svjatoslav.sixth.e3d.renderer.octree.raytracer.LightSource;
final double c2 = (Math.cos(x / 10f) * 100f) + 127;
final double c3 = (Math.cos(z / 12f) * 100f) + 127;
- putRect(x - size, y - size, z - size, x + size, y + size, z + size,
+ putRect(
+ new IntegerPoint( x - size, y - size, z - size),
+ new IntegerPoint( x + size, y + size, z + size),
new Color((int) c1, (int) c2, (int) c3, 100));
if (size > 1) {
dotSpiral();
// arbitrary rectangles
- putRect(-10, -10, -10, 10, 10, -20, new Color(200, 255, 200, 100));
- putRect(-3, 0, -30, 12, 3, 300, new Color(255, 200, 200, 100));
- putRect(-20, 20, -20, 20, 80, 20, new Color(255, 200, 255, 100));
+ putRect(new IntegerPoint(-10, -10, -10),
+ new IntegerPoint(10, 10, -20),
+ new Color(200, 255, 200, 100));
+
+ putRect(new IntegerPoint(-3, 0, -30),
+ new IntegerPoint( 12, 3, 300),
+ new Color(255, 200, 200, 100));
+
+ putRect(new IntegerPoint(-20, 20, -20),
+ new IntegerPoint(20, 80, 20),
+ new Color(255, 200, 255, 100));
tiledFloor();
fractal(-50, 20, 100, 32, 1);
final TextCanvas message = new TextCanvas(new Transform(new Point3D(
- -10, 20, -180)), "Press \"r\" to raytrace current wiew",
+ -10, 20, -180)), "Press \"r\" to raytrace current view",
Color.WHITE, Color.PURPLE);
shapeCollection.addShape(message);
}
- private void putRect(final int x1, final int y1, final int z1, final int x2,
- final int y2, final int z2, final Color color) {
+ private void putRect(IntegerPoint p1, IntegerPoint p2, final Color color) {
shapeCollection
.addShape(new SolidPolygonRectangularBox(
- new Point3D(x1, y1, z1).scaleUp(magnification),
- new Point3D(x2, y2, z2).scaleUp(magnification), color));
+ new Point3D(p1).scaleUp(magnification),
+ new Point3D(p2).scaleUp(magnification), color));
- octreeVolume.fillRect3D(x1, y1, z1, x2, y2, z2, color);
+ octreeVolume.fillRectangle(p1, p2, color);
}
private void raytrace() {
private void tiledFloor() {
final int step = 40;
final int size = step - 15;
+ Color color = new Color(255, 255, 255, 100);
for (int x = -200; x < 200; x += step)
for (int z = -200; z < 200; z += step)
- putRect(x, 100, z, x + size, 110, z + size, new Color(255, 255,
- 255, 100));
+ putRect(
+ new IntegerPoint(x, 100, z),
+ new IntegerPoint(x + size, 110, z + size),
+ color);
}
}
+++ /dev/null
-/*
- * Sixth 3D engine demos. Author: Svjatoslav Agejenko.
- * This project is released under Creative Commons Zero (CC0) license.
- *
-*/
-
-package eu.svjatoslav.sixth.e3d.examples;
-
-import eu.svjatoslav.sixth.e3d.geometry.Point3D;
-import eu.svjatoslav.sixth.e3d.gui.ViewFrame;
-import eu.svjatoslav.sixth.e3d.math.Transform;
-import eu.svjatoslav.sixth.e3d.renderer.raster.ShapeCollection;
-import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.Galaxy;
-
-public class PointCloudDemo {
-
- public static void main(final String[] args) {
-
- final ViewFrame viewFrame = new ViewFrame();
-
- final ShapeCollection geometryCollection = viewFrame.getViewPanel()
- .getRootShapeCollection();
-
- Transform transform = new Transform(new Point3D(0, -1000, 1000), 0, 0);
-
- // add galaxy
- geometryCollection.addShape(new Galaxy(500, 3, 10000, transform));
-
- }
-}
--- /dev/null
+/*
+ * Sixth 3D engine. Author: Svjatoslav Agejenko.
+ * This project is released under Creative Commons Zero (CC0) license.
+ */
+package eu.svjatoslav.sixth.e3d.examples.galaxy_demo;
+
+import eu.svjatoslav.sixth.e3d.geometry.Point3D;
+import eu.svjatoslav.sixth.e3d.math.Transform;
+import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.GlowingPoint;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.base.AbstractCompositeShape;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import static java.lang.Math.*;
+
+public class Galaxy extends AbstractCompositeShape {
+
+ /**
+ * The number of unique colors used in the galaxy.
+ */
+ public static final int UNIQUE_COLORS_COUNT = 30;
+
+ /**
+ * A list of all colors used in the galaxy.
+ * Used to reuse textures of glowing points of the same color.
+ */
+ private static List<Color> colors;
+
+ public Galaxy(final int galaxySize, final int tailCount, final int starsCount,
+ Transform transform) {
+
+ super(transform);
+
+ ensureColorsAreInitialized();
+
+ final double angle1 = random() * 10;
+ final double angle2 = random() * 10;
+
+ final double angleSin1 = sin(angle1);
+ final double angleCos1 = cos(angle1);
+ final double angleSin2 = sin(angle2);
+ final double angleCos2 = cos(angle2);
+
+ Random random = new Random();
+
+ double starSize = galaxySize / 70d;
+
+ for (int i = 1; i < starsCount; i++) {
+ final double b = random() * 10;
+
+ final double s = (b * b) / 30;
+
+ final double v1 = (random() * (11.5 - b)) / 3;
+ final double v1p = v1 / 2;
+
+ final double ane = ((random() * (s / 2)) / tailCount) * 2;
+ final double sba = ((2 * PI) / tailCount)
+ * random.nextInt(tailCount);
+
+ final double x = (((sin((b - sba) + ane) * s) + (random() * v1)) - v1p) * galaxySize;
+ final double z = (((cos((b - sba) + ane) * s) + (random() * v1)) - v1p) * galaxySize;
+ final double y = ((random() * v1) - v1p) * galaxySize;
+
+ final double x1 = (x * angleCos1) + (z * angleSin1);
+ final double z1 = (z * angleCos1) - (x * angleSin1);
+
+ final double y1 = (y * angleCos2) + (z1 * angleSin2);
+ final double z2 = (z1 * angleCos2) - (y * angleSin2);
+
+ addStar(new Point3D(x1, y1, z2), starSize);
+ }
+ }
+
+ private void addStar(final Point3D starLocation, double size) {
+ addShape(new GlowingPoint(starLocation, size, colors.get((int) (random() * colors.size()))));
+ }
+
+ /**
+ * Initializes the list of colors used in the galaxy.
+ * Used to reuse textures of glowing points of the same color.
+ */
+ private synchronized void ensureColorsAreInitialized() {
+ if (colors != null) return;
+
+ colors = new ArrayList<>();
+
+ for (int i = 0; i < UNIQUE_COLORS_COUNT; i++)
+ colors.add(
+ new Color(
+ random() + 0.5,
+ random() + 0.5,
+ random() + 0.5,
+ 255));
+ }
+
+}
--- /dev/null
+/*
+ * Sixth 3D engine demos. Author: Svjatoslav Agejenko.
+ * This project is released under Creative Commons Zero (CC0) license.
+ *
+*/
+
+package eu.svjatoslav.sixth.e3d.examples.galaxy_demo;
+
+import eu.svjatoslav.sixth.e3d.geometry.Point3D;
+import eu.svjatoslav.sixth.e3d.gui.ViewFrame;
+import eu.svjatoslav.sixth.e3d.math.Transform;
+import eu.svjatoslav.sixth.e3d.renderer.raster.ShapeCollection;
+
+public class PointCloudDemo {
+
+ public static void main(final String[] args) {
+
+ final ViewFrame viewFrame = new ViewFrame();
+
+ final ShapeCollection geometryCollection = viewFrame.getViewPanel()
+ .getRootShapeCollection();
+
+ Transform transform = new Transform(new Point3D(0, -1000, 1000), 0, 0);
+
+ // add galaxy
+ geometryCollection.addShape(new Galaxy(500, 3, 10000, transform));
+
+ }
+}
--- /dev/null
+/*
+ * Sixth 3D engine demos. Author: Svjatoslav Agejenko.
+ * This project is released under Creative Commons Zero (CC0) license.
+ *
+*/
+
+package eu.svjatoslav.sixth.e3d.examples.launcher;
+
+import eu.svjatoslav.sixth.e3d.examples.*;
+import eu.svjatoslav.sixth.e3d.examples.galaxy_demo.PointCloudDemo;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+
+class ApplicationListPanel extends JPanel {
+ private static final long serialVersionUID = 2012721856427052560L;
+
+ ApplicationListPanel() {
+ final GroupLayout groupLayout = new GroupLayout(this);
+ GroupLayout.SequentialGroup sequentialGroup = groupLayout.createSequentialGroup();
+ sequentialGroup.addComponent(new JLabel("Choose an example to launch:"));
+ sequentialGroup.addComponent(new JButton(new ShowOctree()));
+ sequentialGroup.addComponent(new JButton(new ShowMathGraphs()));
+ sequentialGroup.addComponent(new JButton(new ShowPointCloud()));
+ sequentialGroup.addComponent(new JButton(new ShowRain()));
+ sequentialGroup.addComponent(new JButton(new ShowTextEditors()));
+ sequentialGroup.addComponent(new JButton(new ShowTextEditors2()));
+ sequentialGroup.addComponent(new JButton(new ShowGameOfLife()));
+ sequentialGroup.addComponent(new JButton(new ShowRandomPolygons()));
+ }
+
+ private static class ShowTextEditors extends AbstractAction {
+ ShowTextEditors() {
+ putValue(NAME, "Text editors");
+ }
+
+ @Override
+ public void actionPerformed(final ActionEvent e) {
+ TextEditorDemo.main(null);
+ }
+ }
+
+ private static class ShowTextEditors2 extends AbstractAction {
+ ShowTextEditors2() {
+ putValue(NAME, "Text editors city");
+ }
+
+ @Override
+ public void actionPerformed(final ActionEvent e) {
+ TextEditorDemo2.main(null);
+ }
+ }
+
+
+ private static class ShowRain extends AbstractAction {
+ ShowRain() {
+ putValue(NAME, "Raining numbers");
+ }
+
+ @Override
+ public void actionPerformed(final ActionEvent e) {
+ RainingNumbersDemo.main(null);
+ }
+ }
+
+ private static class ShowPointCloud extends AbstractAction {
+ ShowPointCloud() {
+ putValue(NAME, "Point cloud galaxy");
+ }
+
+ @Override
+ public void actionPerformed(final ActionEvent e) {
+ PointCloudDemo.main(null);
+ }
+ }
+
+ private static class ShowMathGraphs extends AbstractAction {
+ ShowMathGraphs() {
+ putValue(NAME, "Mathematical graphs");
+ }
+
+ @Override
+ public void actionPerformed(final ActionEvent e) {
+ GraphDemo.main(null);
+ }
+ }
+
+ private static class ShowRandomPolygons extends AbstractAction {
+ ShowRandomPolygons() {
+ putValue(NAME, "Random polygons");
+ }
+
+ @Override
+ public void actionPerformed(final ActionEvent e) {
+ RandomPolygonsDemo.main(null);
+ }
+ }
+
+ private static class ShowOctree extends AbstractAction {
+ ShowOctree() {
+ putValue(NAME, "Volumetric Octree");
+ }
+
+ @Override
+ public void actionPerformed(final ActionEvent e) {
+ OctreeDemo.main(null);
+ }
+ }
+
+ private static class ShowGameOfLife extends AbstractAction {
+ ShowGameOfLife() {
+ putValue(NAME, "Game of Life");
+ }
+
+ @Override
+ public void actionPerformed(final ActionEvent e) {
+ eu.svjatoslav.sixth.e3d.examples.life_demo.Main.main(null);
+ }
+ }
+
+}
import javax.swing.*;
import java.awt.*;
-class Main extends javax.swing.JFrame {
+import static java.awt.BorderLayout.CENTER;
+import static javax.swing.WindowConstants.DISPOSE_ON_CLOSE;
- private static final long serialVersionUID = -3679656169594556137L;
- private Main() {
- super();
- initGUI();
- }
+class Main {
public static void main(final String[] args) {
- SwingUtilities.invokeLater(() -> {
- final Main inst = new Main();
- final BorderLayout instLayout = new BorderLayout();
- inst.setLocationRelativeTo(null);
- inst.setVisible(true);
- inst.getContentPane().setLayout(instLayout);
- });
+ buildAndShowGuiWindow();
}
- private void initGUI() {
- getContentPane().add(new MenuPanel());
- pack();
- setSize(390, 300);
+ /**
+ * Builds and shows the main window of the application.
+ */
+ private static void buildAndShowGuiWindow() {
+ JFrame frame = new JFrame("Sixth 3D engine demos");
+
+ // Keep application running until last frame is closed.
+ frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
+
+ frame.getContentPane().setLayout(new BorderLayout());
+ frame.getContentPane().add(new ApplicationListPanel(), CENTER);
+ frame.setSize(400, 300);
+
+ frame.setLocationRelativeTo(null); // center frame on screen
+ frame.setVisible(true);
}
}
+++ /dev/null
-/*
- * Sixth 3D engine demos. Author: Svjatoslav Agejenko.
- * This project is released under Creative Commons Zero (CC0) license.
- *
-*/
-
-package eu.svjatoslav.sixth.e3d.examples.launcher;
-
-import eu.svjatoslav.sixth.e3d.examples.*;
-
-import javax.swing.*;
-import java.awt.event.ActionEvent;
-
-class MenuPanel extends JPanel {
- private static final long serialVersionUID = 2012721856427052560L;
-
- MenuPanel() {
- final GroupLayout groupLayout = new GroupLayout(this);
- GroupLayout.SequentialGroup sequentialGroup = groupLayout.createSequentialGroup();
- sequentialGroup.addComponent(new JLabel("Choose an example to launch:"));
- sequentialGroup.addComponent(new JButton(new ShowOctree()));
- sequentialGroup.addComponent(new JButton(new ShowMathGraphs()));
- sequentialGroup.addComponent(new JButton(new ShowPointCloud()));
- sequentialGroup.addComponent(new JButton(new ShowRain()));
- sequentialGroup.addComponent(new JButton(new ShowTextEditors()));
- sequentialGroup.addComponent(new JButton(new ShowTextEditors2()));
- sequentialGroup.addComponent(new JButton(new ShowGameOfLife()));
- sequentialGroup.addComponent(new JButton(new ShowRandomPolygons()));
- }
-
- private static class ShowTextEditors extends AbstractAction {
- ShowTextEditors() {
- putValue(NAME, "Text editors");
- }
-
- @Override
- public void actionPerformed(final ActionEvent e) {
- TextEditorDemo.main(null);
- }
- }
-
- private static class ShowTextEditors2 extends AbstractAction {
- ShowTextEditors2() {
- putValue(NAME, "Text editors city");
- }
-
- @Override
- public void actionPerformed(final ActionEvent e) {
- TextEditorDemo2.main(null);
- }
- }
-
-
- private static class ShowRain extends AbstractAction {
- ShowRain() {
- putValue(NAME, "Raining numbers");
- }
-
- @Override
- public void actionPerformed(final ActionEvent e) {
- RainingNumbersDemo.main(null);
- }
- }
-
- private static class ShowPointCloud extends AbstractAction {
- ShowPointCloud() {
- putValue(NAME, "Pointcloud galaxy");
- }
-
- @Override
- public void actionPerformed(final ActionEvent e) {
- PointCloudDemo.main(null);
- }
- }
-
- private static class ShowMathGraphs extends AbstractAction {
- ShowMathGraphs() {
- putValue(NAME, "Mathematical graphs");
- }
-
- @Override
- public void actionPerformed(final ActionEvent e) {
- GraphDemo.main(null);
- }
- }
-
- private static class ShowRandomPolygons extends AbstractAction {
- ShowRandomPolygons() {
- putValue(NAME, "Random polygons");
- }
-
- @Override
- public void actionPerformed(final ActionEvent e) {
- RandomPolygonsDemo.main(null);
- }
- }
-
- private static class ShowOctree extends AbstractAction {
- ShowOctree() {
- putValue(NAME, "Volumetric Octree");
- }
-
- @Override
- public void actionPerformed(final ActionEvent e) {
- OctreeDemo.main(null);
- }
- }
-
- private static class ShowGameOfLife extends AbstractAction {
- ShowGameOfLife() {
- putValue(NAME, "Game of Life");
- }
-
- @Override
- public void actionPerformed(final ActionEvent e) {
- eu.svjatoslav.sixth.e3d.examples.life.Main.main(null);
- }
- }
-
-}
+++ /dev/null
-package eu.svjatoslav.sixth.e3d.examples.life;
-
-import eu.svjatoslav.sixth.e3d.geometry.Point3D;
-import eu.svjatoslav.sixth.e3d.gui.humaninput.MouseInteractionController;
-import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
-import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.solidpolygon.SolidPolygon;
-import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.base.AbstractCompositeShape;
-
-/**
- * This class corresponds to a single cell within matrix.
- */
-class Cell extends AbstractCompositeShape implements
- MouseInteractionController {
-
- /**
- * cell visual size
- */
- static final int SIZE = 20;
- /**
- * Color of the active cell (R, G, B, A)
- */
- private static final Color ACTIVE_COLOR = new Color("A8FF");
- /**
- * Color of the active cell (R, G, B, A) while mouse is over it.
- */
- private static final Color ACTIVE_COLOR_MOUSE_OVER = new Color("F9FF");
- /**
- * Color of the inactive cell (R, G, B, A)
- */
- private static final Color INACTIVE_COLOR = new Color("55F8");
- /**
- * Color of the inactive cell (R, G, B, A) while mouse is over it.
- */
- private static final Color INACTIVE_COLOR_MOUSE_OVER = new Color("77F8");
- /**
- * A placeholder variable to help in next generation computation. Indicates
- * whether cell is going to survive within next generation.
- */
- public boolean survives;
- /**
- * Indicates whether cell is currently active
- */
- private boolean active;
- /**
- * Indicates whether mouse pointer is currently over this cell.
- */
- private boolean isMouseOver = false;
-
- public Cell(final Point3D center) {
- super(center);
-
- createCellShape();
-
- // enable receiving of mouse events
- setMouseInteractionController(this);
- }
-
- private void createCellShape() {
- final double halfSize = SIZE / 2f;
-
- // define 4 points corresponding to cell borders
- final Point3D p1 = new Point3D(-halfSize, 0, -halfSize);
-
- final Point3D p2 = new Point3D(+halfSize, 0, -halfSize);
-
- final Point3D p3 = new Point3D(+halfSize, 0, +halfSize);
-
- final Point3D p4 = new Point3D(-halfSize, 0, +halfSize);
-
- // connect 4 points with 2 polygons
- addShape(new SolidPolygon(p1, p2, p3, computeCellColor()));
- addShape(new SolidPolygon(p1, p4, p3, computeCellColor()));
- }
-
- /**
- * Compute cell color depending if cell is active and if mouse is over the
- * cell.
- */
- private Color computeCellColor() {
- if (active)
- if (isMouseOver)
- return ACTIVE_COLOR_MOUSE_OVER;
- else
- return ACTIVE_COLOR;
- else if (isMouseOver)
- return INACTIVE_COLOR_MOUSE_OVER;
- else
- return INACTIVE_COLOR;
- }
-
- public boolean isActive() {
- return active;
- }
-
- public void setActive(final boolean active) {
- this.active = active;
- updateColor();
- }
-
- @Override
- public boolean mouseClicked() {
- setActive(!isActive());
- return true;
- }
-
- @Override
- public boolean mouseEntered() {
- setMouseOver(true);
- return true;
- }
-
- @Override
- public boolean mouseExited() {
- setMouseOver(false);
- return true;
- }
-
- private void setMouseOver(final boolean isMouseOver) {
- this.isMouseOver = isMouseOver;
- updateColor();
- }
-
- /**
- * This method is called when cell status is changed to update its color
- * too.
- */
- private void updateColor() {
- setColor(computeCellColor());
- }
-
-}
+++ /dev/null
-package eu.svjatoslav.sixth.e3d.examples.life;
-
-import eu.svjatoslav.sixth.e3d.geometry.Point3D;
-import eu.svjatoslav.sixth.e3d.geometry.Rectangle;
-import eu.svjatoslav.sixth.e3d.gui.Avatar;
-import eu.svjatoslav.sixth.e3d.gui.ViewFrame;
-import eu.svjatoslav.sixth.e3d.gui.ViewPanel;
-import eu.svjatoslav.sixth.e3d.gui.humaninput.WorldNavigationUserInputTracker;
-import eu.svjatoslav.sixth.e3d.math.Transform;
-import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
-import eu.svjatoslav.sixth.e3d.renderer.raster.ShapeCollection;
-import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.line.LineAppearance;
-import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.wireframe.Grid2D;
-
-import java.awt.event.KeyEvent;
-
-
-public class Main extends WorldNavigationUserInputTracker {
-
- private static final Matrix MATRIX = new Matrix(
- new Point3D() // position matrix in the center of the scene
- );
-
- public static void main(final String[] args) {
- new Main().run();
- }
-
- /**
- * Handle keyboard input.
- */
- @Override
- public boolean keyPressed(final KeyEvent event, final ViewPanel viewPanel) {
- switch (event.getKeyChar()) {
- case ' ': // space key
- MATRIX.evolve(false);
- break;
- case 10: // ENTER
- MATRIX.evolve(true);
- break;
- case 'c': // reset matrix
- MATRIX.clear();
- break;
- default:
- return super.keyPressed(event, viewPanel);
- }
- return true;
- }
-
- private void run() {
-
- // create application frame visible to the user
- final ViewFrame viewFrame = new ViewFrame();
-
- final ShapeCollection shapeCollection = viewFrame.getViewPanel()
- .getRootShapeCollection();
-
- // add matrix
- shapeCollection.addShape(MATRIX);
-
- // add wire-frame grid (optional)
- shapeCollection.addShape(createGrid());
-
- final ViewPanel viewPanel = viewFrame.getViewPanel();
-
- setAvatarOrientation(viewPanel.getAvatar());
-
- // enable receiving of keyboard events
- viewPanel.getKeyboardFocusStack().pushFocusOwner(this);
-
- // Done! World is built. So ensure screen is updated too.
- viewPanel.repaintDuringNextViewUpdate();
- }
-
- /**
- * Create pink wire-frame grid below (for decorative purposes).
- */
- private Grid2D createGrid() {
- return new Grid2D(
- new Transform(
- new Point3D( // Grid positioning:
- 0, // center
- 100, // below the main scene
- 0), // center
-
- // Grid orientation:
- 0, // no rotation along XZ axis
- Math.PI / 2), // face down
-
- new Rectangle(800), // large enough, square grid
-
- 5, 5, // grid will be divided to 5x5 segments
-
- new LineAppearance(3, // line thickness
- new Color("FF000050") // red and quite transparent
- )
- );
- }
-
- /**
- * Set Avatar/Camera initial position in the world.
- */
- private void setAvatarOrientation(final Avatar avatar) {
- avatar.setLocation(new Point3D(100, -50, -200));
- avatar.setAngleXZ(0.2f);
- avatar.setAngleYZ(-0.7f);
- }
-
-}
+++ /dev/null
-package eu.svjatoslav.sixth.e3d.examples.life;
-
-import eu.svjatoslav.sixth.e3d.geometry.Point3D;
-import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.base.AbstractCompositeShape;
-import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.base.SubShape;
-
-/**
- * This is our 2D game of life world. It contains 2D array of {@link Cell}'s.
- */
-class Matrix extends AbstractCompositeShape {
-
- /**
- * Empty space between cells.
- */
- private static final int BORDER = 5;
-
- /**
- * Matrix size X and Y. (Amount of cells.)
- */
- private static final int SIZE = 30;
-
- /**
- * Object marker in 3D scene. Allows to locate all stars from the scene.
- */
- private static final String GROUP_STARS = "stars";
-
- /**
- * Object marker in 3D scene. Allows to locate surface on the scene.
- */
- private static final String GROUP_SURFACE = "surface";
-
- /**
- * 2 dimensional matrix of cells
- */
- private final Cell[][] cells = new Cell[SIZE][];
-
- public Matrix(final Point3D location) {
- super(location);
-
-
- for (int x = 0; x < SIZE; x++) {
- cells[x] = new Cell[SIZE];
-
- // init Y row
- for (int z = 0; z < SIZE; z++) {
- // create cell and register it
- final Cell cell = new Cell(getCellLocation(x, z));
- cells[x][z] = cell;
- addShape(cell);
- }
- }
-
- setGroupForUngrouped(GROUP_SURFACE);
- }
-
- /**
- * Clear matrix.
- */
- public void clear() {
-
- // mark every cell as inactive
- for (int x = 0; x < SIZE; x++)
- for (int y = 0; y < SIZE; y++)
- cells[x][y].setActive(false);
-
- // remove history stars
- removeGroup(GROUP_STARS);
- }
-
- /**
- * Compute survived cells based on the rules of Conway's Game of Life.
- */
- private void computeSurvivedCells() {
-
- for (int y = 0; y < SIZE; y++)
- for (int x = 0; x < SIZE; x++)
- processCell(x, y);
-
- for (int y = 0; y < SIZE; y++)
- for (int x = 0; x < SIZE; x++)
- cells[x][y].setActive(cells[x][y].survives);
-
- }
-
- private void processCell(int x, int y) {
- int aliveNeighbours = countNeighbours(x, y);
-
- if (cells[x][y].isActive()) {
- cells[x][y].survives = ((aliveNeighbours == 2) || (aliveNeighbours == 3));
- } else {
- cells[x][y].survives = aliveNeighbours == 3;
- }
- }
-
- private int countNeighbours(int x, int y) {
- int result = 0;
- for (int ny = y - 1; ny <= y + 1; ny++)
- for (int nx = x - 1; nx <= x + 1; nx++)
- if (isCellAlive(nx, ny)) result++;
-
- if (isCellAlive(x, y)) result--;
-
- return result;
- }
-
- private boolean isCellAlive(int x, int y) {
- if (x < 0) return false;
- if (x >= SIZE) return false;
- if (y < 0) return false;
- if (y >= SIZE) return false;
- return cells[x][y].isActive();
- }
-
- /**
- * Evolve matrix for one iteration
- */
- public void evolve(final boolean preserveHistory) {
- if (preserveHistory)
- markActiveCells();
-
- shiftStarsUp();
-
- computeSurvivedCells();
- }
-
- private Point3D getCellLocation(final int x, final int z) {
- final int shift = -((SIZE / 2) * (Cell.SIZE + BORDER));
-
- return new Point3D(
- (x * (Cell.SIZE + BORDER)) + shift,
- 0,
- (z * (Cell.SIZE + BORDER)) + shift);
- }
-
- /**
- * Leave trail of active cells as stars above matrix.
- */
- private void markActiveCells() {
- // mark survived cells
- for (int x = 0; x < SIZE; x++)
- for (int y = 0; y < SIZE; y++)
- if (cells[x][y].isActive())
- addShape(new Star(getCellLocation(x, y)));
-
- setGroupForUngrouped(GROUP_STARS);
- }
-
- /**
- * Find all history tracking stars and shift them up.
- */
- private void shiftStarsUp() {
-
- for (final SubShape subShape : getGroup(GROUP_STARS))
- ((Star) subShape.getShape()).getLocation().translateY(-10);
- }
-}
+++ /dev/null
-package eu.svjatoslav.sixth.e3d.examples.life;
-
-import eu.svjatoslav.sixth.e3d.geometry.Point3D;
-import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
-import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.GlowingPoint;
-
-import java.util.ArrayList;
-import java.util.List;
-
-class Star extends GlowingPoint {
- public static final int STAR_SIZE = 10;
-
- public static final int UNIQUE_STARS_COUNT = 30;
-
- private static final List<Color> uniqueStarColors = new ArrayList<>();
-
- /**
- * A little hack to save RAM. We are going to have potentially lot of stars.
- * Instead of creating new individual texture for each star, Sixth 3D engine
- * uses internal optimization and reuses existing star textures, if star with
- * identical color already exists. To take advantage ot such optimization
- * we create here limited set of precomputed star colors and later reuse them.
- */
- static {
- for (int i = 0; i < UNIQUE_STARS_COUNT; i++)
- uniqueStarColors.add(
- new Color(
- Math.random() + 0.5,
- Math.random() + 0.5,
- Math.random() + 0.5,
- 255));
- }
-
- public Star(Point3D location) {
- super(location,
- STAR_SIZE,
- uniqueStarColors.get((int) (Math.random() * uniqueStarColors.size())) // pick random pre-generated color
- );
- }
-
-}
--- /dev/null
+package eu.svjatoslav.sixth.e3d.examples.life_demo;
+
+import eu.svjatoslav.sixth.e3d.geometry.Point3D;
+import eu.svjatoslav.sixth.e3d.gui.humaninput.MouseInteractionController;
+import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.solidpolygon.SolidPolygon;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.base.AbstractCompositeShape;
+
+/**
+ * This class corresponds to a single cell within matrix.
+ */
+class Cell extends AbstractCompositeShape implements
+ MouseInteractionController {
+
+ /**
+ * cell visual size
+ */
+ static final int SIZE = 20;
+ /**
+ * Color of the active cell (R, G, B, A)
+ */
+ private static final Color ACTIVE_COLOR = new Color("A8FF");
+ /**
+ * Color of the active cell (R, G, B, A) while mouse is over it.
+ */
+ private static final Color ACTIVE_COLOR_MOUSE_OVER = new Color("F9FF");
+ /**
+ * Color of the inactive cell (R, G, B, A)
+ */
+ private static final Color INACTIVE_COLOR = new Color("55F8");
+ /**
+ * Color of the inactive cell (R, G, B, A) while mouse is over it.
+ */
+ private static final Color INACTIVE_COLOR_MOUSE_OVER = new Color("77F8");
+ /**
+ * A placeholder variable to help in next generation computation. Indicates
+ * whether cell is going to survive within next generation.
+ */
+ public boolean survives;
+ /**
+ * Indicates whether cell is currently active
+ */
+ private boolean active;
+ /**
+ * Indicates whether mouse pointer is currently over this cell.
+ */
+ private boolean isMouseOver = false;
+
+ public Cell(final Point3D center) {
+ super(center);
+
+ createCellShape();
+
+ // enable receiving of mouse events
+ setMouseInteractionController(this);
+ }
+
+ private void createCellShape() {
+ final double halfSize = SIZE / 2f;
+
+ // define 4 points corresponding to cell borders
+ final Point3D p1 = new Point3D(-halfSize, 0, -halfSize);
+
+ final Point3D p2 = new Point3D(+halfSize, 0, -halfSize);
+
+ final Point3D p3 = new Point3D(+halfSize, 0, +halfSize);
+
+ final Point3D p4 = new Point3D(-halfSize, 0, +halfSize);
+
+ // connect 4 points with 2 polygons
+ addShape(new SolidPolygon(p1, p2, p3, computeCellColor()));
+ addShape(new SolidPolygon(p1, p4, p3, computeCellColor()));
+ }
+
+ /**
+ * Compute cell color depending on if cell is active and if mouse is over the
+ * cell.
+ */
+ private Color computeCellColor() {
+ if (active)
+ if (isMouseOver)
+ return ACTIVE_COLOR_MOUSE_OVER;
+ else
+ return ACTIVE_COLOR;
+ else if (isMouseOver)
+ return INACTIVE_COLOR_MOUSE_OVER;
+ else
+ return INACTIVE_COLOR;
+ }
+
+ public boolean isActive() {
+ return active;
+ }
+
+ public void setActive(final boolean active) {
+ this.active = active;
+ updateColor();
+ }
+
+ @Override
+ public boolean mouseClicked(int button) {
+ setActive(!isActive());
+ return true;
+ }
+
+ @Override
+ public boolean mouseEntered() {
+ setMouseOver(true);
+ return true;
+ }
+
+ @Override
+ public boolean mouseExited() {
+ setMouseOver(false);
+ return true;
+ }
+
+ private void setMouseOver(final boolean isMouseOver) {
+ this.isMouseOver = isMouseOver;
+ updateColor();
+ }
+
+ /**
+ * This method is called when cell status is changed to update its color
+ * too.
+ */
+ private void updateColor() {
+ setColor(computeCellColor());
+ }
+
+}
--- /dev/null
+package eu.svjatoslav.sixth.e3d.examples.life_demo;
+
+import eu.svjatoslav.sixth.e3d.geometry.Point3D;
+import eu.svjatoslav.sixth.e3d.geometry.Rectangle;
+import eu.svjatoslav.sixth.e3d.gui.Avatar;
+import eu.svjatoslav.sixth.e3d.gui.ViewFrame;
+import eu.svjatoslav.sixth.e3d.gui.ViewPanel;
+import eu.svjatoslav.sixth.e3d.gui.humaninput.WorldNavigationUserInputTracker;
+import eu.svjatoslav.sixth.e3d.math.Transform;
+import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
+import eu.svjatoslav.sixth.e3d.renderer.raster.ShapeCollection;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.line.LineAppearance;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.wireframe.Grid2D;
+
+import java.awt.event.KeyEvent;
+
+
+public class Main extends WorldNavigationUserInputTracker {
+
+ private static final Matrix MATRIX = new Matrix(
+ new Point3D() // position matrix in the center of the scene
+ );
+
+ public static void main(final String[] args) {
+ new Main().run();
+ }
+
+ /**
+ * Handle keyboard input.
+ */
+ @Override
+ public boolean keyPressed(final KeyEvent event, final ViewPanel viewPanel) {
+ switch (event.getKeyChar()) {
+ case ' ': // space key
+ MATRIX.evolve(false);
+ break;
+ case 10: // ENTER
+ MATRIX.evolve(true);
+ break;
+ case 'c': // reset matrix
+ MATRIX.clear();
+ break;
+ default:
+ return super.keyPressed(event, viewPanel);
+ }
+ return true;
+ }
+
+ private void run() {
+
+ // create application frame visible to the user
+ final ViewFrame viewFrame = new ViewFrame();
+
+ final ShapeCollection shapeCollection = viewFrame.getViewPanel()
+ .getRootShapeCollection();
+
+ // add matrix
+ shapeCollection.addShape(MATRIX);
+
+ // add wire-frame grid (optional)
+ shapeCollection.addShape(createGrid());
+
+ final ViewPanel viewPanel = viewFrame.getViewPanel();
+
+ setAvatarOrientation(viewPanel.getAvatar());
+
+ // enable receiving of keyboard events
+ viewPanel.getKeyboardFocusStack().pushFocusOwner(this);
+
+ // Done! World is built. So ensure screen is updated too.
+ viewPanel.repaintDuringNextViewUpdate();
+ }
+
+ /**
+ * Create pink wire-frame grid below (for decorative purposes).
+ */
+ private Grid2D createGrid() {
+ return new Grid2D(
+ new Transform(
+ new Point3D( // Grid positioning:
+ 0, // center
+ 100, // below the main scene
+ 0), // center
+
+ // Grid orientation:
+ 0, // no rotation along XZ axis
+ Math.PI / 2), // face down
+
+ new Rectangle(800), // large enough, square grid
+
+ 5, 5, // grid will be divided to 5x5 segments
+
+ new LineAppearance(3, // line thickness
+ new Color("FF000050") // red and quite transparent
+ )
+ );
+ }
+
+ /**
+ * Set Avatar/Camera initial position in the world.
+ */
+ private void setAvatarOrientation(final Avatar avatar) {
+ avatar.setLocation(new Point3D(100, -50, -200));
+ avatar.setAngleXZ(0.2f);
+ avatar.setAngleYZ(-0.7f);
+ }
+
+}
--- /dev/null
+package eu.svjatoslav.sixth.e3d.examples.life_demo;
+
+import eu.svjatoslav.sixth.e3d.geometry.Point3D;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.base.AbstractCompositeShape;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.base.SubShape;
+
+/**
+ * This is our 2D game of life world. It contains 2D array of {@link Cell}'s.
+ */
+class Matrix extends AbstractCompositeShape {
+
+ /**
+ * Empty space between cells.
+ */
+ private static final int BORDER = 5;
+
+ /**
+ * Matrix size X and Y. (Amount of cells.)
+ */
+ private static final int SIZE = 30;
+
+ /**
+ * Object marker in 3D scene. Allows to locate all stars from the scene.
+ */
+ private static final String GROUP_STARS = "stars";
+
+ /**
+ * Object marker in 3D scene. Allows to locate surface on the scene.
+ */
+ private static final String GROUP_SURFACE = "surface";
+
+ /**
+ * 2 dimensional matrix of cells
+ */
+ private final Cell[][] cells = new Cell[SIZE][];
+
+ public Matrix(final Point3D location) {
+ super(location);
+
+
+ for (int x = 0; x < SIZE; x++) {
+ cells[x] = new Cell[SIZE];
+
+ // init Y row
+ for (int z = 0; z < SIZE; z++) {
+ // create cell and register it
+ final Cell cell = new Cell(getCellLocation(x, z));
+ cells[x][z] = cell;
+ addShape(cell);
+ }
+ }
+
+ setGroupForUngrouped(GROUP_SURFACE);
+ }
+
+ /**
+ * Clear matrix.
+ */
+ public void clear() {
+
+ // mark every cell as inactive
+ for (int x = 0; x < SIZE; x++)
+ for (int y = 0; y < SIZE; y++)
+ cells[x][y].setActive(false);
+
+ // remove history stars
+ removeGroup(GROUP_STARS);
+ }
+
+ /**
+ * Compute survived cells based on the rules of Conway's Game of Life.
+ */
+ private void computeSurvivedCells() {
+
+ for (int y = 0; y < SIZE; y++)
+ for (int x = 0; x < SIZE; x++)
+ processCell(x, y);
+
+ for (int y = 0; y < SIZE; y++)
+ for (int x = 0; x < SIZE; x++)
+ cells[x][y].setActive(cells[x][y].survives);
+
+ }
+
+ private void processCell(int x, int y) {
+ int aliveNeighbours = countNeighbours(x, y);
+
+ if (cells[x][y].isActive()) {
+ cells[x][y].survives = ((aliveNeighbours == 2) || (aliveNeighbours == 3));
+ } else {
+ cells[x][y].survives = aliveNeighbours == 3;
+ }
+ }
+
+ private int countNeighbours(int x, int y) {
+ int result = 0;
+ for (int ny = y - 1; ny <= y + 1; ny++)
+ for (int nx = x - 1; nx <= x + 1; nx++)
+ if (isCellAlive(nx, ny)) result++;
+
+ if (isCellAlive(x, y)) result--;
+
+ return result;
+ }
+
+ private boolean isCellAlive(int x, int y) {
+ if (x < 0) return false;
+ if (x >= SIZE) return false;
+ if (y < 0) return false;
+ if (y >= SIZE) return false;
+ return cells[x][y].isActive();
+ }
+
+ /**
+ * Evolve matrix for one iteration
+ */
+ public void evolve(final boolean preserveHistory) {
+ if (preserveHistory)
+ markActiveCells();
+
+ shiftStarsUp();
+
+ computeSurvivedCells();
+ }
+
+ private Point3D getCellLocation(final int x, final int z) {
+ final int shift = -((SIZE / 2) * (Cell.SIZE + BORDER));
+
+ return new Point3D(
+ (x * (Cell.SIZE + BORDER)) + shift,
+ 0,
+ (z * (Cell.SIZE + BORDER)) + shift);
+ }
+
+ /**
+ * Leave trail of active cells as stars above matrix.
+ */
+ private void markActiveCells() {
+ // mark survived cells
+ for (int x = 0; x < SIZE; x++)
+ for (int y = 0; y < SIZE; y++)
+ if (cells[x][y].isActive())
+ addShape(new Star(getCellLocation(x, y)));
+
+ setGroupForUngrouped(GROUP_STARS);
+ }
+
+ /**
+ * Find all history tracking stars and shift them up.
+ */
+ private void shiftStarsUp() {
+
+ for (final SubShape subShape : getGroup(GROUP_STARS))
+ ((Star) subShape.getShape()).getLocation().translateY(-10);
+ }
+}
--- /dev/null
+package eu.svjatoslav.sixth.e3d.examples.life_demo;
+
+import eu.svjatoslav.sixth.e3d.geometry.Point3D;
+import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.GlowingPoint;
+
+import java.util.ArrayList;
+import java.util.List;
+
+class Star extends GlowingPoint {
+ public static final int STAR_SIZE = 10;
+
+ public static final int UNIQUE_STARS_COUNT = 30;
+
+ private static final List<Color> uniqueStarColors = new ArrayList<>();
+
+ /*
+ * A little hack to save RAM. We are going to have potentially lot of stars.
+ * Instead of creating new individual texture for each star, Sixth 3D engine
+ * uses internal optimization and reuses existing star textures, if star with
+ * identical color already exists. To take advantage ot such optimization
+ * we create here limited set of precomputed star colors and later reuse them.
+ */
+ static {
+ for (int i = 0; i < UNIQUE_STARS_COUNT; i++)
+ uniqueStarColors.add(
+ new Color(
+ Math.random() + 0.5,
+ Math.random() + 0.5,
+ Math.random() + 0.5,
+ 255));
+ }
+
+ public Star(Point3D location) {
+ super(location,
+ STAR_SIZE,
+ uniqueStarColors.get((int) (Math.random() * uniqueStarColors.size())) // pick random pre-generated color
+ );
+ }
+
+}
#!/bin/bash
-cd "${0%/*}"; if [ "$1" != "T" ]; then gnome-terminal -e "'$0' T"; exit; fi;
+
+cd "${0%/*}"; if [ "$1" != "T" ]; then gnome-terminal -- "$0" T; exit; fi;
+
cd ..
+++ /dev/null
-#!/bin/bash
-
-if [ "$1" != "T" ]; then gnome-terminal -e "'$0' T"; exit; fi
-
-#
-# This is a helper bash script that starts current Java project in debug mode
-# with JRebel attached. It also opens its own terminal window, so you can run
-# this script by simply clicking on it in file navigator.
-#
-#
-# Script assumes:
-#
-# + GNU OS
-# + Gnome workspace
-# + JRebel is installed in /opt/jrebel
-#
-
-
-cd "${0%/*}"
-cd ..
-
-
-while true; do
-
- # clear screen
- printf "\033c"
-
- # enable debugging
- export DEBUG_OPTIONS="-Xdebug -Xrunjdwp:transport=dt_socket,address=127.0.0.1:8000,server=y,suspend=n"
-
- # enable JRebel
- export REBEL_BASE="$HOME/.jrebel"
- export JREBEL_OPTS="-agentpath:/opt/jrebel/libjrebel64.so -Drebel.project.path=`pwd`"
-
- # enable LWJGL native libraries
- export LWJGL_OPTS="-Djava.library.path=target/natives"
-
- # define Maven options
- export MAVEN_OPTS="-Xmx4000m $DEBUG_OPTIONS $JREBEL_OPTS $LWJGL_OPTS"
-
- mvn compile exec:java -Dexec.mainClass="eu.svjatoslav.sixth.e3d.examples.launcher.Main"
-
- echo "press ENTER to reload application"
- read
-
-done
#!/bin/bash
-#
-# This is a helper bash script that starts IntelliJ with the current project.
-# Script is written is such a way that you can simply click on it in file
-# navigator to run it.
-#
-#
-# Script assumes:
-#
-# + GNU operating system
-# + IntelliJ is installed and commandline launcher "idea" is enabled.
-#
+# This script launches IntelliJ IDEA with the current project
+# directory. The script is designed to be run by double-clicking it in
+# the GNOME Nautilus file manager.
+
+# First, we change the current working directory to the directory of
+# the script.
+
+# "${0%/*}" gives us the path of the script itself, without the
+# script's filename.
+
+# This command basically tells the system "change the current
+# directory to the directory containing this script".
cd "${0%/*}"
+
+# Then, we move up one directory level.
+# The ".." tells the system to go to the parent directory of the current directory.
+# This is done because we assume that the project directory is one level up from the script.
cd ..
-setsid idea . &>/dev/null
+# Now, we use the 'setsid' command to start a new session and run
+# IntelliJ IDEA in the background. 'setsid' is a UNIX command that
+# runs a program in a new session.
+
+# The command 'idea .' opens IntelliJ IDEA with the current directory
+# as the project directory. The '&' at the end is a UNIX command that
+# runs the process in the background. The '> /dev/null' part tells
+# the system to redirect all output (both stdout and stderr, denoted
+# by '&') that would normally go to the terminal to go to /dev/null
+# instead, which is a special file that discards all data written to
+# it.
+
+setsid idea . &>/dev/null &
+
+# The 'disown' command is a shell built-in that removes a shell job
+# from the shell's active list. Therefore, the shell will not send a
+# SIGHUP to this particular job when the shell session is terminated.
+
+# '-h' option specifies that if the shell receives a SIGHUP, it also
+# doesn't send a SIGHUP to the job.
+
+# '$!' is a shell special parameter that expands to the process ID of
+# the most recent background job.
+disown -h $!
+
+
+sleep 2
+
+# Finally, we use the 'exit' command to terminate the shell script.
+# This command tells the system to close the terminal window after
+# IntelliJ IDEA has been opened.
+exit
#!/bin/bash
-cd "${0%/*}"; if [ "$1" != "T" ]; then gnome-terminal -e "'$0' T"; exit; fi;
+cd "${0%/*}"; if [ "$1" != "T" ]; then gnome-terminal -- "$0" T; exit; fi;
cd ..