+/*
+ * Sixth - System for data storage, computation, exploration and interaction.
+ * Copyright ©2012-2016, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 3 of the GNU Lesser General Public License
+ * or later as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.sixth.e3d.examples;
+
+import eu.svjatoslav.sixth.e3d.geometry.Point3D;
+import eu.svjatoslav.sixth.e3d.geometry.Transform;
+import eu.svjatoslav.sixth.e3d.gui.ViewContext;
+import eu.svjatoslav.sixth.e3d.gui.ViewFrame;
+import eu.svjatoslav.sixth.e3d.gui.humaninput.WorldNavigationTracker;
+import eu.svjatoslav.sixth.e3d.renderer.octree.OctreeVolume;
+import eu.svjatoslav.sixth.e3d.renderer.octree.raytracer.Camera;
+import eu.svjatoslav.sixth.e3d.renderer.octree.raytracer.LightSource;
+import eu.svjatoslav.sixth.e3d.renderer.octree.raytracer.RayTracer;
+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.GlowingPoint;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.line.LineAppearance;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.LightSourceMarker;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.solid.SolidPolygonRectangularBox;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.textcanvas.TextCanvas;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.wireframe.Grid3D;
+
+import java.awt.event.KeyEvent;
+import java.io.IOException;
+import java.util.Vector;
+
+public class OctreeDemo extends WorldNavigationTracker {
+
+ private static final double magnification = 5;
+ private final LineAppearance gridAppearance = new LineAppearance(40, new Color(255,
+ 0, 0, 60));
+ private final Vector<LightSource> lights = new Vector<>();
+ private OctreeVolume octreeVolume;
+ private ShapeCollection shapeCollection;
+ private ViewContext context;
+
+ public static void main(final String[] args) throws IOException {
+ new OctreeDemo().init();
+ }
+
+ private void addLight(final Point3D location, final Color color,
+ final float brightness) {
+ shapeCollection.addShape(new LightSourceMarker(new Point3D(location)
+ .scaleUp(magnification), color));
+
+ final LightSource lightSource = new LightSource(location, color,
+ brightness);
+
+ lights.add(lightSource);
+ }
+
+ private void dotSpiral() {
+ for (double i = 0; i < 20; i = i + .1) {
+
+ double w = 1;
+ double h = 1;
+
+ final double x = Math.sin(i) * 20f * h;
+ final double y = Math.cos(i) * 20f * w;
+ final double c1 = (Math.cos(i * 3f) * 100) + 127;
+ final double c2 = (Math.cos(i * 5.3332f) * 100f) + 127;
+ final double c3 = (Math.cos(i * 1.342f) * 100f) + 127;
+
+ putPixel((int) x, (int) y, (int) (i * 4f), new Color((int) c1,
+ (int) c2, (int) c3, 255));
+ }
+ }
+
+ private void fractal(final int x, final int y, final int z, final int size,
+ final int step) {
+ final double c1 = (Math.cos(y / 7f) * 100f) + 127;
+ final double c2 = (Math.cos(x / 10f) * 100f) + 127;
+ final double c3 = (Math.cos(z / 12f) * 100f) + 127;
+
+ putRect(x - size, y - size, z - size, x + size, y + size, z + size,
+ new Color((int) c1, (int) c2, (int) c3, 100));
+
+ if (size > 1) {
+ fractal(x, y - (size * 3), z, size / 2, step + 1);
+ fractal(x + (size * 3), y, z, size / 2, step + 1);
+ fractal(x, y, z + (size * 3), size / 2, step + 1);
+ }
+ }
+
+ private void init() throws IOException {
+
+ final ViewFrame viewFrame = new ViewFrame();
+ context = viewFrame.getView().getContext();
+
+ context.getAvatar().setLocation(new Point3D(0, -30, -300));
+
+ octreeVolume = new OctreeVolume();
+
+ shapeCollection = context.getRootShapeCollection();
+
+ shapeCollection.addShape(new Grid3D(
+ new Point3D(-10000, -10000, -10000), new Point3D(10000, 10000,
+ 10000), 4000, gridAppearance));
+
+ // yellow light
+ addLight(new Point3D(20, -450, 240), new Color(255, 255, 255, 255), 100);
+
+ // red light
+ addLight(new Point3D(-150, -116, 141), new Color(255, 0, 0, 255), 10);
+
+ dotSpiral();
+
+ // arbitrary rectangles
+ putRect(-10, -10, -10, 10, 10, -20, new Color(200, 255, 200, 100));
+ putRect(-3, 0, -30, 12, 3, 300, new Color(255, 200, 200, 100));
+ putRect(-20, 20, -20, 20, 80, 20, new Color(255, 200, 255, 100));
+
+ tiledFloor();
+
+ fractal(-50, 20, 100, 32, 1);
+
+ final TextCanvas message = new TextCanvas(new Transform(new Point3D(
+ -10, 20, -180)), "Press \"r\" to raytrace current wiew",
+ Color.WHITE, Color.PURPLE);
+ shapeCollection.addShape(message);
+
+ context.getKeyboardFocusTracker().setFocusOwner(this);
+ context.getView().repaintDuringNextViewUpdate();
+ }
+
+ @Override
+ public void keyPressed(final KeyEvent event, final ViewContext viewContext) {
+
+ if ('r' == event.getKeyChar()) {
+ raytrace();
+ return;
+ }
+ super.keyPressed(event, viewContext);
+ }
+
+ private void putPixel(final int x, final int y, final int z,
+ final Color color) {
+ shapeCollection.addShape(new GlowingPoint(new Point3D(x, y, z)
+ .scaleUp(magnification), 3 * magnification, color));
+ octreeVolume.putCell(x, y, z, color);
+
+ }
+
+ private void putRect(final int x1, final int y1, final int z1, final int x2,
+ final int y2, final int z2, final Color color) {
+
+ shapeCollection
+ .addShape(new SolidPolygonRectangularBox(
+ new Point3D(x1, y1, z1).scaleUp(magnification),
+ new Point3D(x2, y2, z2).scaleUp(magnification), color));
+
+ octreeVolume.fillRect3D(x1, y1, z1, x2, y2, z2, color);
+ }
+
+ private void raytrace() {
+ // create and add camera object to scene
+ final Camera camera = new Camera(context.getAvatar(), magnification);
+ shapeCollection.addShape(camera);
+
+ // initialize and start Raytracer in a separate thread
+ final RayTracer rayTracer = new RayTracer(camera.getTexture(),
+ octreeVolume, lights, camera, context.getView());
+ final Thread thread = new Thread(rayTracer);
+ thread.start();
+ }
+
+ private void tiledFloor() {
+ final int step = 40;
+ final int size = step - 15;
+ for (int x = -200; x < 200; x += step)
+ for (int z = -200; z < 200; z += step)
+ putRect(x, 100, z, x + size, 110, z + size, new Color(255, 255,
+ 255, 100));
+ }
+
+}