View difference between Paste ID: yrH2vT7z and 8VKAs66E
SHOW: | | - or go back to the newest paste.
1
#tiny-tracer-no-vector-class. 2x speedup.
2
 
3
#original pastebin: http://pastebin.com/F8f5GHJZ
4
#original thread:   http://www.reddit.com/r/tinycode/comments/169ri9/ray_tracer_in_140_sloc_of_python_with_picture/
5
6
import timeit
7
8
from math import sqrt, pow, pi
9-
def vMul(a,b):  return [ a[0]*b[0], a[1]*b[1], a[2]*b[2] ]
9+
10-
def vMulD(a,b): return [ a[0]*b,    a[1]*b,    a[2]*b    ]
10+
 
11-
def vAdd(a,b):  return [ a[0]+b[0], a[1]+b[1], a[2]+b[2] ]
11+
def vMul(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    ]
12+
def vMulD(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] ]
13+
def vAdd(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    ]
14+
def vAddD(a,b): return ( a[0]+b,    a[1]+b,    a[2]+b    )
15-
def vNeg(a):    return [-a[0],     -a[1],     -a[2]      ]
15+
def vSub(a,b):  return ( a[0]-b[0], a[1]-b[1], a[2]-b[2] )
16-
def vPow(a,b):  return [ a[0]**b,   a[1]**b,   a[2]**b   ]
16+
def vSubD(a,b): return ( a[0]-b,    a[1]-b,    a[2]-b    )
17
def vNeg(a):    return (-a[0],     -a[1],     -a[2]      )
18
def vPow(a,b):  return ( a[0]**b,   a[1]**b,   a[2]**b   )
19
 
20
def vDot(a,b):  return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]
21
def vSqr(a):    return vDot(a,a)
22
def vLen(a):    return sqrt(vSqr(a))
23
def vNorm(a):   return vMulD(a, 1.0/vLen(a))
24-
	
24+
 
25-
	def __init__(self, center, radius, color):
25+
26-
		self.c = center
26+
       
27-
		self.r = radius
27+
        def __init__(self, center, radius, color):
28-
		self.col = color
28+
                self.c = center
29-
		
29+
                self.r = radius
30-
	def intersection(self, l):
30+
                self.col = color
31-
		q = vDot(l.d, vSub(l.o, self.c))**2 - vSqr(vSub(l.o, self.c)) + self.r**2
31+
               
32-
		if q < 0:
32+
        def intersection(self, l):
33-
			return Intersection( [0,0,0], -1, [0,0,0], self)
33+
                q = vDot(l.d, vSub(l.o, self.c))**2 - vSqr(vSub(l.o, self.c)) + self.r**2
34-
		else:
34+
                if q < 0:
35-
			d = -vDot(l.d, vSub(l.o, self.c))
35+
                        return Intersection( (0,0,0), -1, (0,0,0), self)
36-
			d1 = d - sqrt(q)
36+
                else:
37-
			d2 = d + sqrt(q)
37+
                        d = -vDot(l.d, vSub(l.o, self.c))
38-
			if 0 < d1 and ( d1 < d2 or d2 < 0):
38+
                        d1 = d - sqrt(q)
39-
				return Intersection(vAdd(l.o,vMulD(l.d,d1)), d1, self.normal(vAdd(l.o,vMulD(l.d,d1))), self)
39+
                        d2 = d + sqrt(q)
40-
			elif 0 < d2 and ( d2 < d1 or d1 < 0):
40+
                        if 0 < d1 and ( d1 < d2 or d2 < 0):
41-
				return Intersection(vAdd(l.o,vMulD(l.d,d2)), d2, self.normal(vAdd(l.o,vMulD(l.d,d2))), self)
41+
                                return Intersection(vAdd(l.o,vMulD(l.d,d1)), d1, self.normal(vAdd(l.o,vMulD(l.d,d1))), self)
42-
			else:
42+
                        elif 0 < d2 and ( d2 < d1 or d1 < 0):
