Guest User

Untitled

a guest
Oct 17th, 2017
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.89 KB | None | 0 0
  1. import math
  2.        
  3. class vector:
  4.     """ This class has all functions related to 3d vectors!"""
  5.     def __init__(self, i, j, k):
  6.         self.i=i
  7.         self.j=j
  8.         self.k=k
  9.    
  10.     def dot(self, v):
  11.         return self.i*v.i + self.j*v.j + self.k*v.k
  12.    
  13.     def cross(self, v):
  14.         return vector(self.j*v.k-self.k*v.j,
  15.                   self.k*v.i-self.i*v.k,
  16.                   self.i*v.j-self.j*v.i )
  17.     def norm(self):
  18.         return math.sqrt(self.i*self.i+self.j*self.j+self.k*self.k)
  19.          
  20.     def normalize(self):
  21.         norm = 1/self.norm()
  22.         self.i=self.i*norm
  23.         self.j=self.j*norm
  24.         self.k=self.k*norm
  25.        
  26.     def sub(self, a):
  27.         return vector(self.i-a.i, self.j-a.j, self.k-a.k)
  28.    
  29.     def smult(self, s):
  30.         self.i*=s
  31.         self.j*=s
  32.         self.k*=s
  33.    
  34.     def invert(self):
  35.         self.smult(-1)
  36.    
  37.     def printv(self):
  38.         print self.i, self.j, self.k
  39.  
  40. class Light:
  41.     def __init__(self, origin, intensity):
  42.         self.origin=origin
  43.         self.intensity=intensity
  44.    
  45. class Sphere:
  46.     def __init__(self, origin, radius, color):
  47.         self.origin=origin
  48.         self.radius=radius
  49.         self.color=color
  50.        
  51.     def find_normal(self, point):
  52.         normal=point.sub(self.origin)
  53.         normal.normalize()
  54.         return normal
  55.    
  56.     def find_reflection(self, point, ray): #R = V - ( 2 * V [dot] N ) N
  57.         normal=self.find_normal(point)
  58.         normal.smult(ray.dir.dot(normal)*2)
  59.         return Ray(point, ray.dir.sub(normal))
  60.        
  61.    
  62. class Ray:
  63.     def __init__(self, origin, direction):
  64.         self.origin=origin
  65.         self.dir=direction
  66.         self.dir.normalize()
  67.        
  68.     def sphere_intersect(self, sphere):
  69.         translRay=Ray(self.origin.sub(sphere.origin), self.dir) #translate ray, to have sphere at 0,0,0
  70.                      
  71.         a=self.dir.dot(self.dir)
  72.        
  73.         b=2*translRay.origin.dot(translRay.dir)
  74.        
  75.         c=translRay.origin.dot(translRay.origin)-sphere.radius*sphere.radius
  76.        
  77.         discr=b*b-4*a*c #discriminate of quadratic equation
  78.        
  79.         if(discr<0): #no intersect
  80.             return -1.
  81.        
  82.         discr=math.sqrt(discr)
  83.         a*=2
  84.         t0=(-b+discr)/a
  85.         t1=(-b-discr)/a
  86.        
  87.         if(t1<t0):
  88.             t0=t1
  89.        
  90.         return t0
  91.    
  92.     def sphere_intersect_point(self, t):
  93.         v=vector((self.dir.i*t+self.origin.i),(self.dir.j*t+self.origin.j), (self.dir.k*t+self.origin.k))
  94.         return v
  95.        
  96.     def find_near(self, objects):
  97.         dist=-1
  98.         for obj in objects:
  99.             t=self.sphere_intersect(obj)
  100.             if(t>0 and (t<dist or dist<0) ):
  101.                 dist=t
  102.                 closest=obj
  103.         if(dist<0):
  104.             closest=0
  105.            
  106.         return (closest, self.sphere_intersect_point(dist) )
  107.    
  108.     def find_light(self, objects, closest, point, lights):
  109.         intensity=0
  110.         for light in lights:
  111.             ray = Ray(point, light.origin.sub(point))
  112.             intersect=ray.find_near(objects)
  113.             if(intersect[0] == 0): #not in shadow
  114.                 normal=closest.find_normal(intersect[1])
  115.                 proj=normal.dot(ray.dir)*closest.color*light.intensity
  116.                 if(proj>0):
  117.                     intensity += proj
  118.                
  119.         return intensity       
  120.                
  121.                
  122.  
  123. class Pixel:
  124.     def __init__(self, ray):
  125.         self.ray=ray
  126.         self.color=0
  127.         self.recursions=0
  128.    
  129.     def trace(self, objects, lights):
  130.         near=self.ray.find_near(objects)
  131.         if(near[0]!=0 and self.recursions<1):
  132.             tmp=self.ray.find_light(objects, near[0], near[1], lights)
  133.             #print(tmp, end=" ")
  134.             self.color+=tmp
  135.             self.ray=near[0].find_reflection(near[1], self.ray)
  136.             self.recursions+=1
  137.             self.trace(objects, lights)
  138.            
  139.     def traceS(self, objects, lights):
  140.         near=self.ray.find_near(objects)
  141.         if(near[0]!=0):
  142.             self.color=near[0].color
  143.            
  144.        
  145.  
  146. class Camera:
  147.     def __init__(self, ypix, zpix, pixstep, origin, frameOffy, frameOffz):
  148.         self.zpix=zpix
  149.         self.ypix=ypix
  150.         self.step=pixstep
  151.         self.origin=origin
  152.         self.offsety=frameOffy
  153.         self.offsetz=frameOffz
  154.        
  155.         self.frame = []
  156.         for i in range(zpix):
  157.             for j in range(ypix):
  158.                 rOrigin=vector(0, j*pixstep+frameOffy, i*pixstep+frameOffz)
  159.                
  160.                 rDir=rOrigin.sub( origin )
  161.                 rDir.normalize()
  162.                
  163.                 self.frame.append(Pixel(Ray(rOrigin, rDir)))
  164.        
  165.         #for i in self.frame:
  166.         #   i.ray.dir.print()
  167.                
  168.     def trace(self, objects, lights):
  169.         for pixel in self.frame:
  170.             pixel.trace(objects, lights)
  171.     def traceS(self, objects, lights):
  172.         for pixel in self.frame:
  173.             pixel.traceS(objects, lights)
  174.            
  175.     def printc(self):
  176.         print "P2"
  177.         print "# Generated by python raytracer, by number2"
  178.         print self.ypix, self.zpix
  179.         print 256
  180.         for i in range(self.zpix):
  181.             for j in range(self.ypix):
  182.                 if(self.frame[i*self.ypix+j].color>1):
  183.                     self.frame[i*self.ypix+j].color=1
  184.                 print int(math.ceil(255*self.frame[i*self.ypix+j].color)),
  185.             print ''
  186.                    
  187.    
  188.            
  189.        
  190. def main():
  191.     sphere=Sphere(vector(-20., 4, 0), 10., 1)
  192.     lights=[]
  193.     lights.append(Light(vector(0,8,5), .9))
  194.     lights.append(Light(vector(0,-15,100), .5))
  195.     lights.append(Light(vector(0,0,-40), .3))
  196.  
  197.     objList=[]
  198.     objList.append(sphere)
  199.     objList.append(Sphere(vector(-30, -8, 0), 10, 1))
  200.     objList.append(Sphere(vector(-10, -6, 10), 4, 1))
  201.     objList.append(Sphere(vector(-10, 0, 12), 2, 1))
  202.  
  203.  
  204.     cam=Camera(100, 1000, .008, vector(5, 0, 5), -5, 1)
  205.     cam.trace(objList, lights)
  206.  
  207.     cam.printc()
  208.    
  209. main()
Add Comment
Please, Sign In to add comment