Пример #1
0
 def __init__(self, center, radius, color=Color()):
     self._pp = Plane(Vector(), Vector(), Color())
     self._pn = Plane(Vector(), Vector(), Color())
     Sphere.__init__(self, center, radius, color)
     self.set_reflectivity(0.2)
     self.set_orientation(Vector())
     self.set_cosine(1.0)
Пример #2
0
 def __init__(self, center = Vector(0.0,0.0,0.0),
         radius = 1.0,
         color = Color(),
         orientation = Vector(0.0,1.0,0.0)):
     Sphere.__init__(self, center, radius, color)
     self.set_orientation(orientation)
     self.set_reflectivity(0.9,0.1)
Пример #3
0
 def __init__(self,
         normal = Vector(0.0,1.0,0.0),
         origin = Vector(0.0,0.0,0.0),
         orientation = Vector(1.0,0.0,0.0),
         c1 = Color(0.01,0.01,0.01),
         c2 = Color(0.99,0.99,0.99)):
     """Initializes plane and plane colors."""
     Plane.__init__(self, normal, origin)
     self.set_orientation(orientation)
     self.set_colors(c1,c2)
Пример #4
0
    def __init__(self,
                 r=1.0,
                 normal=Vector(0.0, 1.0, 0.0),
                 origin=Vector(0.0, 0.0, 0.0),
                 orientation=Vector(1.0, 0.0, 0.0),
                 c1=Color(0.01, 0.01, 0.01),
                 c2=Color(0.99, 0.99, 0.99)):
        """Initializes plane and plane colors."""

        CheckPlane.__init__(self, normal, origin, orientation, c1, c2)
        self.origin = origin
        self.set_orientation(orientation)
        self.r = r
        self.R = r**2.0
Пример #5
0
 def __init__(self,
              origin=Vector(0.0, 1.0, 0.0),
              focus=Vector(0.0, 0.0, 1.0),
              width=2.0,
              height=2.0,
              up=Vector(0.0, 1.0, 0.0)):
     """Instantiates new object."""
     self._init = False
     self.set_position(origin)
     self.set_focus(focus)
     self.set_orientation(up)
     self.set_window(width, height)
     self.set_ppu()
     self.set_position_delta(None)
     self._init = True
Пример #6
0
def run():

    for r in rays:
        i.reset()
        for b in bodies:
            d = b.intersection(r)
            if d > 0.0:
                i.hit(b, d)
        i.register_hit(r)
        if i._body == None:
            print "interface didn't register a hit"
        else:
            if i._distance < 0.0:
                print "interface registered hit at negative distance"
            if i._distance > 0.1:
                print "interface didn't catch closest hit"
            if i._body.p() != 'bodystub':
                print "interface didn't catch body of correct type"
            if not i._normal == Vector(0.0, 0.0, 1.0):
                print "interface caught wrong surface normal."
            if not i._color == Color(0.5, 0.5, 0.5):
                print "interface caught wrong surface color."
Пример #7
0
from pytrace import World, Camera, Tracer
from py3D import Color, Vector
from py3D import Plane, CheckPlane, Sphere

win_w = 6.4
win_h = 4.0
ppu = 25
passes = 1
filename = 'room-{0}x{1}.png'.format(int(win_w * ppu), int(win_h * ppu))

ball = Sphere(Vector(0.0, 0.0, 0.0), 1.0, Color(0.1, 0.1, 0.1))
ball.set_reflectivity(0.6)

floor = CheckPlane().set_reflectivity(0.0)

wall_color = Color(0.1, 0.1, 0.1)
n_wall = Plane(Vector(0.0, 0.0, -1.0), Vector(0.0, 0.0, 6.0), wall_color.dup())
s_wall = Plane(Vector(0.0, 0.0, 1.0), Vector(0.0, 0.0, -6.0), wall_color.dup())
w_wall = Plane(Vector(-1.0, 0.0, 0.0), Vector(6.0, 0.0, 0.0), wall_color.dup())
e_wall = Plane(Vector(1.0, 0.0, 0.0), Vector(-6.0, 0.0, 0.0), wall_color.dup())
ceiling = Plane(Vector(0.0, -1.0, 0.0), Vector(0.0, 6.0, 0.0),
                wall_color.dup())