43-
				return Intersection( [0,0,0], -1, [0,0,0], self)
43+
                                return Intersection(vAdd(l.o,vMulD(l.d,d2)), d2, self.normal(vAdd(l.o,vMulD(l.d,d2))), self)
44-
	
44+
                        else:
45-
	def normal(self, b):
45+
                                return Intersection( (0,0,0), -1, (0,0,0), self)
46-
		return vNorm(vSub(b,self.c))
46+
       
47-
	
47+
        def normal(self, b):
48
                return vNorm(vSub(b,self.c))
49-
	
49+
       
50-
	def __init__(self, point, normal, color):
50+
51-
		self.n = normal
51+
       
52-
		self.p = point
52+
        def __init__(self, point, normal, color):
53-
		self.col = color
53+
                self.n = normal
54-
		
54+
                self.p = point
55-
	def intersection(self, l):
55+
                self.col = color
56-
		d = vDot(l.d, self.n)
56+
               
57-
		if d == 0:
57+
        def intersection(self, l):
58-
			return Intersection( [0,0,0], -1, vector[0,0,0], self)
58+
                d = vDot(l.d, self.n)
59-
		else:
59+
                if d == 0:
60-
			d = vDot(vSub(self.p,l.o),self.n) / d
60+
                        return Intersection( (0,0,0), -1, vector(0,0,0), self)
61-
			return Intersection(vAdd(l.o,vMulD(l.d,d)), d, self.n, self)
61+
                else:
62-
	
62+
                        d = vDot(vSub(self.p,l.o),self.n) / d
63
                        return Intersection(vAdd(l.o,vMulD(l.d,d)), d, self.n, self)
64-
	
64+
       
65-
	def __init__(self, origin, direction):
65+
66-
		self.o = origin
66+
       
67-
		self.d = direction
67+
        def __init__(self, origin, direction):
68-
		
68+
                self.o = origin
69
                self.d = direction
70-
	
70+
               
71-
	def __init__(self, point, distance, normal, obj):
71+
72-
		self.p = point
72+
       
73-
		self.d = distance
73+
        def __init__(self, point, distance, normal, obj):
74-
		self.n = normal
74+
                self.p = point
75-
		self.obj = obj
75+
                self.d = distance
76-
		
76+
                self.n = normal
77
                self.obj = obj
78-
	intersect = Intersection( [0,0,0], -1, [0,0,0], None)
78+
               
79-
	
79+
80-
	for obj in objects:
80+
        intersect = Intersection( (0,0,0), -1, (0,0,0), None)
81-
		if obj is not ignore:
81+
       
82-
			currentIntersect = obj.intersection(ray)
82+
        for obj in objects:
83-
			if currentIntersect.d > 0 and intersect.d < 0:
83+
                if obj is not ignore:
84-
				intersect = currentIntersect
84+
                        currentIntersect = obj.intersection(ray)
85-
			elif 0 < currentIntersect.d < intersect.d:
85+
                        if currentIntersect.d > 0 and intersect.d < 0:
86-
				intersect = currentIntersect
86+
                                intersect = currentIntersect
87-
	return intersect
87+
                        elif 0 < currentIntersect.d < intersect.d:
88-
	
88+
                                intersect = currentIntersect
89
        return intersect
90-
	if maxRecur < 0:
90+
       
91-
		return [0,0,0]
91+
92-
	intersect = testRay(ray, objects)
92+
        if maxRecur < 0:
93-
	if intersect.d == -1:
93+
                return (0,0,0)
94-
		col = [AMBIENT,AMBIENT,AMBIENT]
94+
        intersect = testRay(ray, objects)
95-
	elif vDot(intersect.n, vSub(light,intersect.p)) < 0:
95+
        if intersect.d == -1:
96-
		col = vMulD(intersect.obj.col, AMBIENT)
96+
                col = (AMBIENT,AMBIENT,AMBIENT)
97-
	else:
97+
        elif vDot(intersect.n, vSub(light,intersect.p)) < 0:
