│ ├── Cell.java
│ ├── Matrix.java
│ └── Star.java
-├── diamondsquare_demo/ - Procedural terrain generation demo
-│ ├── DiamondSquareLandscape.java
-│ └── DiamondSquareTerrain.java
+├── terrain_demo/ - Procedural terrain generation demo
+│ ├── DiamondSquareTerrain.java
+│ ├── FractalTree.java
+│ └── TerrainDemo.java
├── galaxy_demo/ - Galaxy simulation demo
│ ├── Galaxy.java
│ └── PointCloudDemo.java
Lit Solid Cubes 41.40
Textured Cubes 32.80
Wireframe Cubes 42.84
-Star Grid 304.59
+Star Grid 318.97
================================================================================
#+end_example
--- /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.gui.ViewPanel;
+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.solid.SolidPolygonArrow;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.solid.SolidPolygonCone;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.wireframe.Grid3D;
+
+/**
+ * Demo showcasing the SolidPolygonArrow shape with various colors, sizes,
+ * orientations, and transparency levels.
+ *
+ * <p>This demo displays arrows pointing in different directions to demonstrate
+ * the flexibility of the arrow shape. A 3D grid provides spatial reference.</p>
+ */
+public class ArrowDemo {
+
+ /**
+ * Entry point for the arrow demo.
+ *
+ * @param args command line arguments (ignored)
+ */
+ public static void main(final String[] args) {
+ final ViewFrame viewFrame = new ViewFrame("Arrow Demo");
+ final ViewPanel viewPanel = viewFrame.getViewPanel();
+ final ShapeCollection shapes = viewPanel.getRootShapeCollection();
+
+ // Position camera to view the scene
+ viewPanel.getCamera().getTransform().setTranslation(new Point3D(0, -200, -600));
+
+ // Add a 3D grid for spatial reference
+ final LineAppearance gridAppearance = new LineAppearance(1, new Color(100, 100, 100, 80));
+ final Grid3D grid = new Grid3D(
+ new Point3D(-300, -200, -300),
+ new Point3D(300, 200, 300),
+ 100,
+ gridAppearance
+ );
+ shapes.addShape(grid);
+
+ // Create arrows pointing in different directions with different properties
+
+ // Red arrow pointing up (negative Y direction)
+ final SolidPolygonArrow redArrow = new SolidPolygonArrow(
+ new Point3D(0, 150, 0),
+ new Point3D(0, -150, 0),
+ 8, // body radius
+ 20, // tip radius
+ 40, // tip length
+ 16, // segments
+ Color.RED
+ );
+ shapes.addShape(redArrow);
+
+ // Green arrow pointing along positive X
+ final SolidPolygonArrow greenArrow = new SolidPolygonArrow(
+ new Point3D(-200, 0, 0),
+ new Point3D(0, 0, 0),
+ 6,
+ 15,
+ 30,
+ 12,
+ Color.GREEN
+ );
+ shapes.addShape(greenArrow);
+
+ // Blue arrow pointing along positive Z
+ final SolidPolygonArrow blueArrow = new SolidPolygonArrow(
+ new Point3D(0, 0, -200),
+ new Point3D(0, 0, 0),
+ 6,
+ 15,
+ 30,
+ 12,
+ Color.BLUE
+ );
+ shapes.addShape(blueArrow);
+
+ // Yellow arrow pointing diagonally
+ final SolidPolygonArrow yellowArrow = new SolidPolygonArrow(
+ new Point3D(100, 100, 100),
+ new Point3D(300, -100, 300),
+ 10,
+ 25,
+ 50,
+ 16,
+ Color.YELLOW
+ );
+ shapes.addShape(yellowArrow);
+
+ // Semi-transparent cyan arrow (50% opacity)
+ final SolidPolygonArrow transparentCyanArrow = new SolidPolygonArrow(
+ new Point3D(-150, 50, -100),
+ new Point3D(-50, -100, 100),
+ 8,
+ 20,
+ 40,
+ 12,
+ new Color(0, 255, 255, 128)
+ );
+ shapes.addShape(transparentCyanArrow);
+
+ // Semi-transparent magenta arrow (25% opacity)
+ final SolidPolygonArrow transparentMagentaArrow = new SolidPolygonArrow(
+ new Point3D(50, 200, 50),
+ new Point3D(50, 0, 50),
+ 12,
+ 30,
+ 60,
+ 20,
+ new Color(255, 0, 255, 64)
+ );
+ shapes.addShape(transparentMagentaArrow);
+
+ // Small white arrows forming a circle pattern
+ for (int i = 0; i < 8; i++) {
+ final double angle = i * Math.PI / 4;
+ final double radius = 250;
+ final double startX = radius * Math.cos(angle);
+ final double startZ = radius * Math.sin(angle);
+ final double endX = (radius + 80) * Math.cos(angle);
+ final double endZ = (radius + 80) * Math.sin(angle);
+
+ final SolidPolygonArrow circleArrow = new SolidPolygonArrow(
+ new Point3D(startX, -80, startZ),
+ new Point3D(endX, -80, endZ),
+ 4,
+ 10,
+ 20,
+ 8,
+ Color.WHITE
+ );
+ shapes.addShape(circleArrow);
+ }
+
+ // A standalone cone to demonstrate SolidPolygonCone
+ final SolidPolygonCone standaloneCone = new SolidPolygonCone(
+ new Point3D(-300, 0, 0),
+ 40,
+ 80,
+ 16,
+ new Color(255, 128, 0)
+ );
+ shapes.addShape(standaloneCone);
+
+ viewPanel.repaintDuringNextViewUpdate();
+ }
+}
\ No newline at end of file
* @param args command line arguments (ignored)
*/
public static void main(String[] args) {
- ViewFrame viewFrame = new ViewFrame();
+ ViewFrame viewFrame = new ViewFrame("Minimal Example");
ShapeCollection shapes = viewFrame.getViewPanel().getRootShapeCollection();
viewFrame.getViewPanel().getCamera().getTransform().setTranslation(new Point3D(0, -100, -300));
/** Initializes the demo scene with grid, lights, shapes, and fractal pattern. */
private void init() {
- final ViewFrame viewFrame = new ViewFrame();
+ final ViewFrame viewFrame = new ViewFrame("Volumetric Octree");
viewPanel = viewFrame.getViewPanel();
viewPanel.getCamera().getTransform().set(104.13, -65.04, -370.53, 0.12, 0.14, 0);
/** Initializes the demo by creating the view frame and adding falling numbers. */
private void run() {
- final ViewFrame viewFrame = new ViewFrame();
+ final ViewFrame viewFrame = new ViewFrame("Raining Numbers");
viewFrame.getViewPanel().getCamera().getTransform().set(-129.75, 228.27, -220.69, -0.55, 0.54, 0);
*/
public static void main(final String[] args) {
- final ViewFrame viewFrame = new ViewFrame();
+ final ViewFrame viewFrame = new ViewFrame("Random Polygons");
viewFrame.getViewPanel().getCamera().getTransform().set(-52.96, -239.61, -1293.29, -0.09, -0.36, 0);
package eu.svjatoslav.sixth.e3d.examples;
import eu.svjatoslav.sixth.e3d.geometry.Point3D;
+import eu.svjatoslav.sixth.e3d.gui.FrameListener;
import eu.svjatoslav.sixth.e3d.gui.ViewFrame;
import eu.svjatoslav.sixth.e3d.gui.ViewPanel;
-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.lighting.LightSource;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.line.LineAppearance;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.ForwardOrientedTextBlock;
import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.LightSourceMarker;
-import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.solid.SolidPolygonCube;
-import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.solid.SolidPolygonCylinder;
-import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.solid.SolidPolygonPyramid;
-import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.solid.SolidPolygonSphere;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.solid.*;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.wireframe.*;
import java.util.ArrayList;
import java.util.List;
import static eu.svjatoslav.sixth.e3d.math.Transform.fromAngles;
/**
- * Demo showing a shaded sphere, cube, pyramid, and cylinder with multiple colored light sources.
- * Ten light sources orbit around the shapes on different paths to demonstrate dynamic lighting.
+ * Gallery demo showcasing all available 3D shapes in the Sixth 3D engine.
+ *
+ * <p>This demo displays a 7x2 grid of shapes organized by type (columns) and
+ * rendering style (rows). The top row shows solid polygon shapes, and the bottom
+ * row shows wireframe shapes. Each column represents a different shape type:</p>
+ *
+ * <pre>
+ * Arrow Cone Cube Cylinder Pyramid Box Sphere
+ * ┌────────┬────────┬────────┬────────┬────────┬────────┬────────┐
+ * Solid │ ████ │ /\\ │ ████ │ ║║║ │ /\\ │ ████ │ () │
+ * │ ████ │ / \\ │ ████ │ ║║║ │ /__\\ │ ████ │ ( ) │
+ * ├────────┼────────┼────────┼────────┼────────┼────────┼────────┤
+ * Wirefrm │ ╔══╗ │ /\\ │ ╔══╗ │ ║║║ │ /\\ │ ╔══╗ │ () │
+ * │ ╚══╝ │ / \\ │ ╚══╝ │ ║║║ │ /__\\ │ ╚══╝ │ ( ) │
+ * └────────┴────────┴────────┴────────┴────────┴────────┴────────┘
+ * </pre>
+ *
+ * <p>Features:</p>
+ * <ul>
+ * <li>Orbiting colored lights for dynamic lighting demonstration</li>
+ * <li>Floor grid showing the layout structure</li>
+ * <li>Text labels identifying each shape type</li>
+ * </ul>
*/
public class ShadedShapesDemo {
/**
- * Creates a new ShadedShapesDemo instance.
+ * Number of columns (shape types).
*/
- public ShadedShapesDemo() {
- }
+ private static final int COLUMN_COUNT = 7;
+
+ /**
+ * Size of each cell in world units.
+ */
+ private static final double CELL_SIZE = 250;
- /** Number of orbiting light sources in the scene. */
+ /**
+ * Radius/size for most shapes.
+ */
+ private static final double SHAPE_RADIUS = 50;
+
+ /**
+ * Number of segments for smooth curved shapes.
+ */
+ private static final int SEGMENTS = 16;
+
+ /**
+ * Y offset for labels above shapes.
+ */
+ private static final double LABEL_Y_OFFSET = -100;
+
+ /**
+ * Number of orbiting light sources in the scene.
+ */
private static final int LIGHT_COUNT = 10;
+ /**
+ * Color palette - one color per column (shape type).
+ */
+ private static final Color[] SHAPE_COLORS = {
+ new Color(255, 100, 100), // Arrow - Red
+ new Color(255, 180, 100), // Cone - Orange
+ new Color(255, 255, 100), // Cube - Yellow
+ new Color(100, 255, 100), // Cylinder - Green
+ new Color(100, 255, 255), // Pyramid - Cyan
+ new Color(100, 150, 255), // RectangularBox - Blue
+ new Color(200, 150, 255), // Sphere - Purple
+ };
+
+ /**
+ * Shape type names for labels.
+ */
+ private static final String[] SHAPE_NAMES = {
+ "Arrow",
+ "Cone",
+ "Cube",
+ "Cylinder",
+ "Pyramid",
+ "Box",
+ "Sphere",
+ };
+
/**
* Entry point for the shaded shapes demo.
+ *
* @param args command line arguments (ignored)
*/
public static void main(final String[] args) {
- final ViewFrame viewFrame = new ViewFrame();
+ final ViewFrame viewFrame = new ViewFrame("3D Shape Gallery");
final ViewPanel viewPanel = viewFrame.getViewPanel();
final ShapeCollection shapes = viewPanel.getRootShapeCollection();
- viewPanel.getCamera().getTransform().setTranslation(new Point3D(200, -250, -900));
+ // Position camera to view the entire gallery
+ viewPanel.getCamera().getTransform().set(-615.31, -299.50, -378.64, -0.62, -0.66, 0.00);
+
+ // Set up lighting
+ viewPanel.getLightingManager().setAmbientLight(new Color(40, 40, 50));
+
+ // Create floor grid
+ createFloorGrid(shapes);
+
+ // Create all shapes
+ createAllShapes(shapes);
+
+ // Create orbiting lights
+ createOrbitingLights(viewPanel, shapes);
+
+ viewPanel.repaintDuringNextViewUpdate();
+ }
+
+ /**
+ * Creates the floor grid that outlines the gallery cells.
+ *
+ * @param shapes the shape collection to add the grid to
+ */
+ private static void createFloorGrid(final ShapeCollection shapes) {
+ final LineAppearance gridAppearance = new LineAppearance(1, new Color(80, 80, 100));
+
+ // Calculate grid bounds: 7 columns, 2 rows, centered around origin
+ final double halfWidth = (COLUMN_COUNT * CELL_SIZE) / 2.0;
+ final double gridDepth = 2 * CELL_SIZE;
+
+ final Point3D cornerA = new Point3D(-halfWidth, 0, -CELL_SIZE / 2);
+ final Point3D cornerB = new Point3D(halfWidth, 0, gridDepth - CELL_SIZE / 2);
+
+ final Grid3D grid = new Grid3D(cornerA, cornerB, CELL_SIZE, gridAppearance);
+ shapes.addShape(grid);
+ }
+
+ /**
+ * Creates all solid and wireframe shapes in the gallery grid.
+ *
+ * @param shapes the shape collection to add shapes to
+ */
+ private static void createAllShapes(final ShapeCollection shapes) {
+ for (int col = 0; col < COLUMN_COUNT; col++) {
+ final double x = getColumnX(col);
+ final Color color = SHAPE_COLORS[col];
+ final String name = SHAPE_NAMES[col];
+
+ // Row 0: Solid polygon shapes
+ final Point3D solidPos = new Point3D(x, 0, 0);
+ createSolidShape(shapes, col, solidPos, color);
+ createLabel(shapes, solidPos, name, color);
+
+ // Row 1: Wireframe shapes
+ final Point3D wireframePos = new Point3D(x, 0, CELL_SIZE);
+ createWireframeShape(shapes, col, wireframePos, color);
+ }
+ }
+
+ /**
+ * Calculates the X coordinate for a given column index.
+ *
+ * @param col the column index (0-6)
+ * @return the X coordinate in world units
+ */
+ private static double getColumnX(final int col) {
+ return (col - (COLUMN_COUNT - 1) / 2.0) * CELL_SIZE;
+ }
+
+ /**
+ * Creates a solid polygon shape for the given column.
+ *
+ * @param shapes the shape collection
+ * @param col the column index (determines shape type)
+ * @param pos the center position
+ * @param color the shape color
+ */
+ private static void createSolidShape(final ShapeCollection shapes, final int col,
+ final Point3D pos, final Color color) {
+ switch (col) {
+ case 0: // Arrow
+ final SolidPolygonArrow arrow = new SolidPolygonArrow(
+ new Point3D(pos.x, SHAPE_RADIUS / 2, pos.z),
+ new Point3D(pos.x, -SHAPE_RADIUS / 2, pos.z),
+ 8, 20, 40, 12, color);
+ arrow.setShadingEnabled(true);
+ shapes.addShape(arrow);
+ break;
+
+ case 1: // Cone (pointing upward)
+ final SolidPolygonCone cone = new SolidPolygonCone(
+ new Point3D(pos.x, -SHAPE_RADIUS, pos.z), // apex above
+ new Point3D(pos.x, SHAPE_RADIUS / 2, pos.z), // base below
+ SHAPE_RADIUS * 0.8, SEGMENTS, color);
+ cone.setShadingEnabled(true);
+ shapes.addShape(cone);
+ break;
+
+ case 2: // Cube
+ final SolidPolygonCube cube = new SolidPolygonCube(pos, SHAPE_RADIUS * 0.8, color);
+ cube.setShadingEnabled(true);
+ shapes.addShape(cube);
+ break;
+
+ case 3: // Cylinder
+ final SolidPolygonCylinder cylinder = new SolidPolygonCylinder(
+ new Point3D(pos.x, SHAPE_RADIUS, pos.z),
+ new Point3D(pos.x, -SHAPE_RADIUS, pos.z),
+ SHAPE_RADIUS * 0.7, SEGMENTS, color);
+ cylinder.setShadingEnabled(true);
+ shapes.addShape(cylinder);
+ break;
+
+ case 4: // Pyramid
+ final SolidPolygonPyramid pyramid = new SolidPolygonPyramid(
+ new Point3D(pos.x, -SHAPE_RADIUS, pos.z), // apex above
+ new Point3D(pos.x, SHAPE_RADIUS / 2, pos.z), // base below
+ SHAPE_RADIUS * 0.8, color);
+ pyramid.setShadingEnabled(true);
+ shapes.addShape(pyramid);
+ break;
+
+ case 5: // RectangularBox
+ final SolidPolygonRectangularBox box = new SolidPolygonRectangularBox(
+ new Point3D(pos.x - SHAPE_RADIUS * 0.7, pos.y - SHAPE_RADIUS * 0.5, pos.z - SHAPE_RADIUS * 0.6),
+ new Point3D(pos.x + SHAPE_RADIUS * 0.7, pos.y + SHAPE_RADIUS * 0.5, pos.z + SHAPE_RADIUS * 0.6),
+ color);
+ box.setShadingEnabled(true);
+ shapes.addShape(box);
+ break;
+
+ case 6: // Sphere
+ final SolidPolygonSphere sphere = new SolidPolygonSphere(pos, SHAPE_RADIUS, SEGMENTS, color);
+ sphere.setShadingEnabled(true);
+ shapes.addShape(sphere);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Creates a wireframe shape for the given column.
+ *
+ * @param shapes the shape collection
+ * @param col the column index (determines shape type)
+ * @param pos the center position
+ * @param color the line color
+ */
+ private static void createWireframeShape(final ShapeCollection shapes, final int col,
+ final Point3D pos, final Color color) {
+ final LineAppearance appearance = new LineAppearance(2, color);
+
+ switch (col) {
+ case 0: // Arrow
+ final WireframeArrow arrow = new WireframeArrow(
+ new Point3D(pos.x, SHAPE_RADIUS / 2, pos.z),
+ new Point3D(pos.x, -SHAPE_RADIUS / 2, pos.z),
+ 8, 20, 40, 12, appearance);
+ shapes.addShape(arrow);
+ break;
- // Use the global lighting manager from ViewPanel
- viewPanel.getLightingManager().setAmbientLight(new Color(25, 25, 25));
+ case 1: // Cone
+ final WireframeCone cone = new WireframeCone(
+ new Point3D(pos.x, -SHAPE_RADIUS, pos.z), // apex above
+ new Point3D(pos.x, SHAPE_RADIUS / 2, pos.z), // base below
+ SHAPE_RADIUS * 0.8, SEGMENTS, appearance);
+ shapes.addShape(cone);
+ break;
+ case 2: // Cube
+ final WireframeCube cube = new WireframeCube(pos, SHAPE_RADIUS * 0.8, appearance);
+ shapes.addShape(cube);
+ break;
+
+ case 3: // Cylinder
+ final WireframeCylinder cylinder = new WireframeCylinder(
+ new Point3D(pos.x, SHAPE_RADIUS, pos.z),
+ new Point3D(pos.x, -SHAPE_RADIUS, pos.z),
+ SHAPE_RADIUS * 0.7, SEGMENTS, appearance);
+ shapes.addShape(cylinder);
+ break;
+
+ case 4: // Pyramid
+ final WireframePyramid pyramid = new WireframePyramid(
+ new Point3D(pos.x, -SHAPE_RADIUS, pos.z), // apex above
+ new Point3D(pos.x, SHAPE_RADIUS / 2, pos.z), // base below
+ SHAPE_RADIUS * 0.8, appearance);
+ shapes.addShape(pyramid);
+ break;
+
+ case 5: // Box (WireframeBox)
+ final WireframeBox box = new WireframeBox(
+ new Point3D(pos.x - SHAPE_RADIUS * 0.7, pos.y - SHAPE_RADIUS * 0.5, pos.z - SHAPE_RADIUS * 0.6),
+ new Point3D(pos.x + SHAPE_RADIUS * 0.7, pos.y + SHAPE_RADIUS * 0.5, pos.z + SHAPE_RADIUS * 0.6),
+ appearance);
+ shapes.addShape(box);
+ break;
+
+ case 6: // Sphere
+ final WireframeSphere sphere = new WireframeSphere(pos, (float) SHAPE_RADIUS, appearance);
+ shapes.addShape(sphere);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Creates a text label above a shape.
+ *
+ * @param shapes the shape collection
+ * @param pos the shape position
+ * @param text the label text
+ * @param color the text color
+ */
+ private static void createLabel(final ShapeCollection shapes, final Point3D pos,
+ final String text, final Color color) {
+ final Point3D labelPos = new Point3D(pos.x, pos.y + LABEL_Y_OFFSET, pos.z);
+ final ForwardOrientedTextBlock label = new ForwardOrientedTextBlock(
+ labelPos, 0.8, 2, text, color);
+ shapes.addShape(label);
+ }
+
+ /**
+ * Creates orbiting light sources around the scene.
+ *
+ * @param viewPanel the view panel
+ * @param shapes the shape collection
+ */
+ private static void createOrbitingLights(final ViewPanel viewPanel, final ShapeCollection shapes) {
final Random random = new Random(42);
final List<OrbitingLight> orbitingLights = new ArrayList<>();
random.nextInt(256)
);
- final double orbitRadius = 500 + random.nextInt(200);
- final double speed = 0.01 + random.nextDouble() * 0.03;
+ final double orbitRadius = 600 + random.nextInt(200);
+ final double speed = 0.01 + random.nextDouble() * 0.02;
final double angleOffset = random.nextDouble() * Math.PI * 2;
- final double intensity = 2.0 + random.nextDouble() * 3.0;
+ final double intensity = 2.0 + random.nextDouble() * 2.0;
final int axis = random.nextInt(3);
final double ellipseFactor = 0.7 + random.nextDouble() * 0.3;
- final LightSource light = new LightSource(new Point3D(0, 0, 0), color, intensity);
+ final LightSource light = new LightSource(new Point3D(0, 0, CELL_SIZE / 2), color, intensity);
final LightSourceMarker marker = new LightSourceMarker(light.getPosition(), color);
viewPanel.getLightingManager().addLight(light);
));
}
- // Sphere
- final SolidPolygonSphere sphere = new SolidPolygonSphere(
- new Point3D(-400, 0, 0), 150, 28, new Color(200, 210, 255)
- );
- sphere.setShadingEnabled(true);
- shapes.addShape(sphere);
-
- // Pyramid
- final SolidPolygonPyramid pyramid = new SolidPolygonPyramid(
- new Point3D(0, 130, 0), 150, 260, new Color(255, 200, 200)
- );
- pyramid.setShadingEnabled(true);
- shapes.addShape(pyramid);
-
- // Cube
- final SolidPolygonCube cube = new SolidPolygonCube(
- new Point3D(400, 0, 0), 150, new Color(200, 255, 200)
- );
- cube.setShadingEnabled(true);
- shapes.addShape(cube);
-
- // Cylinder
- final SolidPolygonCylinder cylinder = new SolidPolygonCylinder(
- new Point3D(800, 0, 0), 120, 260, 24, new Color(255, 220, 180)
- );
- cylinder.setShadingEnabled(true);
- shapes.addShape(cylinder);
-
final MultiLightAnimator animator = new MultiLightAnimator(orbitingLights);
viewPanel.addFrameListener(animator);
-
- viewPanel.repaintDuringNextViewUpdate();
}
/**
* Represents a light source that orbits around the scene center.
- * Each light follows an elliptical path on one of three possible axes.
*/
private static class OrbitingLight {
final LightSource light;
final double ellipseFactor;
double angle;
- /**
- * Creates an orbiting light with the specified parameters.
- * @param light the light source to orbit
- * @param marker the visual marker for the light position
- * @param orbitRadius the base radius of the orbit
- * @param speed the angular speed of orbit
- * @param angleOffset the starting angle offset
- * @param axis the axis of orbit (0, 1, or 2)
- * @param ellipseFactor the ellipse distortion factor
- */
- OrbitingLight(LightSource light, LightSourceMarker marker,
- double orbitRadius, double speed, double angleOffset,
- int axis, double ellipseFactor) {
+ OrbitingLight(final LightSource light, final LightSourceMarker marker,
+ final double orbitRadius, final double speed, final double angleOffset,
+ final int axis, final double ellipseFactor) {
this.light = light;
this.marker = marker;
this.orbitRadius = orbitRadius;
}
/**
- * Frame listener that animates all orbiting lights each frame.
- * Updates light positions based on their individual orbital parameters.
+ * Frame listener that animates all orbiting lights.
*/
- private static class MultiLightAnimator implements eu.svjatoslav.sixth.e3d.gui.FrameListener {
- private final List<OrbitingLight> lights;
+ private record MultiLightAnimator(List<OrbitingLight> lights) implements FrameListener {
- /**
- * Creates an animator for the specified lights.
- * @param lights the list of lights to animate
- */
- MultiLightAnimator(List<OrbitingLight> lights) {
- this.lights = lights;
- }
-
- /**
- * Updates all light positions each frame.
- * @param viewPanel the view panel
- * @param millisecondsSinceLastFrame time elapsed since last frame
- * @return true to continue animation
- */
@Override
- public boolean onFrame(ViewPanel viewPanel, int millisecondsSinceLastFrame) {
- for (OrbitingLight orbitingLight : lights) {
+ public boolean onFrame(final ViewPanel viewPanel, final int millisecondsSinceLastFrame) {
+ final double centerY = CELL_SIZE / 2;
+
+ for (final OrbitingLight orbitingLight : lights) {
orbitingLight.angle += orbitingLight.speed * millisecondsSinceLastFrame / 100;
- double r = orbitingLight.orbitRadius;
- double e = orbitingLight.ellipseFactor;
+ final double r = orbitingLight.orbitRadius;
+ final double e = orbitingLight.ellipseFactor;
double x, y, z;
switch (orbitingLight.axis) {
break;
}
- Point3D newPosition = new Point3D(x, y + 50, z);
+ final Point3D newPosition = new Point3D(x, y + centerY, z);
orbitingLight.light.setPosition(newPosition);
orbitingLight.marker.setTransform(fromAngles(
newPosition.x, newPosition.y, newPosition.z, 0, 0, 0));
return true;
}
}
-}
+}
\ No newline at end of file
*/
public static void main(final String[] args) {
- final ViewFrame viewFrame = new ViewFrame();
+ final ViewFrame viewFrame = new ViewFrame("Sine Heightmap");
final ShapeCollection geometryCollection = viewFrame.getViewPanel()
.getRootShapeCollection();
*/
public static void main(final String[] args) {
- final ViewFrame viewFrame = new ViewFrame();
+ final ViewFrame viewFrame = new ViewFrame("Text Editors");
final ViewPanel viewPanel = viewFrame.getViewPanel();
viewPanel.getCamera().getTransform().set(500, -300, -800, 0.6, -0.5, 0);
* @throws IOException if demo text file cannot be read
*/
public void build() throws URISyntaxException, IOException {
- final ViewFrame viewFrame = new ViewFrame();
+ final ViewFrame viewFrame = new ViewFrame("Text Editors City");
final ViewPanel viewPanel = viewFrame.getViewPanel();
viewPanel.getCamera().getTransform().set(500, -300, -800, 0.6, -0.5, 0);
* @param args command line arguments (ignored)
*/
public static void main(String[] args) {
- ViewFrame viewFrame = new ViewFrame();
+ ViewFrame viewFrame = new ViewFrame("Winding Order Demo");
ViewPanel viewPanel = viewFrame.getViewPanel();
ShapeCollection shapes = viewPanel.getRootShapeCollection();
}
private void initializeWindow() {
- viewFrame = new ViewFrame(WINDOW_WIDTH, WINDOW_HEIGHT);
+ viewFrame = new ViewFrame("Graphics Benchmark", WINDOW_WIDTH, WINDOW_HEIGHT);
viewPanel = viewFrame.getViewPanel();
viewPanel.setFrameRate(0);
shapes = viewPanel.getRootShapeCollection();
+++ /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.diamondsquare_demo;
-
-import eu.svjatoslav.sixth.e3d.geometry.Point3D;
-import eu.svjatoslav.sixth.e3d.math.DiamondSquare;
-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;
-
-/**
- * A procedurally generated terrain mesh using the diamond-square algorithm.
- * Creates a grid of triangular polygons with height variation for mountains.
- */
-public class DiamondSquareTerrain extends AbstractCompositeShape {
-
- private static final double TERRAIN_SIZE = 800.0;
-
- /**
- * Creates a diamond-square terrain with the specified parameters.
- *
- * @param gridSize the size of the heightmap grid (must be 2^n + 1)
- * @param minHeight the minimum terrain height
- * @param maxHeight the maximum terrain height
- * @param seed random seed for reproducible terrain
- */
- public DiamondSquareTerrain(final int gridSize, final double minHeight, final double maxHeight, final long seed) {
- super();
-
- final double[][] heightmap = DiamondSquare.generateMap(gridSize, minHeight, maxHeight, seed);
- createPolygons(gridSize, heightmap);
- setBackfaceCulling(true);
- }
-
- /**
- * Creates triangular polygons from the heightmap.
- */
- private void createPolygons(final int gridSize, final double[][] heightmap) {
- final double cellSize = TERRAIN_SIZE / (gridSize - 1);
- final double offsetX = -TERRAIN_SIZE / 2;
- final double offsetZ = -TERRAIN_SIZE / 2;
-
- for (int z = 0; z < gridSize - 1; z++) {
- for (int x = 0; x < gridSize - 1; x++) {
- final double x0 = offsetX + x * cellSize;
- final double x1 = offsetX + (x + 1) * cellSize;
- final double z0 = offsetZ + z * cellSize;
- final double z1 = offsetZ + (z + 1) * cellSize;
-
- final double y00 = heightmap[z][x];
- final double y10 = heightmap[z][x + 1];
- final double y01 = heightmap[z + 1][x];
- final double y11 = heightmap[z + 1][x + 1];
-
- final Color color = new Color(10, 10, 10);
-
- final Point3D p00 = new Point3D(x0, y00, z0);
- final Point3D p10 = new Point3D(x1, y10, z0);
- final Point3D p01 = new Point3D(x0, y01, z1);
- final Point3D p11 = new Point3D(x1, y11, z1);
-
- final SolidPolygon tri1 = new SolidPolygon(p00, p10, p01, color);
- final SolidPolygon tri2 = new SolidPolygon(p10, p11, p01, color);
-
- tri1.setShadingEnabled(true);
- tri2.setShadingEnabled(true);
-
- addShape(tri1);
- addShape(tri2);
- }
- }
- }
-}
\ No newline at end of file
+++ /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.diamondsquare_demo;
-
-import eu.svjatoslav.sixth.e3d.geometry.Point3D;
-import eu.svjatoslav.sixth.e3d.gui.ViewFrame;
-import eu.svjatoslav.sixth.e3d.gui.ViewPanel;
-import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
-import eu.svjatoslav.sixth.e3d.renderer.raster.ShapeCollection;
-import eu.svjatoslav.sixth.e3d.renderer.raster.lighting.LightSource;
-import eu.svjatoslav.sixth.e3d.renderer.raster.lighting.LightingManager;
-import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.LightSourceMarker;
-
-/**
- * Demo showing a procedurally generated mountain landscape using the diamond-square algorithm.
- * Three colored light sources (warm orange, cool cyan, neutral white) illuminate the terrain
- * from above, demonstrating dynamic flat shading.
- */
-public class TerrainDemo {
-
- /**
- * Entry point for the terrain demo.
- * @param args command line arguments (ignored)
- */
- public static void main(final String[] args) {
- final ViewFrame viewFrame = new ViewFrame();
- ViewPanel viewPanel = viewFrame.getViewPanel();
-
- viewPanel.getCamera().getTransform().set(-307.96, -847.50, -768.20, -0.52, -0.66, 0);
-
- final ShapeCollection shapes = viewPanel.getRootShapeCollection();
-
- setLights(viewFrame, shapes);
-
- shapes.addShape(new DiamondSquareTerrain(129, 0.0, 300.0, 42));
-
- viewPanel.repaintDuringNextViewUpdate();
- }
-
- /**
- * Sets up the lighting for the terrain scene.
- * @param viewFrame the view frame containing the lighting manager
- * @param shapes the shape collection to add light source markers to
- */
- private static void setLights(ViewFrame viewFrame, ShapeCollection shapes) {
- LightingManager lightingManager = viewFrame.getViewPanel().getLightingManager();
- lightingManager.setAmbientLight(new Color(250, 150, 100));
-
- final LightSource warmLight = new LightSource(
- new Point3D(-400, -500, 0),
- new Color(255, 180, 100),
- 190.0
- );
- final LightSource coolLight = new LightSource(
- new Point3D(400, -500, 0),
- new Color(100, 200, 255),
- 220.0
- );
- final LightSource neutralLight = new LightSource(
- new Point3D(0, -600, 300),
- new Color(255, 255, 255),
- 250.0
- );
-
- lightingManager.addLight(warmLight);
- lightingManager.addLight(coolLight);
- lightingManager.addLight(neutralLight);
-
- shapes.addShape(new LightSourceMarker(warmLight.getPosition(), new Color(255, 180, 100)));
- shapes.addShape(new LightSourceMarker(coolLight.getPosition(), new Color(100, 200, 255)));
- shapes.addShape(new LightSourceMarker(neutralLight.getPosition(), new Color(255, 255, 255)));
- }
-}
\ No newline at end of file
*/
public static void main(final String[] args) {
- final ViewFrame viewFrame = new ViewFrame();
+ final ViewFrame viewFrame = new ViewFrame("Point Cloud Galaxy");
viewFrame.getViewPanel().getCamera().getTransform().set(-1099.85, -2862.44, 144.32, -1.09, -0.60, 0);
*/
public static void main(final String[] args) {
- final ViewFrame viewFrame = new ViewFrame();
+ final ViewFrame viewFrame = new ViewFrame("Math Graphs");
final ShapeCollection geometryCollection = viewFrame.getViewPanel()
.getRootShapeCollection();
package eu.svjatoslav.sixth.e3d.examples.launcher;
-import eu.svjatoslav.sixth.e3d.examples.diamondsquare_demo.TerrainDemo;
+import eu.svjatoslav.sixth.e3d.examples.terrain_demo.TerrainDemo;
import eu.svjatoslav.sixth.e3d.examples.SineHeightmap;
import eu.svjatoslav.sixth.e3d.examples.graph_demo.MathGraphsDemo;
import eu.svjatoslav.sixth.e3d.examples.MinimalExample;
private void run() {
// create application frame visible to the user
- final ViewFrame viewFrame = new ViewFrame();
+ final ViewFrame viewFrame = new ViewFrame("Game of Life");
final ViewPanel viewPanel = viewFrame.getViewPanel();
viewPanel.getCamera().getTransform().set(100, -50, -200, 0.2f, -0.7f, 0);
--- /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.terrain_demo;
+
+import eu.svjatoslav.sixth.e3d.geometry.Point3D;
+import eu.svjatoslav.sixth.e3d.math.DiamondSquare;
+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;
+
+/**
+ * A procedurally generated terrain mesh using the diamond-square algorithm.
+ * Creates a grid of triangular polygons with height variation for mountains.
+ */
+public class DiamondSquareTerrain extends AbstractCompositeShape {
+
+ private static final double TERRAIN_SIZE = 800.0;
+
+ private final double[][] heightmap;
+ private final int gridSize;
+
+ /**
+ * Creates a diamond-square terrain with the specified parameters.
+ *
+ * @param gridSize the size of the heightmap grid (must be 2^n + 1)
+ * @param minHeight the minimum terrain height
+ * @param maxHeight the maximum terrain height
+ * @param seed random seed for reproducible terrain
+ */
+ public DiamondSquareTerrain(final int gridSize, final double minHeight, final double maxHeight, final long seed) {
+ super();
+
+ this.gridSize = gridSize;
+ this.heightmap = DiamondSquare.generateMap(gridSize, minHeight, maxHeight, seed);
+ createPolygons(gridSize, heightmap);
+ setBackfaceCulling(true);
+ }
+
+ /**
+ * Returns the terrain height at the specified world XZ coordinates.
+ *
+ * @param worldX the world X coordinate
+ * @param worldZ the world Z coordinate
+ * @return the terrain height at that position, or 0 if outside terrain bounds
+ */
+ public double getHeightAt(final double worldX, final double worldZ) {
+ final double cellSize = TERRAIN_SIZE / (gridSize - 1);
+ final double offsetX = -TERRAIN_SIZE / 2;
+ final double offsetZ = -TERRAIN_SIZE / 2;
+
+ final int gridX = (int) Math.round((worldX - offsetX) / cellSize);
+ final int gridZ = (int) Math.round((worldZ - offsetZ) / cellSize);
+
+ if (gridX < 0 || gridX >= gridSize || gridZ < 0 || gridZ >= gridSize) {
+ return 0;
+ }
+
+ return heightmap[gridZ][gridX];
+ }
+
+ /**
+ * Creates triangular polygons from the heightmap.
+ */
+ private void createPolygons(final int gridSize, final double[][] heightmap) {
+ final double cellSize = TERRAIN_SIZE / (gridSize - 1);
+ final double offsetX = -TERRAIN_SIZE / 2;
+ final double offsetZ = -TERRAIN_SIZE / 2;
+
+ for (int z = 0; z < gridSize - 1; z++) {
+ for (int x = 0; x < gridSize - 1; x++) {
+ final double x0 = offsetX + x * cellSize;
+ final double x1 = offsetX + (x + 1) * cellSize;
+ final double z0 = offsetZ + z * cellSize;
+ final double z1 = offsetZ + (z + 1) * cellSize;
+
+ final double y00 = heightmap[z][x];
+ final double y10 = heightmap[z][x + 1];
+ final double y01 = heightmap[z + 1][x];
+ final double y11 = heightmap[z + 1][x + 1];
+
+ final Color color = new Color(10, 10, 10);
+
+ final Point3D p00 = new Point3D(x0, y00, z0);
+ final Point3D p10 = new Point3D(x1, y10, z0);
+ final Point3D p01 = new Point3D(x0, y01, z1);
+ final Point3D p11 = new Point3D(x1, y11, z1);
+
+ final SolidPolygon tri1 = new SolidPolygon(p00, p10, p01, color);
+ final SolidPolygon tri2 = new SolidPolygon(p10, p11, p01, color);
+
+ tri1.setShadingEnabled(true);
+ tri2.setShadingEnabled(true);
+
+ addShape(tri1);
+ addShape(tri2);
+ }
+ }
+ }
+}
\ No newline at end of file
--- /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.terrain_demo;
+
+import eu.svjatoslav.sixth.e3d.geometry.Point3D;
+import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.base.AbstractCompositeShape;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.solid.SolidPolygonCylinder;
+
+/**
+ * A simple tree trunk made of a single cylinder.
+ * Positioned to extend through the full terrain height range.
+ *
+ * @see TerrainDemo
+ * @see SolidPolygonCylinder
+ */
+public class FractalTree extends AbstractCompositeShape {
+
+ private static final Color BROWN = new Color(139, 90, 43);
+
+ /**
+ * Creates a tree trunk at the specified base position.
+ *
+ * @param basePosition the position of the trunk base (on the terrain surface)
+ * @param trunkHeight the height of the trunk
+ * @param trunkRadius the radius of the trunk base
+ */
+ public FractalTree(final Point3D basePosition, final double trunkHeight,
+ final double trunkRadius) {
+ super();
+
+ // In Sixth 3D, Y increases downward (screen-space coordinates).
+ // The trunk extends upward from basePosition, so the top has a smaller Y value.
+ final Point3D topPosition = new Point3D(
+ basePosition.x,
+ basePosition.y - trunkHeight,
+ basePosition.z
+ );
+
+ final SolidPolygonCylinder trunk = new SolidPolygonCylinder(
+ basePosition, // start (bottom of trunk)
+ topPosition, // end (top of trunk)
+ trunkRadius,
+ 8,
+ BROWN);
+ trunk.setShadingEnabled(true);
+
+ addShape(trunk);
+ setBackfaceCulling(true);
+ }
+}
\ No newline at end of file
--- /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.terrain_demo;
+
+import eu.svjatoslav.sixth.e3d.geometry.Point3D;
+import eu.svjatoslav.sixth.e3d.gui.ViewFrame;
+import eu.svjatoslav.sixth.e3d.gui.ViewPanel;
+import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
+import eu.svjatoslav.sixth.e3d.renderer.raster.ShapeCollection;
+import eu.svjatoslav.sixth.e3d.renderer.raster.lighting.LightSource;
+import eu.svjatoslav.sixth.e3d.renderer.raster.lighting.LightingManager;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.LightSourceMarker;
+
+/**
+ * Demo showing a procedurally generated mountain landscape using the diamond-square algorithm.
+ * Three colored light sources (warm orange, cool cyan, neutral white) illuminate the terrain
+ * from above, demonstrating dynamic flat shading. A fractal tree stands at the center of the terrain.
+ */
+public class TerrainDemo {
+
+ /**
+ * Entry point for the terrain demo.
+ *
+ * @param args command line arguments (ignored)
+ */
+ public static void main(final String[] args) {
+ final ViewFrame viewFrame = new ViewFrame("Procedural Terrain");
+ ViewPanel viewPanel = viewFrame.getViewPanel();
+
+ viewPanel.getCamera().getTransform().set(-76.43, -72.05, -159.08, -0.64, -0.46, -0.00);
+
+ final ShapeCollection shapes = viewPanel.getRootShapeCollection();
+
+ setLights(viewFrame, shapes);
+
+ final DiamondSquareTerrain terrain = new DiamondSquareTerrain(129, 0.0, 100.0, 42);
+ shapes.addShape(terrain);
+
+ // Get terrain height at center and place tree trunk on it
+ final double terrainHeight = terrain.getHeightAt(0, 0);
+ shapes.addShape(new FractalTree(new Point3D(0, terrainHeight, 0), 30, 6));
+
+ viewPanel.repaintDuringNextViewUpdate();
+ }
+
+ /**
+ * Sets up the lighting for the terrain scene.
+ *
+ * @param viewFrame the view frame containing the lighting manager
+ * @param shapes the shape collection to add light source markers to
+ */
+ private static void setLights(ViewFrame viewFrame, ShapeCollection shapes) {
+ LightingManager lightingManager = viewFrame.getViewPanel().getLightingManager();
+ lightingManager.setAmbientLight(new Color(250, 150, 100));
+
+ final LightSource warmLight = new LightSource(
+ new Point3D(-400, -500, 0),
+ new Color(255, 180, 100),
+ 190.0
+ );
+ final LightSource coolLight = new LightSource(
+ new Point3D(400, -500, 0),
+ new Color(100, 200, 255),
+ 220.0
+ );
+ final LightSource neutralLight = new LightSource(
+ new Point3D(0, -600, 300),
+ new Color(255, 255, 255),
+ 250.0
+ );
+
+ lightingManager.addLight(warmLight);
+ lightingManager.addLight(coolLight);
+ lightingManager.addLight(neutralLight);
+
+ shapes.addShape(new LightSourceMarker(warmLight.getPosition(), new Color(255, 180, 100)));
+ shapes.addShape(new LightSourceMarker(coolLight.getPosition(), new Color(100, 200, 255)));
+ shapes.addShape(new LightSourceMarker(neutralLight.getPosition(), new Color(255, 255, 255)));
+ }
+}
\ No newline at end of file