refactor(examples): split GraphDemo into separate demos
authorSvjatoslav Agejenko <svjatoslav@svjatoslav.eu>
Tue, 17 Mar 2026 18:30:29 +0000 (20:30 +0200)
committerSvjatoslav Agejenko <svjatoslav@svjatoslav.eu>
Tue, 17 Mar 2026 18:30:29 +0000 (20:30 +0200)
Separate math function graphs into MathGraphsDemo, leaving GraphDemo with only the sine heightmap and sphere. Update launcher with both demos.

doc/index.org
src/main/java/eu/svjatoslav/sixth/e3d/examples/GraphDemo.java
src/main/java/eu/svjatoslav/sixth/e3d/examples/MathGraphsDemo.java [new file with mode: 0644]
src/main/java/eu/svjatoslav/sixth/e3d/examples/launcher/ApplicationListPanel.java

index c53fbf7..8beb6a7 100644 (file)
@@ -71,6 +71,10 @@ To start the demo application, use command:
 :ID:       5f88b493-6ab3-4659-8280-803f75dbd5e0
 :END:
 
+Press *F12* in any demo to open the [[https://www3.svjatoslav.eu/projects/sixth-3d/#outline-container-developer-tools][Developer Tools panel]]. This
+debugging interface provides real-time insight into the rendering
+pipeline with diagnostic toggles.
+
 ** Conway's Game of Life
 :PROPERTIES:
 :CUSTOM_ID: conways-game-of-life
@@ -153,7 +157,7 @@ again, window must be unfocused first using ESC key.
 
 See also [[https://hackers-1995.vercel.app/][similar looking web based demo]] ! :)
 
-** Mathematical formulas
+** Math graphs demo
 :PROPERTIES:
 :CUSTOM_ID: mathematical-formulas
 :ID:       b1c2d3e4-f5a6-7890-bcde-f12345678901
@@ -242,16 +246,6 @@ Star Grid                    304.59
 ================================================================================
 #+end_example
 
-** Developer tools
-:PROPERTIES:
-:CUSTOM_ID: developer-tools
-:ID:       8c5e2a1f-9d3b-4f6a-b8e7-1c4d5f7a9b2e
-:END:
-
-Press *F12* in any demo to open the Developer Tools panel. This
-debugging interface provides real-time insight into the rendering
-pipeline with diagnostic toggles.
-
 * Source code
 :PROPERTIES:
 :CUSTOM_ID: source-code
index 1be37ee..b35160b 100755 (executable)
@@ -2,27 +2,21 @@
  * 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.Point2D;
 import eu.svjatoslav.sixth.e3d.geometry.Point3D;
 import eu.svjatoslav.sixth.e3d.gui.ViewFrame;
 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.basic.solidpolygon.SolidPolygon;
-import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.Graph;
 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.wireframe.WireframeSphere;
 
-import java.util.ArrayList;
-import java.util.List;
-
 /**
- * Demo showing various mathematical function graphs rendered in 3D.
- * Displays sine, cosine, tangent, and composite function graphs arranged around
- * a central sphere, with two wobbly surfaces above and below.
+ * Demo showing a sine heightmap surface with a central wireframe sphere.
+ * Two wobbly surfaces are positioned above and below the sphere.
  */
 public class GraphDemo {
 
@@ -70,7 +64,6 @@ public class GraphDemo {
         for (double x = -500; x < 500; x += 20)
             for (double z = -500; z < 500; z += 20) {
 
-                // use Pythagorean theorem to compute distance from the center
                 final double distanceFromCenter = Math.sqrt((x * x) + (z * z));
 
                 double plateElevation = Math.sin(distanceFromCenter / WAVE_FREQUENCY) * WAVE_AMPLITUDE;
@@ -80,113 +73,6 @@ public class GraphDemo {
             }
     }
 
-    /**
-     * Creates a graph of the cosine function.
-     * @param location the position of the graph in 3D space
-     * @return a Graph component showing y = cos(x)
-     */
-    private static Graph getCosineGraph(final Point3D location) {
-        final List<Point2D> data = new ArrayList<>();
-        for (double x = 0; x < 20; x += 0.25) {
-            final double y = Math.cos(x);
-
-            final Point2D p = new Point2D(x, y);
-            data.add(p);
-        }
-
-        return new Graph(GRAPH_SCALE, data, "Cosine", location);
-    }
-
-    /**
-     * Creates a graph of y = sin(tan(x)).
-     * @param location the position of the graph in 3D space
-     * @return a Graph component showing the composite function
-     */
-    private static Graph getFormula1Graph(final Point3D location) {
-        final List<Point2D> data = new ArrayList<>();
-        for (double x = 0; x < 20; x += 0.25) {
-            final double y = Math.sin(Math.tan(x));
-
-            final Point2D p = new Point2D(x, y);
-            data.add(p);
-        }
-
-        return new Graph(GRAPH_SCALE, data, "y = sin(tan(x))", location);
-    }
-
-    /**
-     * Creates a graph of y = (10-x)^2 / 30.
-     * @param location the position of the graph in 3D space
-     * @return a Graph component showing the parabola
-     */
-    private static Graph getFormula2Graph(final Point3D location) {
-        final List<Point2D> data = new ArrayList<>();
-        for (double x = 0; x < 20; x += 0.25) {
-            final double y = (Math.pow((10 - x), 2) / 30) - 2;
-
-            final Point2D p = new Point2D(x, y);
-            data.add(p);
-        }
-
-        return new Graph(GRAPH_SCALE, data, "y = ( (10-x)^2 ) / 30", location);
-    }
-
-    /**
-     * Creates a graph of y = sin(x/2) + sin(x/1.26).
-     * @param location the position of the graph in 3D space
-     * @return a Graph component showing the composite sine wave
-     */
-    private static Graph getFormula3Graph(final Point3D location) {
-        final List<Point2D> data = new ArrayList<>();
-        for (double x = 0; x < 20; x += 0.25) {
-            final double y = Math.sin(x / 2) + Math.sin(x / 1.26);
-
-            final Point2D p = new Point2D(x, y);
-            data.add(p);
-        }
-
-        return new Graph(GRAPH_SCALE, data, "y = sin(x/2) + sin(x/1.26)", location);
-    }
-
-    /**
-     * Creates a graph of the sine function.
-     * @param location the position of the graph in 3D space
-     * @return a Graph component showing y = sin(x)
-     */
-    private static Graph getSineGraph(final Point3D location) {
-        final List<Point2D> data = new ArrayList<>();
-        for (double x = 0; x < 20; x += 0.25) {
-            final double y = Math.sin(x);
-
-            final Point2D p = new Point2D(x, y);
-            data.add(p);
-        }
-
-        return new Graph(GRAPH_SCALE, data, "Sine", location);
-    }
-
-    /**
-     * Creates a graph of the tangent function with clamped values.
-     * @param location the position of the graph in 3D space
-     * @return a Graph component showing y = tan(x) with clamped range
-     */
-    private static Graph getTangentGraph(final Point3D location) {
-        final List<Point2D> data = new ArrayList<>();
-        for (double x = 0; x < 20; x += 0.25) {
-            double y = Math.tan(x);
-
-            if (y > 2)
-                y = 2;
-            if (y < -2)
-                y = -2;
-
-            final Point2D p = new Point2D(x, y);
-            data.add(p);
-        }
-
-        return new Graph(GRAPH_SCALE, data, "Tangent", location);
-    }
-
     /**
      * Entry point for the graph demo.
      * @param args command line arguments (ignored)
@@ -197,14 +83,12 @@ public class GraphDemo {
         final ShapeCollection geometryCollection = viewFrame.getViewPanel()
                 .getRootShapeCollection();
 
-        addMathFormulas(geometryCollection);
         addSphere(geometryCollection);
         addWobblySurface(geometryCollection, 200);
         addWobblySurface(geometryCollection, -200);
 
         setCameraLocation(viewFrame);
         
-        // Ensure the render thread is started
         viewFrame.getViewPanel().ensureRenderThreadStarted();
     }
 
@@ -213,7 +97,6 @@ public class GraphDemo {
      * @param geometryCollection the collection to add the sphere to
      */
     private static void addSphere(ShapeCollection geometryCollection) {
-        // add sphere
         geometryCollection.addShape(new WireframeSphere(new Point3D(0, 0, 0),
                 100,
                 new LineAppearance(
@@ -222,31 +105,6 @@ public class GraphDemo {
         ));
     }
 
-    /**
-     * Adds all mathematical formula graphs to the scene.
-     * @param geometryCollection the collection to add graphs to
-     */
-    private static void addMathFormulas(ShapeCollection geometryCollection) {
-        int z = 1000;
-        Point3D location = new Point3D(-600, -300, z);
-        geometryCollection.addShape(getSineGraph(location));
-
-        location = new Point3D(600, -300, z);
-        geometryCollection.addShape(getFormula1Graph(location));
-
-        location = new Point3D(-600, 0, z);
-        geometryCollection.addShape(getCosineGraph(location));
-
-        location = new Point3D(600, 0, z);
-        geometryCollection.addShape(getFormula2Graph(location));
-
-        location = new Point3D(-600, 300, z);
-        geometryCollection.addShape(getTangentGraph(location));
-
-        location = new Point3D(600, 300, z);
-        geometryCollection.addShape(getFormula3Graph(location));
-    }
-
     /**
      * Sets the camera to an initial viewing position.
      * @param viewFrame the view frame whose camera to configure
diff --git a/src/main/java/eu/svjatoslav/sixth/e3d/examples/MathGraphsDemo.java b/src/main/java/eu/svjatoslav/sixth/e3d/examples/MathGraphsDemo.java
new file mode 100644 (file)
index 0000000..49bdd88
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * 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.Point2D;
+import eu.svjatoslav.sixth.e3d.geometry.Point3D;
+import eu.svjatoslav.sixth.e3d.gui.ViewFrame;
+import eu.svjatoslav.sixth.e3d.renderer.raster.ShapeCollection;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.Graph;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Demo showing mathematical function graphs rendered in 3D.
+ * Displays sine, cosine, tangent, and composite function graphs.
+ */
+public class MathGraphsDemo {
+
+    private static final double GRAPH_SCALE = 50d;
+
+    /**
+     * Creates a new MathGraphsDemo instance.
+     */
+    public MathGraphsDemo() {
+    }
+
+    /**
+     * Creates a graph of the cosine function.
+     * @param location the position of the graph in 3D space
+     * @return a Graph component showing y = cos(x)
+     */
+    private static Graph getCosineGraph(final Point3D location) {
+        final List<Point2D> data = new ArrayList<>();
+        for (double x = 0; x < 20; x += 0.25) {
+            final double y = Math.cos(x);
+
+            final Point2D p = new Point2D(x, y);
+            data.add(p);
+        }
+
+        return new Graph(GRAPH_SCALE, data, "Cosine", location);
+    }
+
+    /**
+     * Creates a graph of y = sin(tan(x)).
+     * @param location the position of the graph in 3D space
+     * @return a Graph component showing the composite function
+     */
+    private static Graph getFormula1Graph(final Point3D location) {
+        final List<Point2D> data = new ArrayList<>();
+        for (double x = 0; x < 20; x += 0.25) {
+            final double y = Math.sin(Math.tan(x));
+
+            final Point2D p = new Point2D(x, y);
+            data.add(p);
+        }
+
+        return new Graph(GRAPH_SCALE, data, "y = sin(tan(x))", location);
+    }
+
+    /**
+     * Creates a graph of y = (10-x)^2 / 30.
+     * @param location the position of the graph in 3D space
+     * @return a Graph component showing the parabola
+     */
+    private static Graph getFormula2Graph(final Point3D location) {
+        final List<Point2D> data = new ArrayList<>();
+        for (double x = 0; x < 20; x += 0.25) {
+            final double y = (Math.pow((10 - x), 2) / 30) - 2;
+
+            final Point2D p = new Point2D(x, y);
+            data.add(p);
+        }
+
+        return new Graph(GRAPH_SCALE, data, "y = ( (10-x)^2 ) / 30", location);
+    }
+
+    /**
+     * Creates a graph of y = sin(x/2) + sin(x/1.26).
+     * @param location the position of the graph in 3D space
+     * @return a Graph component showing the composite sine wave
+     */
+    private static Graph getFormula3Graph(final Point3D location) {
+        final List<Point2D> data = new ArrayList<>();
+        for (double x = 0; x < 20; x += 0.25) {
+            final double y = Math.sin(x / 2) + Math.sin(x / 1.26);
+
+            final Point2D p = new Point2D(x, y);
+            data.add(p);
+        }
+
+        return new Graph(GRAPH_SCALE, data, "y = sin(x/2) + sin(x/1.26)", location);
+    }
+
+    /**
+     * Creates a graph of the sine function.
+     * @param location the position of the graph in 3D space
+     * @return a Graph component showing y = sin(x)
+     */
+    private static Graph getSineGraph(final Point3D location) {
+        final List<Point2D> data = new ArrayList<>();
+        for (double x = 0; x < 20; x += 0.25) {
+            final double y = Math.sin(x);
+
+            final Point2D p = new Point2D(x, y);
+            data.add(p);
+        }
+
+        return new Graph(GRAPH_SCALE, data, "Sine", location);
+    }
+
+    /**
+     * Creates a graph of the tangent function with clamped values.
+     * @param location the position of the graph in 3D space
+     * @return a Graph component showing y = tan(x) with clamped range
+     */
+    private static Graph getTangentGraph(final Point3D location) {
+        final List<Point2D> data = new ArrayList<>();
+        for (double x = 0; x < 20; x += 0.25) {
+            double y = Math.tan(x);
+
+            if (y > 2)
+                y = 2;
+            if (y < -2)
+                y = -2;
+
+            final Point2D p = new Point2D(x, y);
+            data.add(p);
+        }
+
+        return new Graph(GRAPH_SCALE, data, "Tangent", location);
+    }
+
+    /**
+     * Entry point for the math graphs demo.
+     * @param args command line arguments (ignored)
+     */
+    public static void main(final String[] args) {
+
+        final ViewFrame viewFrame = new ViewFrame();
+        final ShapeCollection geometryCollection = viewFrame.getViewPanel()
+                .getRootShapeCollection();
+
+        addMathFormulas(geometryCollection);
+
+        setCameraLocation(viewFrame);
+        
+        viewFrame.getViewPanel().ensureRenderThreadStarted();
+    }
+
+    /**
+     * Adds all mathematical formula graphs to the scene.
+     * @param geometryCollection the collection to add graphs to
+     */
+    private static void addMathFormulas(ShapeCollection geometryCollection) {
+        int z = 1000;
+        Point3D location = new Point3D(-600, -300, z);
+        geometryCollection.addShape(getSineGraph(location));
+
+        location = new Point3D(600, -300, z);
+        geometryCollection.addShape(getFormula1Graph(location));
+
+        location = new Point3D(-600, 0, z);
+        geometryCollection.addShape(getCosineGraph(location));
+
+        location = new Point3D(600, 0, z);
+        geometryCollection.addShape(getFormula2Graph(location));
+
+        location = new Point3D(-600, 300, z);
+        geometryCollection.addShape(getTangentGraph(location));
+
+        location = new Point3D(600, 300, z);
+        geometryCollection.addShape(getFormula3Graph(location));
+    }
+
+    /**
+     * Sets the camera to an initial viewing position.
+     * @param viewFrame the view frame whose camera to configure
+     */
+    private static void setCameraLocation(ViewFrame viewFrame) {
+        viewFrame.getViewPanel().getCamera().getTransform().setTranslation(new Point3D(0, 0, -500));
+    }
+
+}
\ No newline at end of file
index bd0d9a8..3af0262 100644 (file)
@@ -7,6 +7,7 @@
 package eu.svjatoslav.sixth.e3d.examples.launcher;
 
 import eu.svjatoslav.sixth.e3d.examples.GraphDemo;
+import eu.svjatoslav.sixth.e3d.examples.MathGraphsDemo;
 import eu.svjatoslav.sixth.e3d.examples.MinimalExample;
 import eu.svjatoslav.sixth.e3d.examples.OctreeDemo;
 import eu.svjatoslav.sixth.e3d.examples.RandomPolygonsDemo;
@@ -39,8 +40,11 @@ class ApplicationListPanel extends JPanel {
         new DemoEntry("Volumetric Octree",
                 "Octree-based rendering with on-demand raytracing",
                 new ShowOctree()),
-        new DemoEntry("Mathematical graphs",
-                "Function graphs rendered in 3D around a sphere",
+        new DemoEntry("Sine heightmap",
+                "Two wobbly sine wave surfaces with central sphere",
+                new ShowSineHeightmap()),
+        new DemoEntry("Math graphs demo",
+                "Function graphs (sin, cos, tan) rendered in 3D",
                 new ShowMathGraphs()),
         new DemoEntry("Point cloud galaxy",
                 "Spiral galaxy with 10,000 glowing points",
@@ -167,6 +171,17 @@ class ApplicationListPanel extends JPanel {
             putValue(NAME, "Mathematical graphs");
         }
 
+        @Override
+        public void actionPerformed(final ActionEvent e) {
+            MathGraphsDemo.main(null);
+        }
+    }
+
+    private static class ShowSineHeightmap extends AbstractAction {
+        ShowSineHeightmap() {
+            putValue(NAME, "Sine heightmap");
+        }
+
         @Override
         public void actionPerformed(final ActionEvent e) {
             GraphDemo.main(null);