9e1f3ef5e975cac04dd941cee3528979941abe90
[sixth-3d-demos.git] / src / main / java / eu / svjatoslav / sixth / e3d / examples / OctreeDemo.java
1 /*
2  * Sixth - System for data storage, computation, exploration and interaction.
3  * Copyright ©2012-2016, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
4  * 
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of version 3 of the GNU Lesser General Public License
7  * or later as published by the Free Software Foundation.
8  */
9
10 package eu.svjatoslav.sixth.e3d.examples;
11
12 import eu.svjatoslav.sixth.e3d.geometry.Point3D;
13 import eu.svjatoslav.sixth.e3d.geometry.Transform;
14 import eu.svjatoslav.sixth.e3d.gui.ViewContext;
15 import eu.svjatoslav.sixth.e3d.gui.ViewFrame;
16 import eu.svjatoslav.sixth.e3d.gui.humaninput.WorldNavigationTracker;
17 import eu.svjatoslav.sixth.e3d.renderer.octree.OctreeVolume;
18 import eu.svjatoslav.sixth.e3d.renderer.octree.raytracer.Camera;
19 import eu.svjatoslav.sixth.e3d.renderer.octree.raytracer.LightSource;
20 import eu.svjatoslav.sixth.e3d.renderer.octree.raytracer.RayTracer;
21 import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
22 import eu.svjatoslav.sixth.e3d.renderer.raster.ShapeCollection;
23 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.GlowingPoint;
24 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.line.LineAppearance;
25 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.LightSourceMarker;
26 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.solid.SolidPolygonRectangularBox;
27 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.textcanvas.TextCanvas;
28 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.wireframe.Grid3D;
29
30 import java.awt.event.KeyEvent;
31 import java.io.IOException;
32 import java.util.Vector;
33
34 public class OctreeDemo extends WorldNavigationTracker {
35
36     private static final double magnification = 5;
37     private final LineAppearance gridAppearance = new LineAppearance(40, new Color(255,
38             0, 0, 60));
39     private final Vector<LightSource> lights = new Vector<>();
40     private OctreeVolume octreeVolume;
41     private ShapeCollection shapeCollection;
42     private ViewContext context;
43
44     public static void main(final String[] args) throws IOException {
45         new OctreeDemo().init();
46     }
47
48     private void addLight(final Point3D location, final Color color,
49                           final float brightness) {
50         shapeCollection.addShape(new LightSourceMarker(new Point3D(location)
51                 .scaleUp(magnification), color));
52
53         final LightSource lightSource = new LightSource(location, color,
54                 brightness);
55
56         lights.add(lightSource);
57     }
58
59     private void dotSpiral() {
60         for (double i = 0; i < 20; i = i + .1) {
61
62             double w = 1;
63             double h = 1;
64
65             final double x = Math.sin(i) * 20f * h;
66             final double y = Math.cos(i) * 20f * w;
67             final double c1 = (Math.cos(i * 3f) * 100) + 127;
68             final double c2 = (Math.cos(i * 5.3332f) * 100f) + 127;
69             final double c3 = (Math.cos(i * 1.342f) * 100f) + 127;
70
71             putPixel((int) x, (int) y, (int) (i * 4f), new Color((int) c1,
72                     (int) c2, (int) c3, 255));
73         }
74     }
75
76     private void fractal(final int x, final int y, final int z, final int size,
77                          final int step) {
78         final double c1 = (Math.cos(y / 7f) * 100f) + 127;
79         final double c2 = (Math.cos(x / 10f) * 100f) + 127;
80         final double c3 = (Math.cos(z / 12f) * 100f) + 127;
81
82         putRect(x - size, y - size, z - size, x + size, y + size, z + size,
83                 new Color((int) c1, (int) c2, (int) c3, 100));
84
85         if (size > 1) {
86             fractal(x, y - (size * 3), z, size / 2, step + 1);
87             fractal(x + (size * 3), y, z, size / 2, step + 1);
88             fractal(x, y, z + (size * 3), size / 2, step + 1);
89         }
90     }
91
92     private void init() throws IOException {
93
94         final ViewFrame viewFrame = new ViewFrame();
95         context = viewFrame.getView().getContext();
96
97         context.getAvatar().setLocation(new Point3D(0, -30, -300));
98
99         octreeVolume = new OctreeVolume();
100
101         shapeCollection = context.getRootShapeCollection();
102
103         shapeCollection.addShape(new Grid3D(
104                 new Point3D(-10000, -10000, -10000), new Point3D(10000, 10000,
105                 10000), 4000, gridAppearance));
106
107         // yellow light
108         addLight(new Point3D(20, -450, 240), new Color(255, 255, 255, 255), 100);
109
110         // red light
111         addLight(new Point3D(-150, -116, 141), new Color(255, 0, 0, 255), 10);
112
113         dotSpiral();
114
115         // arbitrary rectangles
116         putRect(-10, -10, -10, 10, 10, -20, new Color(200, 255, 200, 100));
117         putRect(-3, 0, -30, 12, 3, 300, new Color(255, 200, 200, 100));
118         putRect(-20, 20, -20, 20, 80, 20, new Color(255, 200, 255, 100));
119
120         tiledFloor();
121
122         fractal(-50, 20, 100, 32, 1);
123
124         final TextCanvas message = new TextCanvas(new Transform(new Point3D(
125                 -10, 20, -180)), "Press \"r\" to raytrace current wiew",
126                 Color.WHITE, Color.PURPLE);
127         shapeCollection.addShape(message);
128
129         context.getKeyboardFocusTracker().setFocusOwner(this);
130         context.getView().repaintDuringNextViewUpdate();
131     }
132
133     @Override
134     public void keyPressed(final KeyEvent event, final ViewContext viewContext) {
135
136         if ('r' == event.getKeyChar()) {
137             raytrace();
138             return;
139         }
140         super.keyPressed(event, viewContext);
141     }
142
143     private void putPixel(final int x, final int y, final int z,
144                           final Color color) {
145         shapeCollection.addShape(new GlowingPoint(new Point3D(x, y, z)
146                 .scaleUp(magnification), 3 * magnification, color));
147         octreeVolume.putCell(x, y, z, color);
148
149     }
150
151     private void putRect(final int x1, final int y1, final int z1, final int x2,
152                          final int y2, final int z2, final Color color) {
153
154         shapeCollection
155                 .addShape(new SolidPolygonRectangularBox(
156                         new Point3D(x1, y1, z1).scaleUp(magnification),
157                         new Point3D(x2, y2, z2).scaleUp(magnification), color));
158
159         octreeVolume.fillRect3D(x1, y1, z1, x2, y2, z2, color);
160     }
161
162     private void raytrace() {
163         // create and add camera object to scene
164         final Camera camera = new Camera(context.getAvatar(), magnification);
165         shapeCollection.addShape(camera);
166
167         // initialize and start Raytracer in a separate thread
168         final RayTracer rayTracer = new RayTracer(camera.getTexture(),
169                 octreeVolume, lights, camera, context.getView());
170         final Thread thread = new Thread(rayTracer);
171         thread.start();
172     }
173
174     private void tiledFloor() {
175         final int step = 40;
176         final int size = step - 15;
177         for (int x = -200; x < 200; x += step)
178             for (int z = -200; z < 200; z += step)
179                 putRect(x, 100, z, x + size, 110, z + size, new Color(255, 255,
180                         255, 100));
181     }
182
183 }