98-
		lightRay = Ray(intersect.p, vNorm(vSub(light,intersect.p)))
98+
                col = vMulD(intersect.obj.col, AMBIENT)
99-
		if testRay(lightRay, objects, intersect.obj).d == -1:
99+
        else:
100-
			lightIntensity = 1000.0/(4*pi*vLen(vSub(light,intersect.p))**2)
100+
                lightRay = Ray(intersect.p, vNorm(vSub(light,intersect.p)))
101-
			col = vMulD(intersect.obj.col, max(vDot(vNorm(intersect.n),vMulD(vNorm(vSub(light,intersect.p)),lightIntensity)), AMBIENT))
101+
                if testRay(lightRay, objects, intersect.obj).d == -1:
102-
		else:
102+
                        lightIntensity = 1000.0/(4*pi*vLen(vSub(light,intersect.p))**2)
103-
			col = vMulD(intersect.obj.col, AMBIENT)
103+
                        col = vMulD(intersect.obj.col, max(vDot(vNorm(intersect.n),vMulD(vNorm(vSub(light,intersect.p)),lightIntensity)), AMBIENT))
104-
	return col
104+
                else:
105-
	
105+
                        col = vMulD(intersect.obj.col, AMBIENT)
106
        return col
107-
	return (int(pow(color[0]/255.0,factor)*255),
107+
       
108-
			int(pow(color[1]/255.0,factor)*255),
108+
109-
			int(pow(color[2]/255.0,factor)*255))
109+
        return (int(pow(color[0]/255.0,factor)*255),
110
                        int(pow(color[1]/255.0,factor)*255),
111
                        int(pow(color[2]/255.0,factor)*255))
112
 
113
AMBIENT = 0.1
114
GAMMA_CORRECTION = 1/2.2
115
MAX_RECURSION = 10
116-
objs = [ Sphere([-2, 0,-10], 2,   [0,255,0]),
116+
 
117-
         Sphere([ 2, 0,-10], 3.5, [255,0,0]),
117+
118-
         Sphere([ 0,-4,-10], 3,   [0,0,255]),
118+
objs = ( Sphere((-2, 0,-10), 2,   (0,255,0)),
119-
         Plane([0,0,-12], [0,0,1], [255,255,255]) ]
119+
         Sphere(( 2, 0,-10), 3.5, (255,0,0)),
120
         Sphere(( 0,-4,-10), 3,   (0,0,255)),
121-
lightSource = [0,10,0]
121+
         Plane((0,0,-12), (0,0,1), (255,255,255)) )
122-
cameraPos = [0,0,20]
122+
 
123
lightSource = (0,10,0)
124
cameraPos = (0,0,20)
125-
	img = Image.new("RGB",(500,500))
125+
 
126-
	for x in range(500):
126+
127-
		results = []
127+
        img = Image.new("RGB",(500,500))
128-
		for y in range(500):
128+
        for x in range(500):
129-
			ray =  Ray(cameraPos, vNorm(vSub([x/50.0-5, y/50.0-5, 0], cameraPos)))
129+
                results = []
130-
			col = trace(ray, objs, lightSource, MAX_RECURSION)
130+
                for y in range(500):
131-
			img.putpixel((x,499-y),gammaCorrection(col,GAMMA_CORRECTION))
131+
                        ray =  Ray(cameraPos, vNorm(vSub((x/50.0-5, y/50.0-5, 0), cameraPos)))
132-
		print x
132+
                        col = trace(ray, objs, lightSource, MAX_RECURSION)
133-
		sys.stdout.flush()
133+
                        img.putpixel((x,499-y),gammaCorrection(col,GAMMA_CORRECTION))
134-
	img.save("trace.bmp","BMP")
134+
        img.save("trace.bmp","BMP")
135
 
136
if __name__ == '__main__':
137-
	main()
137+
        timer = timeit.Timer(stmt='main()',setup="from __main__ import main")
138
        t = timer.timeit(number=1)
139
        print "t = %f"%t