From 10aef7a3f8501754d635e5c955bf2a2d3010fdf1 Mon Sep 17 00:00:00 2001 From: Adolfo Builes Date: Wed, 14 Oct 2009 20:45:07 -0500 Subject: [PATCH] Adding next part, not drawing yet --- src/AST.scala | 40 +++++++++++ src/Camera.scala | 5 -- src/Group.scala | 45 ++++++++---- src/Hit.scala | 2 +- src/Image.scala | 15 ++-- src/Object3D.scala | 4 +- src/OrtographicCamera.scala | 12 ++++ src/Parser.scala | 132 ++++++++++++++++++++++++++++++++++++ src/Range.scala | 5 +- src/Ray.scala | 5 +- src/SceneCreator.scala | 48 +++++++++++++ src/Sphere.scala | 13 ---- src/scene.pov | 21 ++++++ 13 files changed, 305 insertions(+), 42 deletions(-) create mode 100644 src/AST.scala delete mode 100644 src/Camera.scala create mode 100644 src/OrtographicCamera.scala create mode 100644 src/Parser.scala create mode 100644 src/SceneCreator.scala delete mode 100644 src/Sphere.scala create mode 100644 src/scene.pov diff --git a/src/AST.scala b/src/AST.scala new file mode 100644 index 0000000..0475d02 --- /dev/null +++ b/src/AST.scala @@ -0,0 +1,40 @@ +import javax.vecmath._; +import scala.Math._; + +case class Material(pigment: Color3f) + +class SceneElement +class Geometry() + +sealed case class Background (color : Color3f) extends SceneElement +sealed case class Camera (location: Vector3d, lookAt: Vector3d) extends SceneElement +sealed case class LightSource (location: Vector3d, color: Color3f) extends SceneElement +sealed case class SceneObject (geometry: Geometry, material: Material) extends SceneElement +sealed case class Plane (point:Vector3d , distance: Double) extends Geometry +case class Sphere(center:Vector3d , radius: Double) extends Geometry { + + def intersect (r:Ray, h:Hit, range:Range,material:Color3f): Option [(Hit,Range)]= + { + + var v = new Vector3d ( r.origin.x - this.center.x , r.origin.y - this.center.y,r.origin.z - this.center.z); + var discriminant = pow (v.dot (r.direction),2.0) - (pow (v.dot(v),2) - pow (radius,2)); + if (discriminant >= 0 ) + { + //var t1 = -(v.dot(r.direction)) + sqrt (discriminant); + var t = -(v.dot(r.direction)) - sqrt (discriminant); + + if (t >= range.minT && t < range.maxT ) + { + var h = new Hit (t,material); + range.maxT = t; + + return Some (h,range); + } + return None; + + } + else + return None; + } + +} diff --git a/src/Camera.scala b/src/Camera.scala deleted file mode 100644 index cd37cb7..0000000 --- a/src/Camera.scala +++ /dev/null @@ -1,5 +0,0 @@ -import javax.vecmath._; -trait Camera -{ - def generateRay(point:Point2d):Ray -} diff --git a/src/Group.scala b/src/Group.scala index 7bc8b39..50b8ca3 100644 --- a/src/Group.scala +++ b/src/Group.scala @@ -1,18 +1,39 @@ import java.util.Vector; +import javax.vecmath.Color3f; -case class Group (vector : List [Object3D]) extends Object3D +case class Group (var vector:List [SceneElement] ) { - def add ( o3D:Object3D ):Unit = vector ::: List (o3D) - - - def intersect( r:Ray, h:Hit, range:Range,tMin:TValue ):Boolean = + + + + def intersect( ray:Ray ):Hit = { - // ToDo: - // Iterate over the array of objects, - // finding the intersections - val retVal = false; - // ... - return retVal; - } + var hit = new Hit (-1,new Color3f ()); + var range = new Range (); + println ("aqui"); + vector.foreach { + case SceneObject (g,Material (pigment)) => + g match { + case s:Sphere => { + s.intersect(ray,hit,range,pigment) match{ + case Some ((nh,nr)) => + { + hit = nh; + range = nr; + + } + } + } + } + } + + // ToDo: + // Iterate over the array of objects, + // finding the intersections + + // ... + return hit; + } + } diff --git a/src/Hit.scala b/src/Hit.scala index 8d4c326..7dc62bd 100644 --- a/src/Hit.scala +++ b/src/Hit.scala @@ -1,3 +1,3 @@ import javax.vecmath._; -case class Hit ( t:Double , color:Color3f ) // They call super in the constructor.. What for ? +case class Hit ( var t:Double, var color:Color3f) diff --git a/src/Image.scala b/src/Image.scala index eac2112..cefd09a 100644 --- a/src/Image.scala +++ b/src/Image.scala @@ -1,18 +1,19 @@ import javax.vecmath._ import java.io._ -class Image (width:Int, height:Int) +class Image () { - + var width = 300; + var height = 300; - var image = Array.ofDim [Point3i] (width,height); + var image = Array.ofDim [Point3d] (width,height); - def setColor(x:Int , y:Int, color:Color3f) { - val myColor = new Point3i((color.x * 255)toInt, - (color.y * 255).toInt,(color.z * 255).toInt); - image(x)(y) = myColor; + def setColor(x:Double , y:Double, color:Color3f) { + val myColor = new Point3d ((color.x * 255).toInt, + (color.y * 255).toInt,(color.z * 255.0).toInt); + image(x.toInt)(y.toInt) = myColor; } diff --git a/src/Object3D.scala b/src/Object3D.scala index 93823a8..0faa8bc 100644 --- a/src/Object3D.scala +++ b/src/Object3D.scala @@ -1,4 +1,4 @@ -abstract class Object3D +abstract class Object3D () { - def intersect (r:Ray, h:Hit, range:Range, tMin:TValue): Boolean + } diff --git a/src/OrtographicCamera.scala b/src/OrtographicCamera.scala new file mode 100644 index 0000000..e9ee529 --- /dev/null +++ b/src/OrtographicCamera.scala @@ -0,0 +1,12 @@ +import javax.vecmath._; + +case class OrtographicCamera ( size:Double ) +{ + def generateRay ( point:Point2d ):Ray = + { + + var ray = new Ray ( new Point3d(point.getX(),point.getY(),0), new Vector3d(0d,0d,1d)); + return ray; + } + +} diff --git a/src/Parser.scala b/src/Parser.scala new file mode 100644 index 0000000..b2d7927 --- /dev/null +++ b/src/Parser.scala @@ -0,0 +1,132 @@ +import java.awt.Color +import javax.vecmath._; +import scala.util.parsing.combinator.lexical._ +import scala.util.parsing.combinator.syntactical._ + +/** + * ExprLexical + * this is copied from this address. Basic support for floatTokens + * http://jim-mcbeath.blogspot.com/2008/09/scala-parser-combinators.html + */ +class ExprLexical extends StdLexical { + override def token: Parser[Token] = floatingToken | super.token + + def floatingToken: Parser[Token] = + rep1(digit) ~ optFraction ~ optExponent ^^ + { case intPart ~ frac ~ exp => NumericLit( + (intPart mkString "") :: frac :: exp :: Nil mkString "")} + + def chr(c:Char) = elem("", ch => ch==c ) + def sign = chr('+') | chr('-') + def optSign = opt(sign) ^^ { + case None => "" + case Some(sign) => sign + } + def fraction = '.' ~ rep(digit) ^^ { + case dot ~ ff => dot :: (ff mkString "") :: Nil mkString "" + } + def optFraction = opt(fraction) ^^ { + case None => "" + case Some(fraction) => fraction + } + def exponent = (chr('e') | chr('E')) ~ optSign ~ rep1(digit) ^^ { + case e ~ optSign ~ exp => e :: optSign :: (exp mkString "") :: Nil mkString "" + } + def optExponent = opt(exponent) ^^ { + case None => "" + case Some(exponent) => exponent + } +} + +object SceneParser extends StandardTokenParsers { + override val lexical = new ExprLexical + lexical.delimiters ++= List("-","<",">",",","{","}") + lexical.reserved ++= List( "background", + "color", + "camera", + "light_source", + "location", + "look_at", + "pigment", + "plane", + "sphere", + "Blue", + "Green", + "Red", + "Yellow", + "Black", + "White") + + // Doesn't accept decimals nor negatives + def valueP = opt("-") ~ numericLit ^^ + {case Some(_) ~ s => -s.toDouble + case None ~ s => s.toDouble} + + + def backgroundP = "background" ~>"{" ~> colorP <~ "}" ^^ + { case color => new Background (new Color3f (color)) } + + + def colorP = "color" ~> ("Blue" | "Green" | "Red" | "Yellow" | "White" | "Black") ^^ + {case "Blue" => Color.blue + case "Green" => Color.green + case "Red" => Color.red + case "Yellow" => Color.yellow + case "White" => Color.white + case "Black" => Color.black + } + + def pigmentP = "pigment" ~> "{" ~> colorP <~ "}" + + def vectorLitP = ("<" ~> valueP) ~ + ("," ~> valueP) ~ + ("," ~> valueP <~ ">") ^^ + {case x ~ y ~ z => new Vector3d(x.toDouble, + y.toDouble, + -z.toDouble)} + + // This one lifts a common constructor of objects like sphere and plane + def vectorValueP(cons: String, f: Function[(Vector3d, Double, Color3f), SceneObject]) = + (cons ~> "{" ~> vectorLitP) ~ + ("," ~> valueP ) ~ + (pigmentP <~ "}") ^^ + {case center ~ radius ~ pigment=> f(center, radius, new Color3f ( pigment ))} + + def sphereP = + vectorValueP("sphere", {case (center,radius,pigment) => + new SceneObject (new Sphere(center, radius), new Material(pigment))}) + + def planeP = + vectorValueP("plane", {case (center,radius,pigment) => + new SceneObject (new Plane(center, radius), new Material(pigment))}) + + def cameraP = ("camera" ~> "{" ~> "location"~> vectorLitP ) ~ + ( "look_at" ~> vectorLitP <~ "}") ^^ + { case location ~ lookAt => new Camera (location,lookAt) } + + def lightP = ("light_source" ~> "{" ~> vectorLitP)~ + (colorP <~ "}")^^ + { case location ~ color => new LightSource (location,new Color3f (color)) } + + def sceneObjP = sphereP | planeP | cameraP | lightP | backgroundP + + // The scene is just a list of SceneObjects + def sceneP: Parser[List[SceneElement]] = sceneObjP+ + + def parse(s:String) = { + val tokens = new lexical.Scanner(s) + // Check there's only one camera and LightSource. + def checkTree (tree:List[SceneObject]) = (tree count (_.isInstanceOf[Camera])) >=0 && + (tree count (_.isInstanceOf[LightSource])) >= 0 + // lastFailure = None + phrase(sceneP)(tokens) match { + case Success(tree,_) => + if (true) { // checkTree(tree) + Right(tree) + }else{ + Left("Error in the number of cameras or light sources.") + } + case x => Left(x.toString) + } + } +} diff --git a/src/Range.scala b/src/Range.scala index 42d363a..899adc3 100644 --- a/src/Range.scala +++ b/src/Range.scala @@ -1 +1,4 @@ -case class Range (mintT:Double, maxT:Double) +case class Range () { + var minT:Double =0.0; + var maxT:Double = 50000000; +} diff --git a/src/Ray.scala b/src/Ray.scala index 0abd601..f4ffd06 100644 --- a/src/Ray.scala +++ b/src/Ray.scala @@ -1,6 +1,9 @@ import javax.vecmath._; -case class Ray( origin:Point3d, direction:Vector3d ) //The direction need to be normalized +case class Ray ( var origin:Point3d, var direction:Vector3d ) + + + diff --git a/src/SceneCreator.scala b/src/SceneCreator.scala new file mode 100644 index 0000000..ba42e0c --- /dev/null +++ b/src/SceneCreator.scala @@ -0,0 +1,48 @@ +import javax.vecmath.Point2d; + +object Main extends Application { + + + def process (l:List[SceneElement]):Unit = + { + val size = 300; + var image:Image = new Image () + var camera = new OrtographicCamera (1d); + var group = new Group ( l ); + println ("Got here !!!!!! \n\n ") + for (x <- 0 to size ) + { + var px = (x.toDouble/(size/2.0)) - 1.0 + for (y <-0 to size) + { + var py = (y.toDouble/(size/2.0)) - 1.0; + var ray = camera.generateRay( new Point2d (px,py)); + println ("Is gonna set color"); + + println (px) + println (py) + group.intersect (ray).color + //image.setColor ( px,py,group.intersect (ray).color ); + } + println (x ) + } + println ("Writing") + //image.writeImage (); + + + } + + + def parseScene() = { + val text = io.Source.fromPath("scene.pov").mkString + SceneParser.parse(text) match { + case Left(err) => {println(err); exit(0);} + case Right(tree) => process(tree); + } + } + + + parseScene (); + + +} diff --git a/src/Sphere.scala b/src/Sphere.scala deleted file mode 100644 index c6e1d0b..0000000 --- a/src/Sphere.scala +++ /dev/null @@ -1,13 +0,0 @@ -import javax.vecmath._; - -case class Sphere (center:Point3d, radius: Double, color:Color3f) extends Object3D -{ - def intersect (r:Ray, h:Hit, range:Range, tMin:TValue): Boolean= - { - // ToDo: - // Compute the intersection of the ray with the - // Sphere and update what needs to be updated - // Valid values for t must be within the "range" - return true; - } -} diff --git a/src/scene.pov b/src/scene.pov new file mode 100644 index 0000000..0a7050c --- /dev/null +++ b/src/scene.pov @@ -0,0 +1,21 @@ +sphere { + <0, 0, 3>, + 2.5 + pigment { + color Blue + } +} +background { + color Black +} + +light_source { + <10, 10, -10> + color White +} + +camera { + location <0, 4, -8> + look_at <0, 0, 4> +} +