# Run Point Cloud Galaxy demo
java -cp target/sixth-3d-demos.jar eu.svjatoslav.sixth.e3d.examples.galaxy_demo.PointCloudDemo
+
+# Run Winding Order demo (tests backface culling)
+java -cp target/sixth-3d-demos.jar eu.svjatoslav.sixth.e3d.examples.WindingOrderDemo
```
### Testing
├── TextEditorDemo.java
├── TextEditorDemo2.java
├── RainingNumbersDemo.java
+├── WindingOrderDemo.java - Tests winding order & backface culling
└── package-info.java
```
Implement `MouseInteractionController` for mouse events, or extend input tracker classes for keyboard input.
+### Polygon Winding Order
+
+When creating triangles with backface culling enabled, use CCW winding in screen space:
+- Vertex order: top → lower-left → lower-right (as seen from camera)
+- `signedArea < 0` = front-facing = visible
+- See `WindingOrderDemo.java` for a minimal example
+
## Documentation
Always make sure that documentation in`doc/index.org` stays up to date.
--- /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.solidpolygon.SolidPolygon;
+
+/**
+ * Demo to test winding order and backface culling documentation.
+ * <p>
+ * Creates one triangle with CCW winding (front face) following the docs:
+ * <ul>
+ * <li>upper-center → lower-left → lower-right</li>
+ * <li>Backface culling enabled</li>
+ * </ul>
+ * <p>
+ * Expected: green triangle visible (CCW = front face).
+ */
+public class WindingOrderDemo {
+
+ public static void main(String[] args) {
+ ViewFrame viewFrame = new ViewFrame();
+ ViewPanel viewPanel = viewFrame.getViewPanel();
+ ShapeCollection shapes = viewPanel.getRootShapeCollection();
+
+ double size = 150;
+
+ Point3D upperCenter = new Point3D(0, -size, 0);
+ Point3D lowerLeft = new Point3D(-size, +size, 0);
+ Point3D lowerRight = new Point3D(+size, +size, 0);
+
+ SolidPolygon triangle = new SolidPolygon(upperCenter, lowerLeft, lowerRight, Color.GREEN);
+ triangle.setBackfaceCulling(true);
+
+ shapes.addShape(triangle);
+
+ viewPanel.getCamera().getTransform().setTranslation(new Point3D(0, 0, -500));
+
+ viewPanel.ensureRenderThreadStarted();
+ }
+}
\ No newline at end of file