Sophie

Sophie

distrib > Mandriva > 2010.2 > i586 > media > contrib-backports > by-pkgid > df29c83ca401d91ec9c00bfcf7fea4ea > files > 185

shedskin-0.8-2mdv2010.2.i586.rpm

#  MiniLight Python : minimal global illumination renderer
#
#  Copyright (c) 2007-2008, Harrison Ainsworth / HXA7241 and Juraj Sukop.
#  http://www.hxa7241.org/


from triangle import Triangle, TOLERANCE
from vector3f import Vector3f_seq, Vector3f_scalar, MAX

MAX_LEVELS = 44
MAX_ITEMS  =  8

class SpatialIndex(object):

    def __init__(self, vect, bound, items, level=0):
        if vect:
            for item in items:
                item.bound = item.get_bound()
            bound = vect.as_list() * 2
            for item in items:
                for j in range(6):
                    if (bound[j] > item.bound[j]) ^ (j > 2):
                        bound[j] = item.bound[j]
            size = max((Vector3f_seq(bound[3:6]) - Vector3f_seq(bound[0:3])).as_list())
            self.bound = bound[0:3] + (Vector3f_seq(bound[3:6]).clamped(Vector3f_seq(bound[0:3]) + Vector3f_scalar(size), MAX)).as_list()
        else:
            self.bound = bound
        self.is_branch = len(items) > MAX_ITEMS and level < MAX_LEVELS - 1
        if self.is_branch:
            q1 = 0
            self.vector = [None] * 8
            for s in range(8):
                sub_bound = []
                for j in range(6):
                    m = j % 3
                    if (((s >> m) & 1) != 0) ^ (j > 2):
                        sub_bound.append((self.bound[m] + self.bound[m + 3]) * 0.5)
                    else:
                        sub_bound.append(self.bound[j])
                sub_items = []
                for item in items:
                    if item.bound[3] >= sub_bound[0] and item.bound[0] < sub_bound[3] and \
                       item.bound[4] >= sub_bound[1] and item.bound[1] < sub_bound[4] and \
                       item.bound[5] >= sub_bound[2] and item.bound[2] < sub_bound[5]:
                           sub_items.append(item)
                q1 += 1 if len(sub_items) == len(items) else 0
                q2 = (sub_bound[3] - sub_bound[0]) < (TOLERANCE * 4.0)
                if len(sub_items) > 0:
                    self.vector[s] = SpatialIndex(None, sub_bound, sub_items, MAX_LEVELS if q1 > 1 or q2 else level + 1)
        else:
            self.items = items

    def get_intersection(self, ray_origin, ray_direction, last_hit, start=None):
        start = start if start else ray_origin
        hit_object = hit_position = None
        b0, b1, b2, b3, b4, b5 = self.bound
        if self.is_branch:
            sub_cell = 1 if start.x >= (b0+b3) * 0.5 else 0
            if start.y >= (b1+b4) * 0.5:
                sub_cell |= 2
            if start.z >= (b2+b5) * 0.5:
                sub_cell |= 4
            cell_position = start
            while True:
                if self.vector[sub_cell] != None:
                    hit_object, hit_position = self.vector[sub_cell].get_intersection(ray_origin, ray_direction, last_hit, cell_position)
                    if hit_object != None:
                        break
                step = 1.797e308
                axis = 0
                for i in range(3):
                    high = (sub_cell >> i) & 1
                    face = self.bound[i + high * 3] if (ray_direction[i] < 0.0) ^ (0 != high) else (self.bound[i] + self.bound[i + 3]) * 0.5
                    try:
                        distance = (face - ray_origin[i]) / ray_direction[i]
                    except:
                        distance = float(1e30000)
                    if distance <= step:
                        step = distance
                        axis = i
                if (((sub_cell >> axis) & 1) == 1) ^ (ray_direction[axis] < 0.0):
                    break
                cell_position = ray_origin + ray_direction * step
                sub_cell = sub_cell ^ (1 << axis)
        else:
            nearest_distance = 1.797e308
            for item in self.items:
                if item != last_hit:
                    distance = item.get_intersection(ray_origin, ray_direction)
                    if 0.0 <= distance < nearest_distance:
                        hit = ray_origin + ray_direction * distance
                        if (b0 - hit.x <= TOLERANCE) and \
                           (hit.x - b3 <= TOLERANCE) and \
                           (b1 - hit.y <= TOLERANCE) and \
                           (hit.y - b4 <= TOLERANCE) and \
                           (b2 - hit.z <= TOLERANCE) and \
                           (hit.z - b5 <= TOLERANCE):
                               hit_object = item
                               hit_position = hit
                               nearest_distance = distance
        return hit_object, hit_position