sketchucation logo sketchucation
    • Login
    ℹ️ Licensed Extensions | FredoBatch, ElevationProfile, FredoSketch, LayOps, MatSim and Pic2Shape will require license from Sept 1st More Info

    [plugin] Ruby Raytracer

    Scheduled Pinned Locked Moved Developers' Forum
    17 Posts 8 Posters 4.4k Views 8 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • MarianM Offline
      Marian
      last edited by

      I guess I won't have much use for it then πŸ˜›

      http://marian87.deviantart.com/

      1 Reply Last reply Reply Quote 0
      • A Offline
        Aerilius
        last edited by

        And it seems to render a "built-in" model, not actually my SketchUp model (that's probably why it is called a "micro raytracer"). When I change the numbers in G, the balls shift.

        1 Reply Last reply Reply Quote 0
        • thomthomT Offline
          thomthom
          last edited by

          There is a reason this is posted in the Developers section, not the Plugins section. πŸ˜‰

          Thomas Thomassen β€” SketchUp Monkey & Coding addict
          List of my plugins and link to the CookieWare fund

          1 Reply Last reply Reply Quote 0
          • AdamBA Offline
            AdamB
            last edited by

            Guys, guys

            Its a 100 lines of Ruby that manages to do image file writing, blurry depth of field, a point light and multiple materials!
            How on earth do you think it would be a full raytracer! 😲

            However, if you're interested in raytracing, its very simple and you can play around with it to learn about this area of graphics.

            The G[] array contains a Bitmap of 32x10 stored as 10 integers.

            In function T(), I test the primary ray against an infinite plane and if hit return position+surface normal+materialID (Line 36).
            I run through each bit of the bitmap and where this is '1' bits, I trace a reflective Sphere returning a surface position+normal+materiaID. (Line 54)

            The Scene function S(), traces the primary ray into the scene (Line 70) and colors the pixels depending on material m, and a single pointlight (Line 77). Try changing the position of the light.

            The color for the infinite plane is chosen based on a mod function of position. Line 83 controls the scale of chequers.

            The main function "raytrace" starts at line 93 and takes care of generating primary rays, and writing out an PPM image file.

            Adam

            Developer of LightUp Click for website

            1 Reply Last reply Reply Quote 0
            • thomthomT Offline
              thomthom
              last edited by

              Thanks for the breakdown Adam. πŸ‘

              Thomas Thomassen β€” SketchUp Monkey & Coding addict
              List of my plugins and link to the CookieWare fund

              1 Reply Last reply Reply Quote 0
              • T Offline
                tomasz
                last edited by

                Thanks for the sample code and the explanation.
                I wasn't aware that a Raytracer can be written in such a small piece of code!! 😲

                @adamb said:

                Thea will be quaking in their boots. πŸ˜‰
                πŸ˜†

                Author of [Thea Render for SketchUp](http://www.thearender.com/sketchup)

                1 Reply Last reply Reply Quote 0
                • A Offline
                  Aerilius
                  last edited by

                  I edited and reduced some lines. Hope nobody minds...
                  (it's just what I thought would work, I've not yet looked at other raytracing source codes)

                  
                  module RubyRaytracer
                  
                  class Geom;;Vector3d
                    def sc(s)
                      Geom;;Vector3d.new(x*s,y*s,z*s)
                    end
                    def sc!(s)
                      self.x *= s
                      self.y *= s
                      self.z *= s
                      self
                    end
                  end
                  
                  def self.v(x,y,z)
                    Geom;;Vector3d.new(x,y,z)
                  end
                  
                  # @lights; position, color, intensity, radius of light source
                  @lights = [ [[1000,1000,1000],[255,255,255],300,10], [[-20,23,15],[255,0,0],50,0], [[-5.5,8,15],[0,0,255],50,0] ]
                  @groundcolor = v(180,160,120)
                  @skycolor = v(180,200,255)
                  @skycolor2 = v(140,160,220)
                  @rez = 256
                  @samples = 8
                  
                  def self.cast_ray(o, d)
                    hit = @model.raytest([o,d],false)
                    return (d.z<0)? @groundcolor.sc(1+0.5*d.z) ; @skycolor.sc(1-2*d.z)+@skycolor2.sc(2*d.z) if hit == nil || (f = hit[1].last).class != Sketchup;;Face
                    p = hit[0]
                    n = f.normal
                    rd = (d - n.sc( 2*(d%n)/(n.length**2) )).normalize # reflected ray on face
                    m = (d%n<0)? f.material ; (f.back_material||f.material)
                    a = (m!=nil)? m.alpha ; 1 # opacity; I use this parameter for reflectivity
                    lc = v(0,0,0) # light color
                    @lights.each{|lt| # loop over all light sources
                      l = Geom;;Point3d.new(lt[0].collect{|x| x+lt[3]*rand()}) # light position +/- light radius for smooth shadows
                      ld = (p.vector_to(l)).normalize # vector to light source
                      s = ( x=@model.raytest([p,ld]); x!=nil && x[0].on_line?([p,l]) )? 0.5 ; 1 # occlusion test for shadows
                      i = lt[2]/(4*Math;;PI*ld.length)**2 # light intensity decreases with distance
                      h = 0.25+0.75*[(1 - 2*Math.acos( n%ld )/Math;;PI),0].max # shading
                      lc += v(*lt[1]).sc(i*s*h)
                    }
                    c = (m!=nil)? v( *((m.materialType>0)? m.texture.average_color ; m.color).to_a.slice(0,3) ) ; v(255,255,255) # color of face
                    new_color = (lc - v(255,255,255) + c).sc(a)
                    # new_color += self.cast_ray(p,d).sc(1-a) if a<1 # uncomment this for transparency
                    new_color += self.cast_ray(p,rd).sc(1-a) if a<1 # reflectivity
                    return new_color
                  end #def cast_ray
                  
                  # credits to AdamB, http://forums.sketchucation.com/viewtopic.php?f=180&t=40989#p363271
                  def self.raytrace(filename=nil, width=@rez, samples=@samples)
                    @model = Sketchup.active_model
                    @lights[0] = [ @model.shadow_info["SunDirection"].sc(1000000).to_a, [255,255,255], 300, 100000] # SketchUp sun
                  
                    filename = UI.savepanel("Save Raytrace Image", "","output.ppm") unless filename
                    File.open(filename, "wb") {|f|
                      vw = Sketchup.active_model.active_view
                      height = (width*vw.vpheight/vw.vpwidth).to_i
                      f.printf("P6 #{width} #{height} 255\n")
                  
                      fov = vw.field_of_view.degrees
                      e = vw.camera.eye
                      o = v(e.x, e.y, e.z)
                      t = vw.camera.target - e
                      g = v(t.x, t.y, t.z).normalize
                      
                      a = (v(0,0,1).cross(g)).normalize.sc(fov / height)
                      b = (g.cross(a)).normalize.sc(fov / height) 
                      c = a.sc(-width*0.5)+b.sc(-height*0.5)+g
                      
                      for y1 in 0...height
                        y = height - 1 - y1
                        Sketchup.set_status_text "raytrace; line #{y1} of #{height}"
                        for x1 in 0...width
                          x = width - 1 - x1
                          p = v(0,0,0)
                          for r in 1..samples
                            p += self.cast_ray(Geom;;Point3d.new(o.to_a), (a.sc(x+rand())+b.sc(y+rand())+c))
                          end
                          p = p.sc(1/samples.to_f)
                          p = p.to_a.collect{|x| if x>255;255;elsif x<0;0;else;x.to_i;end}
                          f.printf("%c%c%c", *p)
                        end
                      end
                      Sketchup.set_status_text "Finished #{filename}"
                    }
                  end
                  
                  end #module RubyRaytracer
                  
                  if( not file_loaded?(__FILE__) )
                    menu=UI.menu("Plugins")
                    menu.add_item("Raytrace the model!") { RubyRaytracer.raytrace }
                    file_loaded(__FILE__)
                  end
                  
                  
                  
                  #100
                  
                  

                  output.png

                  1 Reply Last reply Reply Quote 0
                  • thomthomT Offline
                    thomthom
                    last edited by

                    It renders the SketchUp scene?

                    Thomas Thomassen β€” SketchUp Monkey & Coding addict
                    List of my plugins and link to the CookieWare fund

                    1 Reply Last reply Reply Quote 0
                    • A Offline
                      Aerilius
                      last edited by

                      Well, instead of the hard-coded materials and G-Bitmap, it does a raytest() in the model and takes the material of the face that the ray hits (+ shading from normal etc). That is all, but when it's repeated for every pixel, the result is impressive.
                      Nevertheless, it's still slow πŸ˜‰

                      1 Reply Last reply Reply Quote 0
                      • AdamBA Offline
                        AdamB
                        last edited by

                        Thats pretty cool. Its it it much slower?

                        Just FYI, I test LightUp raytests in a mode that gives realtime raytracing of your scene as you look around!

                        Adam

                        Developer of LightUp Click for website

                        1 Reply Last reply Reply Quote 0
                        • N Offline
                          notareal
                          last edited by

                          @unknownuser said:

                          Thanks for the sample code and the explanation.
                          I wasn't aware that a Raytracer can be written in such a small piece of code!! 😲
                          πŸ˜†

                          Quite tiny indeed... there are others too, like
                          http://tog.acm.org/resources/GraphicsGems/gemsiv/minray/

                          Welcome to try [Thea Render](http://www.thearender.com/), Thea support | [kerkythea.net](http://www.kerkythea.net/) -team member

                          1 Reply Last reply Reply Quote 0
                          • 1 / 1
                          • First post
                            Last post
                          Buy SketchPlus
                          Buy SUbD
                          Buy WrapR
                          Buy eBook
                          Buy Modelur
                          Buy Vertex Tools
                          Buy SketchCuisine
                          Buy FormFonts

                          Advertisement