diff --git a/.gitignore b/.gitignore
index ebf49b8..7f595cf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,60 +1,7 @@
-# Created by .ignore support plugin (hsz.mobi)
-### Java template
-*.class
-
-# Mobile Tools for Java (J2ME)
-.mtj.tmp/
-
-# Package Files #
-*.jar
-*.war
-*.ear
-
-# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
-hs_err_pid*
-### JetBrains template
-# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
-# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
-
-# User-specific stuff:
-.idea/workspace.xml
-.idea/tasks.xml
-.idea/dictionaries
-.idea/vcs.xml
-.idea/jsLibraryMappings.xml
-
-# Sensitive or high-churn files:
-.idea/dataSources.ids
-.idea/dataSources.xml
-.idea/dataSources.local.xml
-.idea/sqlDataSources.xml
-.idea/dynamic.xml
-.idea/uiDesigner.xml
-
-# Gradle:
-.idea/gradle.xml
-.idea/libraries
-
-# Mongo Explorer plugin:
-.idea/mongoSettings.xml
-
-## File-based project format:
-*.iws
-
-## Plugin-specific files:
-
-# IntelliJ
-/out/
-
-# mpeltonen/sbt-idea plugin
-.idea_modules/
-
-# JIRA plugin
-atlassian-ide-plugin.xml
-
-# Crashlytics plugin (for Android Studio and IntelliJ)
-com_crashlytics_export_strings.xml
-crashlytics.properties
-crashlytics-build.properties
-fabric.properties
+.vscode/
+.settings/
+.classpath
+.project
+*.class
+bin/
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
deleted file mode 100644
index 96cc43e..0000000
--- a/.idea/compiler.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml
deleted file mode 100644
index e7bedf3..0000000
--- a/.idea/copyright/profiles_settings.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index 18d93cc..0000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index a89ad04..0000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/README.md b/README.md
index 71cb9fd..a410568 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,37 @@
-#Trivial Tracer
\ No newline at end of file
+# Trivial Tracer
+
+To compile the project run `make compile`.
+To start the tracers run `make run`.
+
+Run options can be passed through environment variables, the are:
+- `CORNEL=true` : Run the cornel room example instead of the spheres room.
+- `PATH_TRACE=true` : Uses a path tracer instead of a ray tracer.
+- `THREADS=true` : Enables multi-threading.
+
+#### Examples:
+```shell
+$ make run
+$ CORNEL=true make run
+$ PATH_TRACE=true make run
+$ CORNEL=true PATH_TRACE=true THREADS=true make run
+```
+
+### Spheres Room
+
+Ray tracing
+
+![](docs/spheres-room-rt.png)
+
+Path tracing
+
+![](docs/spheres-room-pt.png)
+
+### Cornel Room
+
+Ray tracing
+
+![](docs/cornel-room-rt.png)
+
+Path tracing
+
+![](docs/cornel-room-pt.png)
diff --git a/TrivialTracer.iml b/TrivialTracer.iml
deleted file mode 100644
index c90834f..0000000
--- a/TrivialTracer.iml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/docs/cornel-room-pt.png b/docs/cornel-room-pt.png
new file mode 100644
index 0000000..f66fbc2
Binary files /dev/null and b/docs/cornel-room-pt.png differ
diff --git a/docs/cornel-room-rt.png b/docs/cornel-room-rt.png
new file mode 100644
index 0000000..02a261b
Binary files /dev/null and b/docs/cornel-room-rt.png differ
diff --git a/docs/spheres-room-pt.png b/docs/spheres-room-pt.png
new file mode 100644
index 0000000..3cf33f8
Binary files /dev/null and b/docs/spheres-room-pt.png differ
diff --git a/docs/spheres-room-rt.png b/docs/spheres-room-rt.png
new file mode 100644
index 0000000..3e64a52
Binary files /dev/null and b/docs/spheres-room-rt.png differ
diff --git a/makefile b/makefile
new file mode 100644
index 0000000..6f625ca
--- /dev/null
+++ b/makefile
@@ -0,0 +1,5 @@
+build:
+ mvn clean compile
+
+run: build
+ mvn exec:exec
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..bba9204
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,48 @@
+
+
+ 4.0.0
+
+ trivialtracer
+ trivial-tracer
+ 1.0.0
+
+
+ 14
+ 14
+
+
+
+ ${project.basedir}/src
+ ${project.basedir}/bin
+
+
+ ${project.basedir}/res
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+
+ 14
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 1.6.0
+
+ java
+
+ -classpath
+
+ Main
+
+
+
+
+
+
+
diff --git a/model/back.obj b/res/model/back.obj
similarity index 100%
rename from model/back.obj
rename to res/model/back.obj
diff --git a/model/ceiling.obj b/res/model/ceiling.obj
similarity index 100%
rename from model/ceiling.obj
rename to res/model/ceiling.obj
diff --git a/model/cornellroom.sdl b/res/model/cornellroom.sdl
similarity index 100%
rename from model/cornellroom.sdl
rename to res/model/cornellroom.sdl
diff --git a/model/cube1.obj b/res/model/cube1.obj
similarity index 100%
rename from model/cube1.obj
rename to res/model/cube1.obj
diff --git a/model/cube2.obj b/res/model/cube2.obj
similarity index 100%
rename from model/cube2.obj
rename to res/model/cube2.obj
diff --git a/model/floor.obj b/res/model/floor.obj
similarity index 100%
rename from model/floor.obj
rename to res/model/floor.obj
diff --git a/model/leftwall.obj b/res/model/leftwall.obj
similarity index 100%
rename from model/leftwall.obj
rename to res/model/leftwall.obj
diff --git a/model/luzcornell.obj b/res/model/luzcornell.obj
similarity index 100%
rename from model/luzcornell.obj
rename to res/model/luzcornell.obj
diff --git a/model/rightwall.obj b/res/model/rightwall.obj
similarity index 100%
rename from model/rightwall.obj
rename to res/model/rightwall.obj
diff --git a/src/Main.java b/src/Main.java
index 14f3674..13723bb 100644
--- a/src/Main.java
+++ b/src/Main.java
@@ -1,8 +1,11 @@
+import java.io.IOException;
+import javax.swing.JFrame;
import loader.SDLLoader;
-import tracer.data.base.Matrix4;
import tracer.data.base.Vector3;
import tracer.data.visual.Color;
-import tracer.model.Model;
+import tracer.data.visual.Material;
+import tracer.model.Sphere;
+import tracer.renderer.AbstractRenderer;
import tracer.renderer.MTRenderer;
import tracer.renderer.PTRenderer;
import tracer.renderer.RTRenderer;
@@ -11,10 +14,7 @@
import tracer.scene.Display;
import tracer.scene.Scene;
import tracer.scene.display.JDisplay;
-import tracer.util.TTRand;
-import javax.swing.*;
-import java.io.IOException;
/**
* @author Pedro Henrique
@@ -22,33 +22,98 @@
public class Main {
public static void main(String[] args) throws IOException {
- Scene scene = SDLLoader.load("model\\cornellroom.sdl");
- Camera camera = new Camera(new Vector3(0, 0, 1f),
- Vector3.zero(), Vector3.up(), (float) Math.toRadians(25)
- );
- Display display = new JDisplay(650, 650);
+ var env = System.getenv();
+ boolean cornelExample = env.containsKey("CORNEL") && env.get("CORNEL").equals("true");
+ boolean pathTracer = env.containsKey("PATH_TRACE") && env.get("PATH_TRACE").equals("true");
+ boolean multiThreaded = env.containsKey("THREADS") && env.get("THREADS").equals("true");
+ System.out.println(cornelExample);
+ if (!cornelExample) spheres(pathTracer, multiThreaded);
+ else cornellRoom(pathTracer, multiThreaded);
+ }
+
+ static void frameUpdateConsumer(Renderer r) {
+ System.out.println(r.getFrameRate());
+ }
+
+ static void spheres(boolean pathTracer, boolean multiThreaded) {
+ Scene scene = new Scene();
+ Camera camera = new Camera(Vector3.back().scale(30).sum(Vector3.up().scale(10)), Vector3.up().scale(10));
+ Display display = new JDisplay(800, 800);
+ //
+
+ //
+ Material lightMat = new Material(Color.white());
+
+ Material redWallMat = new Material(Color.red(), 1, 0, 0, 1);
+ Material whiteWallMat = new Material(Color.white(), 1, 0, 0, 1);
+ Material greenWallMat = new Material(Color.green(), 1, 0, 0, 1);
+
+ Material sphere1Mat = new Material(Color.black(), 0, 1, 0, 1);
+ Material sphere2Mat = new Material(Color.black(), 0, 0, 1, 1.2f);
+ //
+
+ //
+ scene.addModel(new Sphere(Vector3.up().scale(19), 2, lightMat));
+
+ scene.addModel(new Sphere(Vector3.left().scale(10010), 10000, redWallMat));
+ scene.addModel(new Sphere(Vector3.forward().scale(10010), 10000, whiteWallMat));
+ scene.addModel(new Sphere(Vector3.up().scale(10020), 10000, whiteWallMat));
+ scene.addModel(new Sphere(Vector3.right().scale(10010), 10000, greenWallMat));
+ scene.addModel(new Sphere(Vector3.down().scale(10000), 10000, whiteWallMat));
+
+ scene.addModel(new Sphere(new Vector3(5, 5, 3), 5, sphere1Mat));
+ scene.addModel(new Sphere(new Vector3(-4, 3, 1), 3, sphere2Mat));
+
+ // scene
+ // .addModel(
+ // new Torus(redWallMat, Vector3.up().scale(8).sum(Vector3.forward().scale(7)), Vector3.forward(), 2f, 5f)
+ // );
JFrame frame = new JFrame();
- frame.setSize(700, 700);
+ frame.setSize(800, 800);
frame.add((JDisplay) display);
- Renderer renderer = new MTRenderer(new PTRenderer(scene, camera, display, Main::frameUpdateConsumer), 8);
+ frame.addWindowListener(new java.awt.event.WindowAdapter() {
+ @Override
+ public void windowClosing(java.awt.event.WindowEvent windowEvent) {
+ System.exit(0);
+ }
+ });
+
+ // Renderer renderer = new RTRenderer(scene, camera, display);
+ AbstractRenderer renderer = pathTracer
+ ? new PTRenderer(scene, camera, display, Main::frameUpdateConsumer)
+ : new RTRenderer(scene, camera, display, Main::frameUpdateConsumer);
+ if (multiThreaded) renderer = new MTRenderer(renderer, Runtime.getRuntime().availableProcessors());
renderer.start();
frame.setVisible(true);
}
- static void frameUpdateConsumer(Renderer r) {
- Vector3 cameraPosition = r.getCamera().getPosition();
- r.getCamera().setPosition(
- Matrix4.rotationY(
- (float) Math.toRadians(0) * r.getFrameTime()
- ).transformAsPoint(cameraPosition)
- );
- for (Model light : r.getScene().getLights()) {
- //light.getMaterial().setEmissiveColor(Color.white().scale(TTRand.range(0.1f, 1)));
- }
- System.out.println(r.getFrameRate());
+ static void cornellRoom(boolean pathTracer, boolean multiThreaded) throws IOException {
+ String scenePath = Main.class.getResource("model/cornellroom.sdl").getPath();
+ Scene scene = SDLLoader.load(scenePath);
+ Camera camera = new Camera(new Vector3(0, 0, 1f), Vector3.zero(), Vector3.up(), (float) Math.toRadians(25));
+ Display display = new JDisplay(800, 800);
+ JFrame frame = new JFrame();
+ frame.setSize(800, 800);
+ frame.add((JDisplay) display);
+
+ frame.addWindowListener(new java.awt.event.WindowAdapter() {
+ @Override
+ public void windowClosing(java.awt.event.WindowEvent windowEvent) {
+ System.exit(0);
+ }
+ });
+
+ AbstractRenderer renderer = pathTracer
+ ? new PTRenderer(scene, camera, display, Main::frameUpdateConsumer)
+ : new RTRenderer(scene, camera, display, Main::frameUpdateConsumer);
+ if (multiThreaded) renderer = new MTRenderer(renderer, Runtime.getRuntime().availableProcessors());
+ renderer.start();
+
+ frame.setVisible(true);
}
+
}
diff --git a/src/Main2.java b/src/Main2.java
deleted file mode 100644
index 12f1d3e..0000000
--- a/src/Main2.java
+++ /dev/null
@@ -1,88 +0,0 @@
-import tracer.data.base.Matrix4;
-import tracer.data.base.Vector3;
-import tracer.data.visual.Color;
-import tracer.data.visual.Material;
-import tracer.model.Model;
-import tracer.model.Sphere;
-import tracer.model.Torus;
-import tracer.renderer.MTRenderer;
-import tracer.renderer.PTRenderer;
-import tracer.renderer.RTRenderer;
-import tracer.renderer.Renderer;
-import tracer.scene.Camera;
-import tracer.scene.Display;
-import tracer.scene.Scene;
-import tracer.scene.display.JDisplay;
-
-import javax.swing.*;
-import java.io.IOException;
-
-/**
- * @author Pedro Henrique
- */
-public class Main2 {
-
- public static void main(String[] args) throws IOException {
-
- //
- Scene scene = new Scene();
- Camera camera = new Camera(Vector3.back().scale(30).sum(Vector3.up().scale(10)), Vector3.up().scale(10));
- Display display = new JDisplay(600, 600);
- //
-
- //
- Material lightMat = new Material(Color.white());
-
- Material redWallMat = new Material(Color.red(), 1, 0, 0, 1);
- Material whiteWallMat = new Material(Color.white(), 1, 0, 0, 1);
- Material greenWallMat = new Material(Color.green(), 1, 0, 0, 1);
-
- Material sphere1Mat = new Material(Color.black(), 0, 1, 0, 1);
- Material sphere2Mat = new Material(Color.black(), 0, 0, 1, 1.2f);
- //
-
- //
- scene.addModel(new Sphere(Vector3.up().scale(19), 2, lightMat));
-
- scene.addModel(new Sphere(Vector3.left().scale(10010), 10000, redWallMat));
- scene.addModel(new Sphere(Vector3.forward().scale(10010), 10000, whiteWallMat));
- scene.addModel(new Sphere(Vector3.up().scale(10020), 10000, whiteWallMat));
- scene.addModel(new Sphere(Vector3.right().scale(10010), 10000, greenWallMat));
- scene.addModel(new Sphere(Vector3.down().scale(10000), 10000, whiteWallMat));
-
- scene.addModel(new Sphere(new Vector3(5, 5, 3), 5, sphere1Mat));
- scene.addModel(new Sphere(new Vector3(-4, 3, 1), 3, sphere2Mat));
-
- //scene.addModel(new Torus(redWallMat, Vector3.up().scale(8).sum(Vector3.forward().scale(7)), Vector3.forward(), 2f, 5f));
- //
-
- JFrame frame = new JFrame();
- frame.setSize(700, 700);
- frame.add((JDisplay) display);
-
- frame.addWindowListener(new java.awt.event.WindowAdapter() {
- @Override
- public void windowClosing(java.awt.event.WindowEvent windowEvent) {
- System.exit(0);
- }
- });
-
- //Renderer renderer = new RTRenderer(scene, camera, display);
- Renderer renderer = new PTRenderer(scene, camera, display, Main2::frameUpdateConsumer);
- renderer.start();
-
- frame.setVisible(true);
- }
-
- static void frameUpdateConsumer(Renderer r) {
- Matrix4 rot = Matrix4.rotationY((float) Math.toRadians(10));
- for (Model m : r.getScene().getModels()) {
- if (m instanceof Torus) {
- Torus t = (Torus) m;
- t.setAxis(rot.transformAsDirection(t.getAxis()));
- }
- }
- System.out.println(r.getFrameRate());
-
- }
-}
diff --git a/src/loader/SDLLoader.java b/src/loader/SDLLoader.java
index b17f7d0..b929b3a 100644
--- a/src/loader/SDLLoader.java
+++ b/src/loader/SDLLoader.java
@@ -47,7 +47,7 @@ public static Scene load(String sdlFilePath) throws IOException {
));
break;
case "light":
- String objLightFilePath = path.getParent().toString() + "\\" + parts[1];
+ String objLightFilePath = path.getParent().toString() + "/" + parts[1];
Model light = OBJLoader.load(objLightFilePath);
Color emissiveColor = new Color(
@@ -58,7 +58,7 @@ public static Scene load(String sdlFilePath) throws IOException {
scene.addModel(light);
break;
case "object":
- String objFilePath = path.getParent().toString() + "\\" + parts[1];
+ String objFilePath = path.getParent().toString() + "/" + parts[1];
Model model = OBJLoader.load(objFilePath);
Color surfaceColor = new Color(
diff --git a/src/tracer/renderer/AbstractRenderer.java b/src/tracer/renderer/AbstractRenderer.java
index 5c25eb9..1004b28 100644
--- a/src/tracer/renderer/AbstractRenderer.java
+++ b/src/tracer/renderer/AbstractRenderer.java
@@ -1,5 +1,8 @@
package tracer.renderer;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Consumer;
import tracer.data.base.Matrix4;
import tracer.data.base.Vector3;
import tracer.data.trace.Hit;
@@ -10,11 +13,6 @@
import tracer.scene.Display;
import tracer.scene.Scene;
import tracer.util.TTRand;
-
-import java.util.Objects;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.Consumer;
-
/**
* Abstract Renderer implementation with the necessary objects and methods. Only the method {@link #renderPixel(Ray)}
* needs to be implemented to the renderer work, but the method {@link #renderFrame()} too can be override.
@@ -145,6 +143,11 @@ public void setDisplay(Display display) {
public void setFrameUpdate(Consumer frameUpdate) {
this.frameUpdate = frameUpdate;
}
+
+ @Override
+ public Consumer getFrameUpdate() {
+ return frameUpdate;
+ }
// Rendering thread methods
diff --git a/src/tracer/renderer/MTRenderer.java b/src/tracer/renderer/MTRenderer.java
index d6a715a..e2af067 100644
--- a/src/tracer/renderer/MTRenderer.java
+++ b/src/tracer/renderer/MTRenderer.java
@@ -1,5 +1,6 @@
package tracer.renderer;
+import java.util.concurrent.atomic.AtomicInteger;
import tracer.data.base.Matrix4;
import tracer.data.base.Vector3;
import tracer.data.trace.Ray;
@@ -8,9 +9,6 @@
import tracer.scene.Display;
import tracer.scene.Scene;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.function.Consumer;
-
/**
* @author Pedro Henrique
*/
@@ -29,6 +27,7 @@ public class MTRenderer extends AbstractRenderer {
public MTRenderer(AbstractRenderer internalRenderer, int numberOfThreads) {
this.internalRenderer = internalRenderer;
this.numberOfThreads = numberOfThreads;
+ setFrameUpdate(internalRenderer.getFrameUpdate());
}
@Override
@@ -61,11 +60,6 @@ public void setDisplay(Display display) {
internalRenderer.setDisplay(display);
}
- @Override
- public void setFrameUpdate(Consumer frameUpdate) {
- internalRenderer.setFrameUpdate(frameUpdate);
- }
-
// Multi-threading attributes
private AtomicInteger currentPixel;
private final int pixelsPerThreadLoop = 100;
diff --git a/src/tracer/renderer/PTRenderer.java b/src/tracer/renderer/PTRenderer.java
index 3f22a67..537be80 100644
--- a/src/tracer/renderer/PTRenderer.java
+++ b/src/tracer/renderer/PTRenderer.java
@@ -1,5 +1,6 @@
package tracer.renderer;
+import java.util.function.Consumer;
import tracer.data.base.Matrix4;
import tracer.data.base.Vector3;
import tracer.data.trace.Hit;
@@ -12,8 +13,6 @@
import tracer.scene.Scene;
import tracer.util.TTRand;
-import java.util.function.Consumer;
-
/**
* Renderer implementation using the path tracer techniques.
*
@@ -57,7 +56,6 @@ protected void renderFrame() {
).normalize();
frontBuffer[x + y * width] = renderPixel(new Ray(rayOrigin, rayDirection)).getIntValue();
}
- System.out.println("column " + x);
display.flush(); // flushes each column
}
}
diff --git a/src/tracer/renderer/Renderer.java b/src/tracer/renderer/Renderer.java
index 0361db7..8821015 100644
--- a/src/tracer/renderer/Renderer.java
+++ b/src/tracer/renderer/Renderer.java
@@ -1,11 +1,10 @@
package tracer.renderer;
+import java.util.function.Consumer;
import tracer.scene.Camera;
import tracer.scene.Display;
import tracer.scene.Scene;
-import java.util.function.Consumer;
-
/**
* The Renderer interface, any rendering algorithm should implement this interface.
*
@@ -61,6 +60,7 @@ public interface Renderer {
* @param frameUpdate the received frame update consumer in the renderer.
*/
void setFrameUpdate(Consumer frameUpdate);
+ Consumer getFrameUpdate();
/**
* Starts the thread that renders the frames. To stop, call the stop() method. If is already running throws an