bodies = [n_wall, s_wall, w_wall, e_wall, ceiling]
for b in bodies:
    b.set_reflectivity(0.6)
bodies.append(ball)
bodies.append(floor)

world = World(bodies).set_base_brightness(0.9)
Пример #8
0
class World:
    """This class holds body/camera/view information and performs raytrace."""

    _bodies = []
    _sky = Color()
    _interface = Interface()
    _light = Vector().norm()
    _base_brightness = 0.2

    def __init__(self, bodies=[], sky=Sky()):
        self._bodies = bodies
        self._sky = sky
        self._light = sky.get_light()
        interface = Interface()
        self._base_brightness = 0.2

    def add_body(self, body):
        self._bodies.append(body)
        return self

    def set_sky(self, sky):
        self._sky = sky
        return self

    def get_sky(self, ray):
        return self._sky.get_color(ray)

    def get_light(self):
        return self._light.dup()

    def set_base_brightness(self, b):
        self._base_brightness = b
        return self

    def trace(self, ray, last_hit=None):
        """Finds first interaction of a ray within the world."""

        self._interface.reset()

        for bodies in self._bodies:

            # check for intersection of ray with body
            distance = bodies.intersection(ray)
            if distance < 0.0:
                continue

            # move on if we're interacting with our starting point
            if bodies == last_hit and distance < bounds.too_close:
                continue

            # if we've got a hit, register it if it's closer
            self._interface.hit(bodies, distance)
        # end for

        # register the rest of our interface
        self._interface.register_hit(ray)

        return self._interface

    def shade(self, interface):
        """Detects amount of illumination at point."""
        ray = Ray(interface.poi, self.get_light())
        lambertian = self._light.dot(interface.normal)

        if lambertian < 0.0:
            return lambertian

        for bodies in self._bodies:
            distance = bodies.intersection(ray)
            if distance < 0.0:
                continue
            if bodies != interface.body or distance > bounds.too_small:
                lambertian = -1.0
                break

        return lambertian

    def highlight(self, lambertian, ray, interface):

        if lambertian < 0.0:
            return interface.color.dim(self._base_brightness)
        lambertian = max(lambertian, self._base_brightness)
        ray.reflect(i.poi, i.normal)
        highlight = max(0.0, ray.d.dot(self.get_light()))
        highlight **= i.exp
        return i.color.dim(L).gamma(1 - highlight)

    def sample(self, ray, index=1.0, depth=0, last_hit=None):
        """Recursively traces ray within world."""

        # check trace depth boundary
        if depth == bounds.max_depth:
            return Color(0.001, 0.001, 0.001)

        # get a trace interface
        i = self.trace(ray, last_hit)

        # detect hitting the sky
        if i.body == None:
            return self.get_sky(ray)

        # shade point
        L = self.shade(i)

        # add specular highlight if matte surface
        if i.matte:
            return self.highlight(L, ray, i)

        # if not matte, we do specular reflection
        else:
            if L < self._base_brightness:
                L = self._base_brightness
            cos_i = abs(ray.d.dot(i.normal))
            R = i.body.reflectivity(i.poi)
            D = 1 - R
            Ps = R + D * ((1 - cos_i)**i.exp)
            Pt = 1.0 - Ps

            color = i.color.dim(L).dim(Pt)
            return color + self.sample(ray.reflect(i.poi, i.normal), index,
                                       depth + 1, i.body).dim(Ps)
Пример #9
0
 def __init__(self, light=Vector(0.0, 1.0, 0.0), color=Color(0.2, 0.2,
                                                             0.9)):
     Sky.__init__(self, light)
     self.color = color
     self._exp = _default_exponent
