Permalink
Browse files

* Fixed the issue where specular reflectivity showed on all sides of …

…the sphere (even non-visible sides)

* Cleaned up some unnecessary Vector3 duplication
* Optimized some math calculation
* Added an attempt at spot lights -- not working yet.
* Replace Color usage with ColorMagnitude, as we're not using color values -- we're using intensities of color.
* Dirtied up JavaRay a bit with some test scenes -- need to start loading scenes from external config files.
  • Loading branch information...
mbolt35 committed Apr 25, 2011
1 parent c27c47a commit 03ad54784c54975216b93174e19db7ee26fd9c0b
@@ -22,6 +22,7 @@
import com.mattbolt.javaray.camera.Camera;
import com.mattbolt.javaray.geom.Vector3;
import com.mattbolt.javaray.light.Light;
+import com.mattbolt.javaray.light.SpotLight;
import com.mattbolt.javaray.primitives.Plane;
import com.mattbolt.javaray.primitives.Sphere;
import com.mattbolt.javaray.render.ColorMagnitude;
@@ -59,25 +60,24 @@ public static void main(String[] args) {
});
Camera camera = new Camera(new Vector3(4, 3, 3));
- Scene scene = getSceneTwo(configuration);
+ Scene scene = getSceneThree(configuration);
long t = new Date().getTime();
- try {
- new RayTracer(configuration).render(scene, view, camera);
- } catch (Exception e) {
- logger.error("Error", e);
- }
+ //new RayTracer(configuration).synchronousRender(scene, view, camera);
+
+ new RayTracer(configuration).render(scene, view, camera);
logger.debug("Took: {} seconds", ((new Date().getTime() - t) / 1000));
}
private static Scene getSceneOne(JavaRayConfiguration configuration) {
Scene scene = new Scene(configuration);
+ scene.add( new Light(new Vector3(4, 3, 10), 5, 1) );
scene.add( new Sphere(new Vector3(4, 3, -5), newMat(0, 0, 0, 6, 6, 6, 10, 10, 10), 2.5) );
scene.add( new Sphere(new Vector3(2.75, 4, -1), newMat(2, 0, 0, 5, 0, 0, 0, 0, 2), 0.5) );
scene.add( new Sphere(new Vector3(5.25, 4, -1), newMat(0, 2, 0, 0, 5, 0, 0, 2, 0), 0.5) );
- scene.add( new Light(new Vector3(4, 3, 10), 5, 1) );
+ //scene.add( new Sphere(new Vector3(4, 1, -1), newMat(0, 0, 2, 0, 0, 5, 0, 0, 5), 0.5) );
//scene.add( new Light(new Vector3(6, 1, 10), 3, 1) );
return scene;
@@ -108,6 +108,27 @@ private static Scene getSceneTwo(JavaRayConfiguration configuration) {
return scene;
}
+ private static Scene getSceneThree(JavaRayConfiguration configuration) {
+ Scene scene = new Scene(configuration);
+
+ // Lights
+ //scene.add( new Light(new Vector3(4, 16, -3), 12, 1) );
+
+ // SpotLights
+ scene.add( new SpotLight(new Vector3(4, 4, 3), new Vector3(4, 0, -7), new ColorMagnitude(0, 10, 0), 1, 20.0) );
+ scene.add( new SpotLight(new Vector3(0, 4, 2), new Vector3(4, 0, -7), new ColorMagnitude(10, 0, 0), 1, 20.0) );
+ scene.add( new SpotLight(new Vector3(8, 4, 2), new Vector3(4, 0, -7), new ColorMagnitude(0, 0, 10), 1, 20.0) );
+
+ // Planes
+ scene.add( new Plane(new Vector3(0, 0, -28), new Vector3(0, 0, 1), newMat(2, 2, 2, 3.2, 3.2, 3.2, 0, 0, 0)) );
+ scene.add( new Plane(new Vector3(0, 0, 0), new Vector3(0, 1, 0), newMat(2, 2, 2, 3.2, 3.2, 3.2, 0, 0, 0)) );
+
+ // Spheres
+ //scene.add( new Sphere(new Vector3(4, 3, -3), newMat(0, 0, 0, 5, 5, 5, 1, 1, 1), 2.0) );
+
+ return scene;
+ }
+
private static Material newMat( double ar,
double ag,
double ab,
@@ -51,7 +51,7 @@
public HitResult(double t, Vector3 hitPoint) {
this.t = t;
- this.hitPoint = hitPoint;
+ this.hitPoint = hitPoint != null ? new Vector3(hitPoint) : null;
}
public double getT() {
@@ -0,0 +1,107 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// MATTBOLT.BLOGSPOT.COM
+// Copyright(C) 2011 Matt Bolt
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.mattbolt.javaray.geom;
+
+/**
+ * This class is used to represent a sphere geometrically.
+ *
+ * @author Matt Bolt, mbolt35@gmail.com
+ */
+public class SphereGeometry implements Geometry {
+ private final Vector3 position;
+ private final double radiusSquared;
+
+ public SphereGeometry(Vector3 position, double radius) {
+ this.position = new Vector3(position);
+ this.radiusSquared = Math.pow(radius, 2.0);
+ }
+
+ @Override
+ public HitResult hits(Ray ray) {
+ Vector3 direction = ray.getDirection();
+ direction.normalize();
+
+ Vector3 start = Vector3.subtract(ray.getPosition(), position);
+
+ double a = Vector3.dotProduct(direction, direction);
+ double b = Vector3.dotProduct(direction, start) * 2.0;
+ double c = Vector3.dotProduct(start, start) - radiusSquared;
+
+ double disc = Math.pow(b, 2.0) - (4.0 * a * c);
+
+ if (disc > 0) {
+ double sqrtDisc = Math.sqrt(disc);
+ double t = Math.min(
+ (-b - sqrtDisc) / (2.0 * a),
+ (-b + sqrtDisc) / (2.0 * a));
+
+ Vector3 hitLocation = hitsSphere(ray.getPosition(), direction, t);
+
+ if (hitLocation.getZ() > 0 && ray.getPosition().getZ() > 0) {
+ return new HitResult(-1, null);
+ }
+
+ return new HitResult(t, hitLocation);
+ }
+
+ return new HitResult(-1, null);
+ }
+
+ private Vector3 hitsSphere(Vector3 base, Vector3 direction, double t) {
+ Vector3 d = new Vector3(direction);
+ d.normalize();
+ d.scale(t);
+
+ return Vector3.add(base, d);
+ }
+
+ @Override
+ public Vector3 normalTo(Vector3 point) {
+ Vector3 normal = Vector3.subtract(point, position);
+ normal.normalize();
+ return normal;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof SphereGeometry)) {
+ return false;
+ }
+
+ SphereGeometry that = (SphereGeometry) o;
+
+ return Double.compare(that.radiusSquared, radiusSquared) == 0
+ && !(position != null ? !position.equals(that.position) : that.position != null);
+
+ }
+
+ @Override
+ public int hashCode() {
+ int result;
+ long temp;
+ result = position != null ? position.hashCode() : 0;
+ temp = radiusSquared != +0.0d ? Double.doubleToLongBits(radiusSquared) : 0L;
+ result = 31 * result + (int) (temp ^ (temp >>> 32));
+ return result;
+ }
+}
@@ -92,16 +92,6 @@ public void scale(double scalar) {
z *= scalar;
}
- /**
- * This method copies the values from the {@code source} parameter into this instance.
- * @param source
- */
- public void copyFrom(Vector3 source) {
- x = source.x;
- y = source.y;
- z = source.z;
- }
-
/**
* This method creates a new {@code Vector3} instance containing identical data.
*
@@ -241,7 +231,7 @@ public static Vector3 reflection(Vector3 direction, Vector3 normal) {
Vector3 v = Vector3.subtract(direction, norm);
v.normalize();
-
+
return v;
}
@@ -31,7 +31,11 @@
public class Light extends Sphere implements SceneObject {
public Light(Vector3 position, double intensity, double radius) {
- super(position, new Material(new ColorMagnitude(intensity, intensity, intensity)), radius);
+ this(position, new ColorMagnitude(intensity, intensity, intensity), radius);
+ }
+
+ public Light(Vector3 position, ColorMagnitude emissivity, double radius) {
+ super(position, new Material(emissivity), radius);
}
@Override
@@ -19,8 +19,77 @@
package com.mattbolt.javaray.light;
+import com.mattbolt.javaray.geom.Geometry;
+import com.mattbolt.javaray.geom.Ray;
+import com.mattbolt.javaray.geom.SphereGeometry;
+import com.mattbolt.javaray.geom.Vector3;
+import com.mattbolt.javaray.primitives.AbstractPrimitive;
+import com.mattbolt.javaray.primitives.SceneObject;
+import com.mattbolt.javaray.render.ColorMagnitude;
+import com.mattbolt.javaray.render.Material;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
*
*/
-public class SpotLight {
+public class SpotLight extends AbstractPrimitive implements SceneObject {
+
+ private static final Logger logger = LoggerFactory.getLogger(SpotLight.class);
+
+ private final Geometry geometry;
+
+ public SpotLight(Vector3 position, Vector3 target, double intensity, double radius, double theta) {
+ this(position, target, new ColorMagnitude(intensity, intensity, intensity), radius, theta);
+ }
+
+ public SpotLight(Vector3 position, Vector3 target, ColorMagnitude emissivity, double radius, double theta) {
+ super(position, new Material(emissivity));
+
+ geometry = new SpotGeometry(position, target, radius, theta);
+ }
+
+ @Override
+ public Geometry getGeometry() {
+ return geometry;
+ }
+
+ /**
+ * spotlight geometry
+ */
+ private static class SpotGeometry extends SphereGeometry implements Geometry {
+ private final Vector3 position;
+ private final Vector3 target;
+ private final double theta;
+
+ private SpotGeometry(Vector3 position, Vector3 target, double radius, double theta) {
+ super(position, radius);
+
+ this.position = new Vector3(position);
+ this.target = new Vector3(target);
+ this.theta = theta;
+ }
+
+ @Override
+ public HitResult hits(Ray ray) {
+ Vector3 difference = Vector3.subtract(position, ray.getPosition());
+ Vector3 direction = Vector3.subtract(position, target);
+ difference.normalize();
+ direction.normalize();
+
+ double angle = Vector3.dotProduct(difference, direction);
+ //logger.debug("angle: {}", angle);
+
+ if (angle < theta) {
+ return new HitResult(-1, null);
+ }
+
+ return super.hits(ray);
+ }
+
+ @Override
+ public Vector3 normalTo(Vector3 point) {
+ return super.normalTo(point);
+ }
+ }
}
@@ -26,7 +26,10 @@
import java.util.concurrent.atomic.AtomicLong;
/**
+ * This abstract class should be used to as a base class for a primitive shape. It provides the basic getter/setter methods
+ * for position, materials, and lights.
*
+ * @author Matt Bolt, mbolt35@gmail.com
*/
public abstract class AbstractPrimitive {
private static final AtomicLong idFactory = new AtomicLong();
@@ -42,7 +45,7 @@ public AbstractPrimitive(Vector3 position, Material material) {
}
public Vector3 getPosition() {
- return new Vector3(position);
+ return position;
}
public Material getMaterial() {
@@ -105,18 +105,18 @@ private Vector3 hitPoint(Vector3 base, Vector3 direction, double t) {
@Override
public Vector3 normalTo(Vector3 point) {
- /*
- double zero[3] = {0,0,0};
-
- vl_sum3(obj->plane->normal, zero, obj->normal);
- */
return planeNormal;
}
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (!(o instanceof PlaneGeometry)) return false;
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof PlaneGeometry)) {
+ return false;
+ }
PlaneGeometry that = (PlaneGeometry) o;
Oops, something went wrong.

0 comments on commit 03ad547

Please sign in to comment.