Updated readability of the code.
[sixth-3d-demos.git] / src / main / java / eu / svjatoslav / sixth / e3d / examples / OctreeDemo.java
1 /*
2  * Sixth 3D engine demos. Author: Svjatoslav Agejenko. 
3  * This project is released under Creative Commons Zero (CC0) license.
4  *
5 */
6
7 package eu.svjatoslav.sixth.e3d.examples;
8
9 import eu.svjatoslav.sixth.e3d.geometry.Point3D;
10 import eu.svjatoslav.sixth.e3d.gui.ViewFrame;
11 import eu.svjatoslav.sixth.e3d.gui.ViewPanel;
12 import eu.svjatoslav.sixth.e3d.gui.humaninput.WorldNavigationUserInputTracker;
13 import eu.svjatoslav.sixth.e3d.math.Transform;
14 import eu.svjatoslav.sixth.e3d.renderer.octree.IntegerPoint;
15 import eu.svjatoslav.sixth.e3d.renderer.octree.OctreeVolume;
16 import eu.svjatoslav.sixth.e3d.renderer.octree.raytracer.Camera;
17 import eu.svjatoslav.sixth.e3d.renderer.octree.raytracer.LightSource;
18 import eu.svjatoslav.sixth.e3d.renderer.octree.raytracer.RayTracer;
19 import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
20 import eu.svjatoslav.sixth.e3d.renderer.raster.ShapeCollection;
21 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.GlowingPoint;
22 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.line.LineAppearance;
23 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.LightSourceMarker;
24 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.solid.SolidPolygonRectangularBox;
25 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.textcanvas.TextCanvas;
26 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.wireframe.Grid3D;
27
28 import java.awt.event.KeyEvent;
29 import java.util.Vector;
30
31 public class OctreeDemo extends WorldNavigationUserInputTracker {
32
33     private static final double magnification = 5;
34     private final LineAppearance gridAppearance = new LineAppearance(40, new Color(255,
35             0, 0, 60));
36     private final Vector<LightSource> lights = new Vector<>();
37     private OctreeVolume octreeVolume;
38     private ShapeCollection shapeCollection;
39     private ViewPanel viewPanel;
40
41     public static void main(final String[] args) {
42         new OctreeDemo().init();
43     }
44
45     private void addLight(final Point3D location, final Color color,
46                           final float brightness) {
47         shapeCollection.addShape(new LightSourceMarker(new Point3D(location)
48                 .scaleUp(magnification), color));
49
50         final LightSource lightSource = new LightSource(location, color,
51                 brightness);
52
53         lights.add(lightSource);
54     }
55
56     private void dotSpiral() {
57         for (double i = 0; i < 20; i = i + .1) {
58
59             double w = 1;
60             double h = 1;
61
62             final double x = Math.sin(i) * 20f * h;
63             final double y = Math.cos(i) * 20f * w;
64             final double c1 = (Math.cos(i * 3f) * 100) + 127;
65             final double c2 = (Math.cos(i * 5.3332f) * 100f) + 127;
66             final double c3 = (Math.cos(i * 1.342f) * 100f) + 127;
67
68             putPixel((int) x, (int) y, (int) (i * 4f), new Color((int) c1,
69                     (int) c2, (int) c3, 255));
70         }
71     }
72
73     private void fractal(final int x, final int y, final int z, final int size,
74                          final int step) {
75         final double c1 = (Math.cos(y / 7f) * 100f) + 127;
76         final double c2 = (Math.cos(x / 10f) * 100f) + 127;
77         final double c3 = (Math.cos(z / 12f) * 100f) + 127;
78
79         putRect(
80                 new IntegerPoint( x - size, y - size, z - size),
81                 new IntegerPoint( x + size, y + size, z + size),
82                 new Color((int) c1, (int) c2, (int) c3, 100));
83
84         if (size > 1) {
85             fractal(x, y - (size * 3), z, size / 2, step + 1);
86             fractal(x + (size * 3), y, z, size / 2, step + 1);
87             fractal(x, y, z + (size * 3), size / 2, step + 1);
88         }
89     }
90
91     private void init() {
92
93         final ViewFrame viewFrame = new ViewFrame();
94         viewPanel = viewFrame.getViewPanel();
95
96         viewPanel.getAvatar().setLocation(new Point3D(0, -30, -300));
97
98         octreeVolume = new OctreeVolume();
99
100         shapeCollection = viewPanel.getRootShapeCollection();
101
102         shapeCollection.addShape(new Grid3D(
103                 new Point3D(-10000, -10000, -10000), new Point3D(10000, 10000,
104                 10000), 4000, gridAppearance));
105
106         // yellow light
107         addLight(new Point3D(20, -450, 240), new Color(255, 255, 255, 255), 100);
108
109         // red light
110         addLight(new Point3D(-150, -116, 141), new Color(255, 0, 0, 255), 10);
111
112         dotSpiral();
113
114         // arbitrary rectangles
115         putRect(new IntegerPoint(-10, -10, -10),
116                 new IntegerPoint(10, 10, -20),
117                 new Color(200, 255, 200, 100));
118
119         putRect(new IntegerPoint(-3, 0, -30),
120                 new IntegerPoint( 12, 3, 300),
121                 new Color(255, 200, 200, 100));
122
123         putRect(new IntegerPoint(-20, 20, -20),
124                 new IntegerPoint(20, 80, 20),
125                 new Color(255, 200, 255, 100));
126
127         tiledFloor();
128
129         fractal(-50, 20, 100, 32, 1);
130
131         final TextCanvas message = new TextCanvas(new Transform(new Point3D(
132                 -10, 20, -180)), "Press \"r\" to raytrace current view",
133                 Color.WHITE, Color.PURPLE);
134         shapeCollection.addShape(message);
135
136         viewPanel.getKeyboardFocusStack().pushFocusOwner(this);
137         viewPanel.repaintDuringNextViewUpdate();
138     }
139
140     @Override
141     public boolean keyPressed(final KeyEvent event, final ViewPanel viewPanel) {
142
143         if ('r' == event.getKeyChar()) {
144             raytrace();
145             return true;
146         }
147         return super.keyPressed(event, viewPanel);
148     }
149
150     private void putPixel(final int x, final int y, final int z,
151                           final Color color) {
152         shapeCollection.addShape(new GlowingPoint(new Point3D(x, y, z)
153                 .scaleUp(magnification), 3 * magnification, color));
154         octreeVolume.putCell(x, y, z, color);
155
156     }
157
158     private void putRect(IntegerPoint p1, IntegerPoint p2, final Color color) {
159
160         shapeCollection
161                 .addShape(new SolidPolygonRectangularBox(
162                         new Point3D(p1).scaleUp(magnification),
163                         new Point3D(p2).scaleUp(magnification), color));
164
165         octreeVolume.fillRectangle(p1, p2, color);
166     }
167
168     private void raytrace() {
169         // create and add camera object to scene
170         final Camera camera = new Camera(viewPanel.getAvatar(), magnification);
171         shapeCollection.addShape(camera);
172
173         // initialize and start Raytracer in a separate thread
174         final RayTracer rayTracer = new RayTracer(camera.getTexture(),
175                 octreeVolume, lights, camera, viewPanel);
176         final Thread thread = new Thread(rayTracer);
177         thread.start();
178     }
179
180     private void tiledFloor() {
181         final int step = 40;
182         final int size = step - 15;
183         Color color = new Color(255, 255, 255, 100);
184         for (int x = -200; x < 200; x += step)
185             for (int z = -200; z < 200; z += step)
186                 putRect(
187                         new IntegerPoint(x, 100, z),
188                         new IntegerPoint(x + size, 110, z + size),
189                         color);
190     }
191
192 }