Пример #10
0
def run():
    
    d = 0.0001
    zero = Vector(0.0,0.0,0.0)
    up = Vector(0.0,1.0,0.0)
    left = Vector(1.0,0.0,0.0)
    forward = Vector(0.0,0.0,1.0)
    
    # test __init__() method (and implicitly: length() method)
    u = Vector(3.0,4.0,1.0)
    dx,dy,dz = u.x - 3.0, u.y - 4.0, u.z - 1.0
    if dx > d or dy > d or dz > d:
        print "Constructor: bad coordinates"
    if abs( u.length() - (26.0 ** 0.5) ) > d:
        print "Constructor: bad length"
    del u
    
    # test __sub__() method
    u = Vector(1.5, 2.5, 3.5)
    v = Vector(3.5, 2.5, 1.5)
    w = u - v
    x = Vector( -2.0, 0.0, 2.0 )
    if abs((w - x).length()) > d:
        print "__sub__ method: incorrect coordinates"
    if abs( w.length() - (8 ** 0.5) ) > d:
        print "__sub__ method: incorrect length."
    del u,v,w,x
    
    # test __eq__() method
    u = Vector()
    v = u.dup()
    if not u == v:
        print "__eq__() method: not evaluating true correctly"
    v.trans(1.0,1.0,1.0)
    if u == v:
        print "__eq__() method: not evaluating false correctly"
    del u,v
    
    # test dup() method
    u = Vector(1.0,2.0,3.0)
    v = u.dup()
    if (u - v).length() > d:
        print "dup() method: bad coordinates"
    v.x = 4.0
    if (u - v).length() < 1.0:
        print "dup() method: not a new instance"
    del u,v
    
    # test copy() method
    u = Vector(1.0,2.0,3.0)
    v = Vector()
    v.copy(u)
    if (u - v).length() > d:
        print "copy() method: bad coordinates"
    if abs(u.length() - v.length()) > d:
        print "copy() method: bad length"
    del u,v
    
    # test add() method
    u = Vector(-1.0,1.0,3.0)
    v = Vector(-2.0,2.0,3.0)
    w = Vector()
    for s in [-2.0, -1.0, 0.0, 1.0, 2.0]:
        w.copy(u)
        w.add(v, s)
        x = Vector(u.x + s * v.x, u.y + s * v.y, u.z + s * v.z)
        if (w - x).length() > d:
            print "add() method: bad coordinates with scalar", s
        if abs(w.length() - x.length()) > d:
            print "add() method: bad length with scalar", s
        del x
    del s,u,v,w
    
    # test scale() method
    u = Vector(1.0,2.0,3.0)
    for s in [-2.0, -1.0, 0.0, 1.0, 2.0]:
        v = Vector( s * 1.0, s * 2.0, s * 3.0 )
        w = u.dup().scale(s)
        if (w - v).length() > d:
            print "scale() method: bad coordinates with scalar", s
        if abs(v.length() - w.length()) > d:
            print "scale() method: bad length with scalar", s
        del v
        del w
    del s,u
    
    # test trans() method
    u = Vector(1.0,2.0,3.0)
    v = Vector(-1.0,5.0,0.0)
    u.trans(-2.0,3.0,-3.0)
    if (u - v).length() > d:
        print "trans() method: bad coordinates"
    if abs(u.length() - v.length()) > d:
        print "trans() method: bad length"
    del u,v
    
    # test norm() method
    u = Vector(-3.0,0.0,4.0)
    v = u.dup().norm()
    if abs(v.length() - 1.0) > d:
        print "norm() method: didn't normalize to length 1.0"
    if (v.scale(u.length()) - u).length() > d:
        print "norm() method: didn't maintain direction"
    del u,v
    
    # test dot() method
    for v in [up, left,forward]:
        if abs(v.dot(zero)) > d:
            print "dot() method: handles zero vector poorly"
    for v in [left,forward]:
        if abs(up.dot(v)) > d:
            print "dot() method: handles orthogonal axis vectors poorly"
    if abs(left.dot(forward)) > d:
        print "dot() method: handles orthogonal axis vectors poorly"
    u = Vector(2.0,2.0,2.0).norm()
    v = Vector(1.0,1.0,-2.0).norm()
    if abs(u.dot(v)) > d:
        print "dot() method: handles orthogonal vectors poorly"
    del u,v
    u = Vector(3.0,-2.0,-5.0)
    v = Vector(7.0,-1.0,2.0)
    if abs(u.dot(v) - 13.0) > d:
        print "dot() method: bad non-orthogonal dot products"
    del u,v
    
    # test cross() method
    if (left.cross(up) - forward) > d:
        print "cross() method: fails on axis vectors"
    u = Vector(1.0,2.0,3.0)
    v = Vector(-1.0,3.0,2.0)
    w = u.cross(v)
    if abs(u.dot(w)) > d or abs(v.dot(w)) > d:
        print "cross() method: result not perpendicular"
        exit()
    del u,v,w
    
    # test delta() method
    u = Vector(-3.0,-2.0,-1.0)
    for translations in range(3):
        for delt in [0.001, 0.01, 0.1, 1.0, 10.0]:
            v = u.dup().delta(delt)
            if abs( (v - u).length() - delt ) > delt:
                print "delta() method: wrong delta distance"
        u.trans(1.0,1.0,1.0)
    del u,v
