Advertisement
Xinef

Short ray tracer

Jul 9th, 2017
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 3.44 KB | None | 0 0
  1. import java.lang.Math._
  2. import javax.swing.JFrame
  3. import javax.swing.JPanel
  4. import java.awt.Image
  5. import java.awt.image.BufferedImage
  6. import java.awt.Graphics
  7. import java.awt.Dimension
  8. import java.awt.Color
  9.  
  10. case class Vector(val x : Double, val y : Double, val z : Double) {
  11.  
  12.     def this() = this(0d, 0d, 0d)
  13.     def -() = Vector(-x, -y, -z)
  14.     def +(v : Vector) = Vector(x+v.x, y+v.y, z+v.z)
  15.     def -(v : Vector) = Vector(x-v.x, y-v.y, z-v.z)
  16.     def ^(v : Vector) = Vector(y * v.z - z * v.y, -x * v.z + z * v.x, x * v.y - y * v.x)
  17.     def *(v : Vector) = x*v.x + y*v.y + z*v.z
  18.     def *(s : Double) = Vector(x*s, y*s, z*s)
  19.     def /(s : Double) = Vector(x/s, y/s, z/s)
  20.     def magnitude = sqrt(x * x + y * y + z * z)
  21.     def normalize = this / magnitude
  22. }
  23.  
  24. object World {
  25.     val sphere = Vector(0.0d, 0.0d, -10.0d)
  26.     val radius = 2.5d
  27.     var light = sphere + Vector(10.0d, 10.0d, 10.0d)
  28.     val lightBrightness = 1.0d
  29.     val ambient = 0.2d
  30. }
  31.  
  32. class Ray(origin : Vector, direction : Vector) {
  33.     val directionNorm = direction normalize
  34.    
  35.     def trace() = {
  36.  
  37.         val dist = World.sphere - origin
  38.         val B = directionNorm * dist
  39.         val D = B*B - dist * dist + World.radius * World.radius
  40.         if (D < 0.0d)
  41.             Vector(0.2d, 0.5d, 0.9d)
  42.         else {
  43.             val t0 = B - sqrt(D)
  44.             val t1 = B + sqrt(D)
  45.             var retvalue = false
  46.             var t = 1000000.0d
  47.             if ((t0 > 0.001d) && (t0 < t))
  48.             {
  49.                 t = t0
  50.                 retvalue = true
  51.             }
  52.             if ((t1 > 0.001d) && (t1 < t))
  53.             {
  54.                 t = t1
  55.                 retvalue = true
  56.             }
  57.             if(retvalue)
  58.                 lambert(t)
  59.             else
  60.                 Vector(0.2d, 0.5d, 0.9d)
  61.         }
  62.     }
  63.    
  64.     def lambert(t : Double) = {
  65.    
  66.         val point = origin + directionNorm * t
  67.         val normal = (point - World.sphere).normalize
  68.         val toLight = (World.light - point).normalize
  69.  
  70.         val cosine = normal * toLight
  71.  
  72.         val brightness = if(cosine >= 0.0)
  73.                 cosine * World.lightBrightness / (toLight*toLight) + World.ambient
  74.             else
  75.                 World.ambient
  76.  
  77.         val percieved = 1.0 - exp(-brightness)
  78.        
  79.         Vector(percieved, percieved, percieved)
  80.     }
  81. }
  82.  
  83. object XImage extends JPanel {
  84.  
  85.     var image = new BufferedImage(640, 480, BufferedImage.TYPE_INT_RGB)
  86.        
  87.     override def paint(g : Graphics) : Unit = {
  88.         g.drawImage(image, 0, 0, this)
  89.     }
  90.  
  91.     def clip(brightness : Double) = {
  92.         if(brightness > 1.0)
  93.             1.0f
  94.         else if(brightness < 0.0)
  95.             0.0f
  96.         else
  97.             brightness toFloat
  98.     }
  99.  
  100.     def paint(g2d : Graphics, color : Vector, x : Integer, y : Integer) = {
  101.         g2d.setColor(new Color(clip(color.x), clip(color.y), clip(color.z)))
  102.         g2d.drawLine(x, y, x, y)
  103.  
  104.     }
  105. }
  106.  
  107. val frame = new JFrame("Xapphire")
  108. frame setSize(640, 480)
  109. frame setLocationRelativeTo(null)
  110. frame setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
  111. frame add (XImage)
  112. frame setVisible(true)
  113.  
  114. var counter = 0.0d
  115. var frames = 0.0d
  116. val startTime = System currentTimeMillis
  117.  
  118. val pixels = for(row <- 0 until 480; column <- 0 until 640) yield (column, row)
  119.  
  120. while(true) {
  121.     val g2d = XImage.image.createGraphics()
  122.     for(row <- 0 to 480) {
  123.         for(column <- 0 to 640) {
  124.        
  125.             val x = column / 320.0d - 1.0d
  126.             val y = row / 240.0d - 1.0d
  127.        
  128.             val ray = new Ray(Vector(0.0d, 0.0d, 1.0d), Vector(x, y, -1.0d))
  129.             XImage paint(g2d, ray trace, column, row)
  130.         }
  131.     }
  132.     g2d.dispose()
  133.     XImage.repaint()
  134.     counter += 0.1d
  135.     World.light = World.sphere - Vector(-10.0d*cos(counter) + 10.0d*sin(counter), 5.0d,
  136.         -10.0d*sin(counter) - 10.0d*cos(counter))
  137.  
  138.     frames += 1.0d
  139.     frame.setTitle("" + (frames*1000 / (System.currentTimeMillis() - startTime)) + " FPS")
  140. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement