• API
• FAQ
• Tools
• Trends
• Archive
SHARE
TWEET

# tiny tracer no vector class

a guest Jan 9th, 2013 156 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
1. #tiny-tracer-no-vector-class. 2x speedup.
2.
3. #original pastebin: http://pastebin.com/F8f5GHJZ
5.
6. from math import sqrt, pow, pi
7. import Image, sys
8.
9. def vMul(a,b):  return [ a[0]*b[0], a[1]*b[1], a[2]*b[2] ]
10. def vMulD(a,b): return [ a[0]*b,    a[1]*b,    a[2]*b    ]
11. def vAdd(a,b):  return [ a[0]+b[0], a[1]+b[1], a[2]+b[2] ]
12. def vAddD(a,b): return [ a[0]+b,    a[1]+b,    a[2]+b    ]
13. def vSub(a,b):  return [ a[0]-b[0], a[1]-b[1], a[2]-b[2] ]
14. def vSubD(a,b): return [ a[0]-b,    a[1]-b,    a[2]-b    ]
15. def vNeg(a):    return [-a[0],     -a[1],     -a[2]      ]
16. def vPow(a,b):  return [ a[0]**b,   a[1]**b,   a[2]**b   ]
17.
18. def vDot(a,b):  return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]
19. def vSqr(a):    return vDot(a,a)
20. def vLen(a):    return sqrt(vSqr(a))
21. def vNorm(a):   return vMulD(a, 1.0/vLen(a))
22.
23. class Sphere( object ):
24.
25.         def __init__(self, center, radius, color):
26.                 self.c = center
28.                 self.col = color
29.
30.         def intersection(self, l):
31.                 q = vDot(l.d, vSub(l.o, self.c))**2 - vSqr(vSub(l.o, self.c)) + self.r**2
32.                 if q < 0:
33.                         return Intersection( [0,0,0], -1, [0,0,0], self)
34.                 else:
35.                         d = -vDot(l.d, vSub(l.o, self.c))
36.                         d1 = d - sqrt(q)
37.                         d2 = d + sqrt(q)
38.                         if 0 < d1 and ( d1 < d2 or d2 < 0):
40.                         elif 0 < d2 and ( d2 < d1 or d1 < 0):
42.                         else:
43.                                 return Intersection( [0,0,0], -1, [0,0,0], self)
44.
45.         def normal(self, b):
46.                 return vNorm(vSub(b,self.c))
47.
48. class Plane( object ):
49.
50.         def __init__(self, point, normal, color):
51.                 self.n = normal
52.                 self.p = point
53.                 self.col = color
54.
55.         def intersection(self, l):
56.                 d = vDot(l.d, self.n)
57.                 if d == 0:
58.                         return Intersection( [0,0,0], -1, vector[0,0,0], self)
59.                 else:
60.                         d = vDot(vSub(self.p,l.o),self.n) / d
61.                         return Intersection(vAdd(l.o,vMulD(l.d,d)), d, self.n, self)
62.
63. class Ray( object ):
64.
65.         def __init__(self, origin, direction):
66.                 self.o = origin
67.                 self.d = direction
68.
69. class Intersection( object ):
70.
71.         def __init__(self, point, distance, normal, obj):
72.                 self.p = point
73.                 self.d = distance
74.                 self.n = normal
75.                 self.obj = obj
76.
77. def testRay(ray, objects, ignore=None):
78.         intersect = Intersection( [0,0,0], -1, [0,0,0], None)
79.
80.         for obj in objects:
81.                 if obj is not ignore:
82.                         currentIntersect = obj.intersection(ray)
83.                         if currentIntersect.d > 0 and intersect.d < 0:
84.                                 intersect = currentIntersect
85.                         elif 0 < currentIntersect.d < intersect.d:
86.                                 intersect = currentIntersect
87.         return intersect
88.
89. def trace(ray, objects, light, maxRecur):
90.         if maxRecur < 0:
91.                 return [0,0,0]
92.         intersect = testRay(ray, objects)
93.         if intersect.d == -1:
94.                 col = [AMBIENT,AMBIENT,AMBIENT]
95.         elif vDot(intersect.n, vSub(light,intersect.p)) < 0:
96.                 col = vMulD(intersect.obj.col, AMBIENT)
97.         else:
98.                 lightRay = Ray(intersect.p, vNorm(vSub(light,intersect.p)))
99.                 if testRay(lightRay, objects, intersect.obj).d == -1:
100.                         lightIntensity = 1000.0/(4*pi*vLen(vSub(light,intersect.p))**2)
101.                         col = vMulD(intersect.obj.col, max(vDot(vNorm(intersect.n),vMulD(vNorm(vSub(light,intersect.p)),lightIntensity)), AMBIENT))
102.                 else:
103.                         col = vMulD(intersect.obj.col, AMBIENT)
104.         return col
105.
106. def gammaCorrection(color,factor):
107.         return (int(pow(color[0]/255.0,factor)*255),
108.                         int(pow(color[1]/255.0,factor)*255),
109.                         int(pow(color[2]/255.0,factor)*255))
110.
111. AMBIENT = 0.1
112. GAMMA_CORRECTION = 1/2.2
113. MAX_RECURSION = 10
114.
115. #these are left global so we don't have to pass them to apply_async each pixel
116. objs = [ Sphere([-2, 0,-10], 2,   [0,255,0]),
117.          Sphere([ 2, 0,-10], 3.5, [255,0,0]),
118.          Sphere([ 0,-4,-10], 3,   [0,0,255]),
119.          Plane([0,0,-12], [0,0,1], [255,255,255]) ]
120.
121. lightSource = [0,10,0]
122. cameraPos = [0,0,20]
123.
124. def main():
125.         img = Image.new("RGB",(500,500))
126.         for x in range(500):
127.                 results = []
128.                 for y in range(500):
129.                         ray =  Ray(cameraPos, vNorm(vSub([x/50.0-5, y/50.0-5, 0], cameraPos)))
130.                         col = trace(ray, objs, lightSource, MAX_RECURSION)
131.                         img.putpixel((x,499-y),gammaCorrection(col,GAMMA_CORRECTION))
132.                 print x
133.                 sys.stdout.flush()
134.         img.save("trace.bmp","BMP")
135.
136. if __name__ == '__main__':
137.         main()
RAW Paste Data
Top