Пример #11
0
def run():
    sky = Sky(Vector(1.0,0.0,0.0))
    world = World([],sky)
    cam = Camera(Vector(), Vector(1.0,0.0,0.0))
    cam.set_ppu(20)
    Tracer(world, cam).draw(1).write()
Пример #12
0
 def __init__(self, light=Vector(0.0, 1.0, 0.0)):
     Sky.__init__(self, light)
Пример #13
0
 def normal(self, point):
     return Vector(0.0, 0.0, 1.0)
Пример #14
0
    def normal(self, point):
        return Vector(0.0, 0.0, 1.0)

    def reflectivity(self, point):
        return 0.5

    def intersection(self, ray):
        d = (ray.o - self.center).length()
        if d < 1.0:
            return d
        else:
            return -1.0


ray_origins = [
    Vector(-3.0, -2.0, -1.0),
    Vector(-2.0, -1.0, 0.0),
    Vector(-1.0, 0.0, 1.0),
    Vector(0.0, 1.0, 2.0),
    Vector(1.0, 2.0, 3.0)
]
ray_directions = [
    Vector(-3.0, -2.0, -1.0).norm(),
    Vector(-2.0, -1.0, 0.0).norm(),
    Vector(-1.0, 0.0, 1.0).norm(),
    Vector(0.0, 1.0, 2.0).norm(),
    Vector(1.0, 2.0, 3.0).norm()
]
rays = []
bodies = []
for origins in ray_origins:
Пример #15
0
def run():
    small = 0.00001

    zero = Vector(0.0,0.0,0.0)
    up = Vector(0.0,1.0,0.0)

    ray_origins = [ Vector(-3.0,-2.0,-1.0),
            Vector(-2.0,-1.0,0.0),
            Vector(-1.0,0.0,1.0),
            Vector(0.0,1.0,2.0),
            Vector(1.0,2.0,3.0)]
    ray_directions = [ Vector(-3.0,-2.0,-1.0).norm(),
            Vector(-2.0,-1.0,0.0).norm(),
            Vector(-1.0,0.0,1.0).norm(),
            Vector(0.0,1.0,2.0).norm(),
            Vector(1.0,2.0,3.0).norm()]

    # test initialization
    for o in ray_origins:
        for d in ray_directions:
            ray = Ray(o,d)
            if not ray.o == o:
                print "__init__() method: set origin incorrectly"
            if not ray.d == d:
                print "__init__() method: set direction incorrectly"
            del ray

    # test ray equality
    bad_ray = Ray(ray_origins[-1], ray_directions[-1])
    for o in ray_origins:
        for d in ray_directions:
            ray = Ray(o.dup(),d.dup())
            good_ray = Ray(o.dup(),d.dup())
            if not ray == good_ray:
                print "__eq__() method: evaluates true wrong"
            if ray == bad_ray:
                print "__eq__() method: evaluates false wrong"
            bad_ray.d = d.dup()
        bad_ray.o = o.dup()
        

    # test set_origin() method
    ray = Ray(zero.dup(), up.dup())
    for o in ray_origins:
        ray.set_origin(o)
        if not ray.o == o:
            print "set_origin() method: set bad origin"
    del ray
    
    # test set_direction() method
    ray = Ray(zero.dup(),up.dup())
    for d in ray_directions:
        ray.set_direction(d.dup())
        if not ray.d == d:
            print "set_direction() method: set bad direction"
    
    # test follow() method
    distances = [-3,-2,-1,0,1,2,3]
    for t in distances:
        for o in ray_origins:
            for d in ray_directions:
                p = Ray(o.dup(),d.dup()).follow(t)
                if not p == o.dup().add(d, t):
                    print "follow() method: didn't follow right"
    
    # test reflect() method
    for poi in ray_origins:
        ray = Ray(zero.dup(),poi.dup())
        for normal in ray_directions:
            bounce = ray.dup()
            bounce.reflect(poi.dup(), normal.dup())
            o_sine = ray.d.dot(normal)
            r_sine = bounce.d.dot(normal)
            if abs( o_sine + r_sine ) > small:
                print "reflect() method: exit not at same angle to normal"
                print "    poi:   ", o.p()
                print "    normal:", d.p()
                print "    rayout:", bounce.d.p()
                print "    o_sine:", o_sine
                print "    r_sine:", r_sine
