# MiniLight Python : minimal global illumination renderer
#
# Copyright (c) 2007-2008, Harrison Ainsworth / HXA7241 and Juraj Sukop.
# http://www.hxa7241.org/
from math import sqrt
from random import random
from vector3f import Vector3f, ZERO, ONE, MAX
import re
SEARCH = re.compile('(\(.+\))\s*(\(.+\))\s*(\(.+\))\s*(\(.+\))\s*(\(.+\))').search
TOLERANCE = 1.0 / 1024.0
class Triangle(object):
def __init__(self, in_stream):
for line in in_stream:
if not line.isspace():
v0, v1, v2, r, e = SEARCH(line).groups()
self.vertexs = map(Vector3f, [v0, v1, v2])
self.edge0 = Vector3f(v1) - Vector3f(v0)
self.edge3 = Vector3f(v2) - Vector3f(v0)
self.reflectivity = Vector3f(r).clamped(ZERO, ONE)
self.emitivity = Vector3f(e).clamped(ZERO, MAX)
edge1 = Vector3f(v2) - Vector3f(v1)
self.tangent = self.edge0.unitize()
self.normal = self.tangent.cross(edge1).unitize()
pa2 = self.edge0.cross(edge1)
self.area = sqrt(pa2.dot(pa2)) * 0.5
return
raise StopIteration
def get_bound(self):
v2 = self.vertexs[2]
bound = [v2.x, v2.y, v2.z, v2.x, v2.y, v2.z]
for j in range(3):
v0 = self.vertexs[0][j]
v1 = self.vertexs[1][j]
if v0 < v1:
if v0 < bound[j]:
bound[j] = v0
if v1 > bound[j + 3]:
bound[j + 3] = v1
else:
if v1 < bound[j]:
bound[j] = v1
if v0 > bound[j + 3]:
bound[j + 3] = v0
bound[j] -= (abs(bound[j]) + 1.0) * TOLERANCE
bound[j + 3] += (abs(bound[j + 3]) + 1.0) * TOLERANCE
return bound
def get_intersection(self, ray_origin, ray_direction):
e1x = self.edge0.x; e1y = self.edge0.y; e1z = self.edge0.z
e2x = self.edge3.x; e2y = self.edge3.y; e2z = self.edge3.z
pvx = ray_direction.y * e2z - ray_direction.z * e2y
pvy = ray_direction.z * e2x - ray_direction.x * e2z
pvz = ray_direction.x * e2y - ray_direction.y * e2x
det = e1x * pvx + e1y * pvy + e1z * pvz
if -0.000001 < det < 0.000001:
return None
inv_det = 1.0 / det
v0 = self.vertexs[0]
tvx = ray_origin.x - v0.x
tvy = ray_origin.y - v0.y
tvz = ray_origin.z - v0.z
u = (tvx * pvx + tvy * pvy + tvz * pvz) * inv_det
if u < 0.0 or u > 1.0:
return None
qvx = tvy * e1z - tvz * e1y
qvy = tvz * e1x - tvx * e1z
qvz = tvx * e1y - tvy * e1x
v = (ray_direction.x * qvx + ray_direction.y * qvy + ray_direction.z * qvz) * inv_det
if v < 0.0 or u + v > 1.0:
return None
t = (e2x * qvx + e2y * qvy + e2z * qvz) * inv_det
if t < 0.0:
return None
return t
def get_sample_point(self):
sqr1 = sqrt(random())
r2 = random()
a = 1.0 - sqr1
b = (1.0 - r2) * sqr1
return self.edge0 * a + self.edge3 * b + self.vertexs[0]
|