Пример #16
0
class TruncSphere(Sphere):

    center = Vector()
    radius = 0.0
    R = 0.0
    color = [0.01, 0.01, 0.01]

    def p(self):
        """Returns the name of the type of body this is."""
        return 'TrunkSphere'

    def normal(self, point):
        """Returns normal vector of body at given point."""
        s = point - self.center
        if abs(s.dot(s) - self.R) < bounds.small:
            return s.norm()
        else:
            if s.dot(self._orientation) > 0.0:
                sign = 1
            else:
                sign = -1
            return self._orientation.dup().scale(sign)

    def set_color(self, c):
        self.color = c
        self._pp.set_color(c)
        self._pn.set_color(c)
        return self

    def set_reflectivity(self, r):
        r = max(0.0, min(1.0, r))
        self._r = r
        self._pp.set_reflectivity(r)
        self._pn.set_reflectivity(r)
        return self

    def set_orientation(self, v):
        self._orientation = v.norm()
        self._pp.set_normal(v.dup())
        self._pn.set_normal(v.dup().scale(-1.0))
        return self

    def set_cosine(self, c):
        self._cosine = c
        cp = self.center.dup().add(self._orientation, c * self.radius)
        cn = self.center.dup().add(self._orientation, -1 * c * self.radius)
        self._pp.set_position(cp)
        self._pn.set_position(cn)
        return self

    def __init__(self, center, radius, color=Color()):
        self._pp = Plane(Vector(), Vector(), Color())
        self._pn = Plane(Vector(), Vector(), Color())
        Sphere.__init__(self, center, radius, color)
        self.set_reflectivity(0.2)
        self.set_orientation(Vector())
        self.set_cosine(1.0)

    def intersection(self, ray):
        """Returns distance from ray to closest intersection with sphere."""

        S = ray.o - self.center
        SD = S.dot(ray.d)
        SS = S.dot(S)

        # no hit if sphere is really far away
        if SS > bounds.too_far**2:
            return -1.0

        radical = SD**2 + self.R - SS
        # negative radical implies no solutions
        if radical < 0.0:
            return -1.0

        radical **= 0.5
        hits = [-1 * SD - radical, -1 * SD + radical]
        if hits[0] < bounds.too_close:
            if hits[1] < bounds.too_small:
                return -1.0

        pp = self._pp.intersection(ray)
        pn = self._pn.intersection(ray)

        if pp < pn:
            hitp = [pp, pn]
        else:
            hitp = [pn, pp]

        # if two plane hits before sphere hits, we miss
        if hitp[1] < hits[0]:
            return -1.0

        # if two sphere hits before plane hits, we miss
        if hits[1] < hitp[0]:
            return -1.0

        # if the second thing hit is forward, that's our distance
        hit = max(hits[0], hitp[0])
        if hit > 0:
            return hit
        # otherwise it's the third hit (if positive)
        hit = min(hits[1], hitp[1])
        if hit > 0:
            return hit
        # otherwise, we didn't hit anything
        else:
            return -1.0
Пример #17
0
from py3D import Vector, Ray, Sphere, hmSphere, Plane, CheckPlane, Color, Sky
from pytrace import World, Image, rand
from time import time

filename = 'sample-09.png'
width = 400
height = width

s = hmSphere(Vector(0.0, 1.0, 0.0), 1.0, Color(0.001, 0.99, 0.25),
             Vector(10.0, 1.0, 0.0))
p = CheckPlane()

w = World()
w.add_body(s)
w.add_body(p)
w.set_sky(Sky(Vector(1.0, 10.0, 1.0), Color(0.2, 0.2, 0.8)))

camera = Vector(0.0, 0.8, 16.0)
c_dir = Vector(0.0, 0.0, -1.0).norm()
c_up = Vector(0.0, 1.0, 0.0).norm()
c_origin = Vector(-1.5, 2.3, 0.0) - camera
c_width = 3.0
c_height = 3.0
c_x = c_dir.cross(c_up).scale(c_width / width)
c_y = c_up.dup().scale(-1 * c_height / height)

ray = Ray()
image = Image(width, height)
color = Color()
loops_per_pixel = 16
t_0 = time()
Пример #18
0
def run():

    d = 0.0001
    zero = Vector(0.0, 0.0, 0.0)
    up = Vector(0.0, 1.0, 0.0)
    left = Vector(1.0, 0.0, 0.0)
    forward = Vector(0.0, 0.0, 1.0)

    # test __init__() method (and implicitly: length() method)
    u = Vector(3.0, 4.0, 1.0)
    dx, dy, dz = u.x - 3.0, u.y - 4.0, u.z - 1.0
    if dx > d or dy > d or dz > d:
        print "Constructor: bad coordinates"
    if abs(u.length() - (26.0**0.5)) > d:
        print "Constructor: bad length"
    del u

    # test __sub__() method
    u = Vector(1.5, 2.5, 3.5)
    v = Vector(3.5, 2.5, 1.5)
    w = u - v
    x = Vector(-2.0, 0.0, 2.0)
    if abs((w - x).length()) > d:
        print "__sub__ method: incorrect coordinates"
    if abs(w.length() - (8**0.5)) > d:
        print "__sub__ method: incorrect length."
    del u, v, w, x

    # test __eq__() method
    u = Vector()
    v = u.dup()
    if not u == v:
        print "__eq__() method: not evaluating true correctly"
    v.trans(1.0, 1.0, 1.0)
    if u == v:
        print "__eq__() method: not evaluating false correctly"
    del u, v

    # test dup() method
    u = Vector(1.0, 2.0, 3.0)
    v = u.dup()
    if (u - v).length() > d:
        print "dup() method: bad coordinates"
    v.x = 4.0
    if (u - v).length() < 1.0:
        print "dup() method: not a new instance"
    del u, v

    # test copy() method
    u = Vector(1.0, 2.0, 3.0)
    v = Vector()
    v.copy(u)
    if (u - v).length() > d:
        print "copy() method: bad coordinates"
    if abs(u.length() - v.length()) > d:
        print "copy() method: bad length"
    del u, v

    # test add() method
    u = Vector(-1.0, 1.0, 3.0)
    v = Vector(-2.0, 2.0, 3.0)
    w = Vector()
    for s in [-2.0, -1.0, 0.0, 1.0, 2.0]:
        w.copy(u)
        w.add(v, s)
        x = Vector(u.x + s * v.x, u.y + s * v.y, u.z + s * v.z)
        if (w - x).length() > d:
            print "add() method: bad coordinates with scalar", s
        if abs(w.length() - x.length()) > d:
            print "add() method: bad length with scalar", s
        del x
    del s, u, v, w

    # test scale() method
    u = Vector(1.0, 2.0, 3.0)
    for s in [-2.0, -1.0, 0.0, 1.0, 2.0]:
        v = Vector(s * 1.0, s * 2.0, s * 3.0)
        w = u.dup().scale(s)
        if (w - v).length() > d:
            print "scale() method: bad coordinates with scalar", s
        if abs(v.length() - w.length()) > d:
            print "scale() method: bad length with scalar", s
        del v
        del w
    del s, u

    # test trans() method
    u = Vector(1.0, 2.0, 3.0)
    v = Vector(-1.0, 5.0, 0.0)
    u.trans(-2.0, 3.0, -3.0)
    if (u - v).length() > d:
        print "trans() method: bad coordinates"
    if abs(u.length() - v.length()) > d:
        print "trans() method: bad length"
    del u, v

    # test norm() method
    u = Vector(-3.0, 0.0, 4.0)
    v = u.dup().norm()
    if abs(v.length() - 1.0) > d:
        print "norm() method: didn't normalize to length 1.0"
    if (v.scale(u.length()) - u).length() > d:
        print "norm() method: didn't maintain direction"
    del u, v

    # test dot() method
    for v in [up, left, forward]:
        if abs(v.dot(zero)) > d:
            print "dot() method: handles zero vector poorly"
    for v in [left, forward]:
        if abs(up.dot(v)) > d:
            print "dot() method: handles orthogonal axis vectors poorly"
    if abs(left.dot(forward)) > d:
        print "dot() method: handles orthogonal axis vectors poorly"
    u = Vector(2.0, 2.0, 2.0).norm()
    v = Vector(1.0, 1.0, -2.0).norm()
    if abs(u.dot(v)) > d:
        print "dot() method: handles orthogonal vectors poorly"
    del u, v
    u = Vector(3.0, -2.0, -5.0)
    v = Vector(7.0, -1.0, 2.0)
    if abs(u.dot(v) - 13.0) > d:
        print "dot() method: bad non-orthogonal dot products"
    del u, v

    # test cross() method
    if (left.cross(up) - forward) > d:
        print "cross() method: fails on axis vectors"
    u = Vector(1.0, 2.0, 3.0)
    v = Vector(-1.0, 3.0, 2.0)
    w = u.cross(v)
    if abs(u.dot(w)) > d or abs(v.dot(w)) > d:
        print "cross() method: result not perpendicular"
        exit()
    del u, v, w

    # test delta() method
    u = Vector(-3.0, -2.0, -1.0)
    for translations in range(3):
        for delt in [0.001, 0.01, 0.1, 1.0, 10.0]:
            v = u.dup().delta(delt)
            if abs((v - u).length() - delt) > delt:
                print "delta() method: wrong delta distance"
        u.trans(1.0, 1.0, 1.0)
    del u, v
Пример #19
0
class Plane(Body):
    _normal = Vector(0.0, 1.0, 0.0)
    _origin = Vector()
    _color = [0.05, 0.05, 0.05]

    def p(self):
        """Returns the name of the type of body this is."""
        return 'Plane'

    def set_position(self, p):
        self._origin = p
        return self

    def set_color(self, c):
        self._color = c
        return self

    def get_color(self, point):
        """Returns color of body at given point."""
        return self._color.dup()

    def set_normal(self, n):
        self._normal = n.norm()
        return self

    def normal(self, point):
        """Returns normal vector of body at given point."""
        return self._normal.dup()

    def set_reflectivity(self, r):
        self._r = r
        return self

    def reflectivity(self, point):
        """Returns percentage of brightness due to specular reflection."""
        return self._r

    def __init__(self, normal, origin, color=Color(0.001, 0.001, 0.001)):
        Body.__init__(self)
        self.set_normal(normal)
        self.set_position(origin)
        self.set_color(color)
        self.set_reflectivity(0.2)

    # intersection of a ray with a plane is pretty easy:
    #  * first, find the projection of ray direction onto the normal
    #      * this is the portion of the velocity on the shortest path to plane
    #  * divide the length of the shortest vector from plane to ray origin
    #            by the length of the projection vector above
    #      * get this vector by projecting ray origin minus plane origin onto
    #                the plane normal
    #  * now you have the distance along the ray to the point of intersection!
    #      * this distance might be negative. Take this into account.
    def intersection(self, ray):
        """Returns positive distance to target (or negative if no hit)."""
        d_proj = self._normal.dot(ray.d)
        if abs(d_proj) < bounds.too_small:
            return -1.0
        s_proj = (self._origin - ray.o).dot(self._normal)
        if d_proj * s_proj < 0.0:
            # ray going away from plane
            return -1.0
        else:
            return s_proj / d_proj
Пример #20
0
 def __init__(self, light=Vector(0.0, 1.0, 0.0)):
     self.light = light.norm()