Ejemplo n.º 1
0
def main():
    """Main function."""

    if len(sys.argv) < 5:
        print "Error. Specify filename, sene, width, height."
        return -1
    filename = sys.argv[1]
    scene = sys.argv[2]
    width = int(sys.argv[3])
    height = int(sys.argv[4])

    if scene == "sp":
        primitives = create_simple_sphere()
        cam_pos = Point(0, 3, 8)
        cam_look = Point(0, 0.8, 0)
        cam_up = Vector(0, 1, 0)
    elif scene == "py":
        primitives = create_pyramid()
        cam_pos = Point(10, 10, 4)
        cam_look = Point(0, 0, 2)
        cam_up = Vector(0, 0, 1)
    else:
        print "unknown scene"
        return -1

    cam_transform = look_at(cam_pos, cam_look, cam_up)
    scene = create_scene(primitives)
    film = create_film(filename, width, height)
    camera = create_camera(film, cam_transform)
    renderer = create_renderer(camera)

    # launch render
    renderer.render(scene)

    return 0
Ejemplo n.º 2
0
    def test_intersect(self):
        # test an intersection
        ray = Ray(Point(0, 0, 10), Vector(0, 0, -1))
        intersection = Intersection()
        intersected = self.grid_accel.intersect(ray, intersection)
        self.assertFalse(intersected)
        ray.maxt = float('inf')
        intersected = self.grid_accel.intersect_p(ray)
        self.assertFalse(intersected)

        # test an intersection
        ray2 = Ray(Point(10, 0, 10), Vector(0, 0, -1))
        intersection = Intersection()
        intersected = self.grid_accel.intersect(ray2, intersection)
        self.assertTrue(intersected)
        self.assertEqual(intersection.primitive_id,
                         self.primitive_sphere1.primitive_id)
        self.assertEqual(intersection.shape_id, self.sphere1.shape_id)
        ray2.maxt = float('inf')
        intersected = self.grid_accel.intersect_p(ray2)
        self.assertTrue(intersected)

        # test an intersection
        ray3 = Ray(Point(-10, 0, 10), Vector(0, 0, -1))
        intersection = Intersection()
        intersected = self.grid_accel.intersect(ray3, intersection)
        self.assertTrue(intersected)
        self.assertEqual(intersection.primitive_id,
                         self.primitive_sphere2.primitive_id)
        self.assertEqual(intersection.shape_id, self.sphere2.shape_id)
        ray3.maxt = float('inf')
        intersected = self.grid_accel.intersect_p(ray3)
        self.assertTrue(intersected)
Ejemplo n.º 3
0
 def test_dot_w_zero(self):
     v1 = Vector(1.0, 3.0, 5.0)
     v2 = Vector(2.0, 3.0, 4.0)
     q1 = Quaternion(v1, 0.0)
     q2 = Quaternion(v2, 0.0)
     scalar = dot_quaternions(q1, q2)
     self.assertEqual(scalar, dot(v1, v2))
Ejemplo n.º 4
0
 def test_dot_perpendicular(self):
     v1 = Vector(1.0, 2.0, 0.0)
     v2 = Vector(0.0, 0.0, 5.0)
     q1 = Quaternion(v1, 3.0)
     q2 = Quaternion(v2, 4.0)
     scalar = dot_quaternions(q1, q2)
     self.assertEqual(scalar, 3.0*4.0)
Ejemplo n.º 5
0
    def test_ray_differential(self):
        r = Ray(Point(0, 0, 0), Vector(1, 2, 3))
        rd = RayDifferential(Point(0, 0, 0), Vector(1, 2, 3))

        # test copy constructor from Ray
        rd.has_differentials = True
        rd1 = RayDifferential.from_ray_differential(rd)
        self.assertTrue(isinstance(rd1, RayDifferential))
        self.assertEqual(rd1.o, rd.o)
        self.assertEqual(rd1.d, rd.d)
        self.assertEqual(rd1.rx_origin, rd.rx_origin)
        self.assertEqual(rd1.ry_origin, rd.ry_origin)
        self.assertEqual(rd1.rx_direction, rd.rx_direction)
        self.assertEqual(rd1.ry_direction, rd.ry_direction)
        self.assertEqual(rd1.has_differentials, rd.has_differentials)

        # test copy constructor from Ray
        rd2 = RayDifferential.from_ray(r)
        self.assertTrue(isinstance(rd2, RayDifferential))
        self.assertEqual(rd2.d, r.d)
        self.assertEqual(rd2.has_differentials, False)

        # test constructor from parent ray
        rd3 = RayDifferential.from_ray_parent(r.o, r.d, r, r.mint)
        self.assertTrue(isinstance(rd3, RayDifferential))
        self.assertEqual(rd3.depth, r.depth + 1)

        # test operator()
        p = rd(1.7)
        self.assertEqual(p, Point(1.7, 3.4, 5.1))
Ejemplo n.º 6
0
def create_pyramid():
    primitives = []
    # create the sphere primitive
    material = None
    object_to_world = Transform()
    world_to_object = Transform()
    sphere = Sphere(object_to_world, world_to_object, False, 1.0, -1.0, 1.0,
                    360)
    primitive = GeometricPrimitive(sphere, material, None)

    # now create the instances
    # create the objects, with this layout (shown in 2D)
    #   O O O O  level 0, width 4, pos_x -6
    #    O O O   level 1, width 3, pos_x -4
    #     O O    level 2, width 2, pos_x -2
    #      O     level 3, width 1, pos_x 0

    for level in range(4):
        width_array = 4 - level
        start_pos = Point(-2.0 * (3 - level), -2.0 * (3 - level), level * 2.0)
        for i in range(width_array):
            start_pos_i = start_pos + i * Vector(2.0, 0.0, 0.0)
            for j in range(width_array):
                pos = start_pos_i + j * Vector(0.0, 2.0, 0.0)
                transform = translate(pos).inverse()
                world_to_primitive = AnimatedTransform(transform, 0.0,
                                                       transform, 1.0)
                instance = TransformedPrimitive(primitive, world_to_primitive)
                primitives.append(instance)
    return primitives
Ejemplo n.º 7
0
 def has_scale(self):
     """Return True if the transform has a scaling term."""
     la2 = self(Vector(1, 0, 0)).length_squared()
     lb2 = self(Vector(0, 1, 0)).length_squared()
     lc2 = self(Vector(0, 0, 1)).length_squared()
     not_one = lambda x: x < 0.999 or x > 1.001
     return not_one(la2) or not_one(lb2) or not_one(lc2)
Ejemplo n.º 8
0
 def test_rotate(self):
     self.assertEqual(rotate(40, Vector(1.0, 0.0, 0.0)),
                      rotate_x(40))
     self.assertEqual(rotate(20, Vector(0.0, 1.0, 0.0)),
                      rotate_y(20))
     self.assertEqual(rotate(70, Vector(0.0, 0.0, 1.0)),
                      rotate_z(70))
Ejemplo n.º 9
0
 def test_transform_ray(self):
     ray = Ray(origin=Point(1, 2, 3),
               direction=Vector(10, 20, 30))
     ray_transformed = translate(Point(10, 20, 30))(ray)
     
     self.assertTrue(isinstance(ray_transformed, Ray))
     self.assertEqual(ray_transformed.o, Point(11, 22, 33))
     self.assertEqual(ray_transformed.d, Vector(10, 20, 30))
Ejemplo n.º 10
0
    def compute_differentials(self, ray_diff):
        """Computes the differentials from a RayDifferential."""
        if ray_diff.has_differentials:
            pass

        self.du_dx = 0.0
        self.dv_dx = 0.0
        self.du_dy = 0.0
        self.dv_dy = 0.0
        self.dp_dx = Vector(0, 0, 0)
        self.dp_dy = Vector(0, 0, 0)
Ejemplo n.º 11
0
 def test_decompose(self):
     vector_translate = Vector(10.0, 20.0, 30.0)
     matrix_translate = translate(vector_translate)
     matrix_rotation = rotate(35.0, Vector(1.0, 2.0, 3.0))
     vector_scale = Vector(1.2, 3.4, 3.2)
     matrix_scale = scale(vector_scale.x, vector_scale.y, vector_scale.z)
     transform = matrix_translate * matrix_rotation * matrix_scale
     vector_, quaternion_, scale_ = decompose(transform.m)
     self.assertEqual(vector_translate, vector_)
     self.assertEqual(matrix_rotation, quaternion_.to_transform())
     self.assertEqual(matrix_scale.m, scale_)
Ejemplo n.º 12
0
def time_sphere_intersection():
    # create a transform
    o2w = translate(Vector(10,0,0)) * scale(1.3, 1.8, 2.0)
    w2o = o2w.inverse()

    # create the sphere
    sphere = Sphere(o2w, w2o, False, 1.0, -1.0, 1.0, 360)

    # create a large amount of rays,
    # choose so that half of them will intersect the ray

    positions = [Point(random.randint(0,100),
                       random.randint(0,100),
                       random.randint(0,100)
                       ) for i in range(size)]

    ray = Ray(Point(0,0,0), Vector(1.0, 1.0, 1.0))
    vectors = []
    for i in xrange(size):
        position = positions[i]
        if i%2 == 0:
            # make sure this ray hit the sphere
            vector = sphere.object_to_world(Point(0, 0, 0)) - position
            vector /= float(random.randint(1,10))
        else:
            # construct a random vector
            vector = Vector((random.random()-0.5)*random.randint(1,5),
                            (random.random()-0.5)*random.randint(1,5),
                            (random.random()-0.5*random.randint(1,5)))
                            
        vectors.append(vector)

    intersections = 0
    t1 = time.time()
    for i in xrange(nb_calls):
        ray.o = positions[i%size]
        ray.d = vectors[i%size]
        if sphere.intersect_p(ray):
            intersections += 1

    t2 = time.time()
    for i in xrange(nb_calls):
        ray.o = positions[i%size]
        ray.d = vectors[i%size]
        sphere.intersect(ray)

    t3 = time.time()

    print "%d calls, %d intersections" % (nb_calls, intersections)
    print "Sphere.intersect_p() %.2fms" % ((t2-t1)/float(nb_calls)*1000.0)
    print "Sphere.intersect()   %.2fms" % ((t3-t2)/float(nb_calls)*1000.0)
Ejemplo n.º 13
0
    def test_bounding_box_9(self):
        bbox = BBox(Point(-1, -1, -1), Point(1, 1, 1))
        ray1 = Ray(Point(10, 10, 10), Vector(-1, -1, -1))
        intersect, hit0, hit1 = bbox.intersect_p(ray1)
        self.assertTrue(intersect)

        ray2 = Ray(Point(10, 10, 10), Vector(-1, 1, -1))
        intersect, hit0, hit1 = bbox.intersect_p(ray2)
        self.assertFalse(intersect)

        ray3 = Ray(Point(0, 0, 10), Vector(0, 0, -1))
        intersect, hit0, hit1 = bbox.intersect_p(ray3)
        self.assertTrue(intersect)
        self.assertEqual(hit0, 9.0)
        self.assertEqual(hit1, 11.0)
Ejemplo n.º 14
0
    def setUp(self):
        # create a transform
        o2w = translate(Vector(10, 0, 0)) * scale(1.3, 1.8, 2.0)
        w2o = o2w.inverse()

        # create the sphere
        self.sphere = Sphere(o2w, w2o, False, 1.0, -1.0, 1.0, 360)
Ejemplo n.º 15
0
 def __init__(self, v=None, w=1.0):
     """Default constructor for Quaternion."""
     if v is None:
         self.v = Vector(0.0, 0.0, 0.0)
     else:
         self.v = Vector.from_vector(v)
     self.w = w
Ejemplo n.º 16
0
    def test_transform(self):
        p = Point(1, 2, 3)
        p2 = translate(Point(10, 20, 30))(p)
        self.assertTrue(isinstance(p2, Point))
        self.assertEqual(p2, Point(11, 22, 33))
        
        v = Vector(1, 2, 3)
        v2 = translate(Point(10, 20, 30))(v)
        self.assertTrue(isinstance(v2, Vector))
        self.assertEqual(v2, Vector(1, 2, 3))

        self.assertEqual(scale(2, 3, 4)(Point(1, 2, 3)),
                         Point(2, 6, 12))
        self.assertEqual(scale(2, 3, 4)(Vector(1, 2, 3)),
                         Vector(2, 6, 12))
        self.assertEqual(rotate(90, Vector(0, 1, 0))(Normal(1, 0, 0)),
                         Normal(0, 0, -1))
Ejemplo n.º 17
0
    def setUp(self):
        # create a transform
        o2w1 = translate(Vector(10, 0, 0)) * scale(1.3, 1.8, 2.0)
        w2o1 = o2w1.inverse()

        # create a sphere
        self.sphere1 = Sphere(o2w1, w2o1, False, 1.0, -1.0, 1.0, 360)
        self.primitive_sphere1 = GeometricPrimitive(self.sphere1, None, None)

        # create a transform
        o2w2 = translate(Vector(-10, 0, 0)) * scale(1.3, 1.8, 2.0)
        w2o2 = o2w2.inverse()

        # create a sphere
        self.sphere2 = Sphere(o2w2, w2o2, False, 1.0, -1.0, 1.0, 360)
        self.primitive_sphere2 = GeometricPrimitive(self.sphere2, None, None)

        primitives = [self.primitive_sphere1, self.primitive_sphere2]

        self.grid_accel = GridAccel(primitives, True)
Ejemplo n.º 18
0
    def test_vector(self):
        # operator[]
        v = Vector(1.0, 2.0, 3.0)
        self.assertEqual(v[0], 1.0)
        self.assertEqual(v[1], 2.0)
        self.assertEqual(v[2], 3.0)

        # misc operators
        self.assertEqual(self.v1 * 4, 2 * self.v2)
        self.assertEqual(self.p2 - self.p1, self.v1)

        # length functions
        self.assertEqual(self.v1.length_squared(), 3)
        self.assertEqual(self.v1.length(), math.sqrt(3))

        # operator[] for assignments
        v = Vector(1.0, 2.0, 3.0)
        for i in range(3):
            v[i] = 9.0
            self.assertEqual(v[i], 9.0)
Ejemplo n.º 19
0
    def test_inverse(self):
        m1 = scale(2.0, 3.0, 4.0)
        m2 = scale(1.0/2.0, 1.0/3.0, 1.0/4.0)
        self.assertEqual(m1.inverse(), m2)
        self.assertEqual(m1.m_inv, m2.m)
        self.assertEqual(m2.m_inv, m1.m)

        m3 = translate(Point(5, 6, 7)) * scale(2, -3 , 4) * rotate(17, Vector(-1, 4, -2))
        m4 = m3.inverse()
        identity = Transform()
        self.assertTrue((m3*m4).is_identity())
        self.assertTrue((m4*m3).is_identity())
Ejemplo n.º 20
0
    def test_intersect(self):
        # test an intersection
        ray = Ray(Point(20, 10, 10), Vector(-1, -1, -1))
        intersect, t_hit, ray_epsilon, dg = self.sphere.intersect(ray)
        self.assertTrue(intersect)
        intersect = self.sphere.intersect_p(ray)
        self.assertTrue(intersect)

        # test an intersection
        ray = Ray(Point(20, 10, 10), Vector(-1, 1, -1))
        intersect, t_hit, ray_epsilon, dg = self.sphere.intersect(ray)
        self.assertFalse(intersect)
        intersect = self.sphere.intersect_p(ray)
        self.assertFalse(intersect)

        # test an intersection
        ray = Ray(Point(10, 0, 0), Vector(3, 1, -2))
        intersect, t_hit, ray_epsilon, dg = self.sphere.intersect(ray)
        self.assertTrue(intersect)
        intersect = self.sphere.intersect_p(ray)
        self.assertTrue(intersect)
Ejemplo n.º 21
0
def decompose(matrix):
    """Decompose a Matrix4x4 into T, R and S components.

    Returns:
    T , Vector
    R , Quaternion
    S , Matrix4x4

    """
    R = Quaternion()
    S = Matrix4x4()

    # Extract translation _T_ from transformation matrix
    T = Vector(matrix.m[0][3], matrix.m[1][3], matrix.m[2][3])

    # Compute new transformation matrix _M_ without translation
    M = Matrix4x4.from_matrix4x4(matrix)
    for i in range(3):
        M.m[i][3] = 0.0
        M.m[3][i] = 0.0
    M.m[3][3] = 1.0

    # Extract rotation _R_ from transformation matrix
    norm = 1.0
    count = 0
    R = Matrix4x4.from_matrix4x4(M)
    while (count < 100 and norm > 0.0001):
        # Compute next matrix _Rnext_ in series
        Rnext = Matrix4x4()
        Rit = inverse(transpose(R))
        for i in range(4):
            for j in range(4):
                Rnext.m[i][j] = 0.5 * (R.m[i][j] + Rit.m[i][j])

        # Compute norm of difference between _R_ and _Rnext_
        norm = 0.0
        for i in range(3):
            n = abs(R.m[i][0] - Rnext.m[i][0]) + \
                abs(R.m[i][1] - Rnext.m[i][1]) + \
                abs(R.m[i][2] - Rnext.m[i][2])
            norm = max(norm, n)

        R = Rnext
        count += 1

    # XXX TODO FIXME deal with flip...
    Rquat = Quaternion.from_transform(Transform(R))

    # Compute scale _S_ using rotation and original matrix
    S = inverse(R) * M

    return T, Rquat, S
Ejemplo n.º 22
0
    def __init__(self):
        """Default constructor for DifferentialGeometry."""
        self.p = Point()
        self.nn = Normal()

        self.u = 0.0
        self.v = 0.0

        self.shape = None

        self.dp_du = Vector()
        self.dp_dv = Vector()

        self.dn_du = Normal()
        self.dn_dv = Normal()

        self.dp_dx = Vector()
        self.dp_dy = Vector()

        self.du_dx = 0.0
        self.dv_dx = 0.0

        self.du_dy = 0.0
        self.dv_dy = 0.0
Ejemplo n.º 23
0
    def test_ray(self):
        r = Ray(Point(0, 0, 0), Vector(1, 2, 3))

        # test copy constructor
        r2 = Ray.from_ray(r)
        self.assertTrue(isinstance(r2, Ray))
        self.assertEqual(r2.d, r.d)

        # test constructor from parent ray
        r3 = Ray.from_ray_parent(r.o, r.d, r, r.mint)
        self.assertTrue(isinstance(r3, Ray))
        self.assertEqual(r3.depth, r.depth + 1)

        # test operator()
        p = r(1.7)
        self.assertEqual(p, Point(1.7, 3.4, 5.1))
Ejemplo n.º 24
0
    def test_normal(self):
        # operator[]
        n = Normal(1.0, 2.0, 3.0)
        self.assertEqual(n[0], 1.0)
        self.assertEqual(n[1], 2.0)
        self.assertEqual(n[2], 3.0)

        # face_forward
        n2 = Normal(1, 0, 0)
        v = Vector(-0.5, -0.1, 0.2)
        self.assertEqual(face_forward(n, v), -n)

        # operator[] for assignments
        n = Normal(1.0, 2.0, 3.0)
        for i in range(3):
            n[i] = 9.0
            self.assertEqual(n[i], 9.0)
Ejemplo n.º 25
0
    def test_transform_ray(self):
        ray_differential = RayDifferential(origin=Point(1,2,3),
                                           direction=Vector(10,20,30))
        ray_differential.rx_origin = Point(4,5,6)
        ray_differential.ry_origin = Point(5,6,7)
        ray_differential.rx_direction = Vector(2,3,4)
        ray_differential.ry_direction = Vector(3,4,5)
        ray_transformed = translate(Point(10,20,30))(ray_differential)

        self.assertTrue(isinstance(ray_transformed, RayDifferential))
        self.assertEqual(ray_transformed.o, Point(11,22,33))
        self.assertEqual(ray_transformed.d, Vector(10,20,30))
        self.assertEqual(ray_transformed.rx_origin, Point(14,25,36))
        self.assertEqual(ray_transformed.ry_origin, Point(15,26,37))
        self.assertEqual(ray_transformed.rx_direction, Vector(2,3,4))
        self.assertEqual(ray_transformed.ry_direction, Vector(3,4,5))
Ejemplo n.º 26
0
 def from_transform(cls, transform):
     """Constructor from a Transform."""
     m = transform.m
     trace = m.m[0][0] + m.m[1][1] + m.m[2][2]
     v = Vector()
     w = 1.0
     if trace > 0.0:
         # Compute w from matrix trace, then xyz
         # 4w^2 = m[0][0] + m[1][1] + m[2][2] + m[3][3] (but m[3][3] == 1)
         s = math.sqrt(trace + 1.0)
         w = s / 2.0
         s = 0.5 / s
         v.x = (m.m[2][1] - m.m[1][2]) * s
         v.y = (m.m[0][2] - m.m[2][0]) * s
         v.z = (m.m[1][0] - m.m[0][1]) * s
     else:
         # Compute largest of $x$, $y$, or $z$, then remaining components
         q = [0.0, 0.0, 0.0]
         i = 0
         if m.m[1][1] > m.m[0][0]:
             i = 1
         if m.m[2][2] > m.m[i][i]:
             i = 2
         j = (i + 1) % 3
         k = (j + 1) % 3
         s = math.sqrt((m.m[i][i] - (m.m[j][j] + m.m[k][k])) + 1.0)
         q[i] = s * 0.5
         if s != 0.0:
             s = 0.5 / s
         w = (m.m[k][j] - m.m[j][k]) * s
         q[j] = (m.m[j][i] + m.m[i][j]) * s
         q[k] = (m.m[k][i] + m.m[i][k]) * s
         v.x = q[0]
         v.y = q[1]
         v.z = q[2]
     return cls(v, w)
Ejemplo n.º 27
0
    def intersect(self, r):
        """Intersect the ray with the shape."""
        # Transform _Ray_ to object space
        ray = self.world_to_object(r)

        # Compute quadratic sphere coefficients
        A = ray.d.x * ray.d.x + ray.d.y * ray.d.y + ray.d.z * ray.d.z
        B = 2 * (ray.d.x * ray.o.x + ray.d.y * ray.o.y + ray.d.z * ray.o.z)
        C = ray.o.x*ray.o.x + ray.o.y*ray.o.y + \
                  ray.o.z*ray.o.z - self.radius*self.radius

        # Solve quadratic equation for _t_ values
        found, t0, t1 = quadratic(A, B, C)
        if not found:
            return False, float('inf'), 0.0, None

        # Compute intersection distance along ray
        if (t0 > ray.maxt or t1 < ray.mint):
            return False, float('inf'), 0.0, None
        t_hit = t0
        if (t0 < ray.mint):
            t_hit = t1
            if (t_hit > ray.maxt):
                return False, float('inf'), 0.0, None

        # Compute sphere hit position and $\phi$
        phi_t = ray(t_hit)
        if (phi_t.x == 0.0 and phi_t.y == 0.0):
            phi_t.x = 1e-5 * self.radius
        phi = math.atan2(phi_t.y, phi_t.x)
        if (phi < 0.0):
            phi += 2.0 * math.pi

        # Test sphere intersection against clipping parameters
        if ((self.z_min > -self.radius and phi_t.z < self.z_min) or \
            (self.z_max <  self.radius and phi_t.z > self.z_max) or \
            phi > self.phi_max):
            if (t_hit == t1):
                return False, float('inf'), 0.0, None
            if (t1 > ray.maxt):
                return False, float('inf'), 0.0, None
            t_hit = t1
            # Compute sphere hit position and $\phi$
            phi_t = ray(t_hit)
            if (phi_t.x == 0.0 and phi_t.y == 0.0):
                phi_t.x = 1e-5 * self.radius
            phi = math.atan2(phi_t.y, phi_t.x)
            if (phi < 0.0):
                phi += 2.0 * math.pi
            if ((self.z_min > -self.radius and phi_t.z < self.z_min) or \
                (self.z_max <  self.radius and phi_t.z > self.z_max) or \
                phi > self.phi_max):
                return False, float('inf'), 0.0, None

        # Find parametric representation of sphere hit
        u = phi / self.phi_max
        theta = math.acos(clamp(phi_t.z / self.radius, -1.0, 1.0))
        v = (theta - self.theta_min) / (self.theta_max - self.theta_min)

        # Compute sphere $\dpdu$ and $\dpdv$
        zradius = math.sqrt(phi_t.x * phi_t.x + phi_t.y * phi_t.y)
        inv_z_radius = 1.0 / zradius
        cos_phi = phi_t.x * inv_z_radius
        sin_phi = phi_t.y * inv_z_radius
        dpdu = Vector(-self.phi_max * phi_t.y, self.phi_max * phi_t.x, 0)
        dpdv = (self.theta_max-self.theta_min) * \
               Vector(phi_t.z * cos_phi,
                      phi_t.z * sin_phi,
                      -self.radius * math.sin(theta))

        # Compute sphere $\dndu$ and $\dndv$
        d2Pduu = -self.phi_max * self.phi_max * Vector(phi_t.x, phi_t.y, 0)
        d2Pduv = (self.theta_max - self.theta_min) * phi_t.z * self.phi_max * \
                 Vector(-sin_phi, cos_phi, 0.0)
        d2Pdvv = -(self.theta_max - self.theta_min) * \
                 (self.theta_max - self.theta_min) * \
                 Vector(phi_t.x, phi_t.y, phi_t.z)

        # Compute coefficients for fundamental forms
        E = dot(dpdu, dpdu)
        F = dot(dpdu, dpdv)
        G = dot(dpdv, dpdv)
        N = normalize(cross(dpdu, dpdv))
        e = dot(N, d2Pduu)
        f = dot(N, d2Pduv)
        g = dot(N, d2Pdvv)

        # Compute $\dndu$ and $\dndv$ from fundamental form coefficients
        invEGF2 = 1.0 / (E * G - F * F)
        dndu = Normal.from_vector((f*F - e*G) * invEGF2 * dpdu + \
                                  (e*F - f*E) * invEGF2 * dpdv)
        dndv = Normal.from_vector((g*F - f*G) * invEGF2 * dpdu + \
                                  (f*F - g*E) * invEGF2 * dpdv)

        # Initialize _DifferentialGeometry_ from parametric information
        o2w = self.object_to_world
        dg = DifferentialGeometry.from_intersection(o2w(phi_t), o2w(dpdu),
                                                    o2w(dpdv), o2w(dndu),
                                                    o2w(dndv), u, v, self)

        # Compute _rayEpsilon_ for quadric intersection
        ray_epsilon = 5e-4 * t_hit
        return True, t_hit, ray_epsilon, dg
Ejemplo n.º 28
0
    def __call__(self, elt):
        """Overload the operator().

        Supported operations:
        * Transform(Point)
        * Transform(Vector)
        * Transform(Normal)
        * Transform(Ray)
        * Transform(RayDifferential)
        * Transform(BBox)
        
        """
        if isinstance(elt, Point):
            x = elt.x
            y = elt.y
            z = elt.z
            xp = self.m.m[0][0] * x + self.m.m[0][1] * y + self.m.m[0][
                2] * z + self.m.m[0][3]
            yp = self.m.m[1][0] * x + self.m.m[1][1] * y + self.m.m[1][
                2] * z + self.m.m[1][3]
            zp = self.m.m[2][0] * x + self.m.m[2][1] * y + self.m.m[2][
                2] * z + self.m.m[2][3]
            wp = self.m.m[3][0] * x + self.m.m[3][1] * y + self.m.m[3][
                2] * z + self.m.m[3][3]
            if wp == 1.0:
                return Point(xp, yp, zp)
            else:
                return Point(xp, yp, zp) / wp
        elif isinstance(elt, Vector):
            x = elt.x
            y = elt.y
            z = elt.z
            xp = self.m.m[0][0] * x + self.m.m[0][1] * y + self.m.m[0][2] * z
            yp = self.m.m[1][0] * x + self.m.m[1][1] * y + self.m.m[1][2] * z
            zp = self.m.m[2][0] * x + self.m.m[2][1] * y + self.m.m[2][2] * z
            return Vector(xp, yp, zp)
        elif isinstance(elt, Normal):
            x = elt.x
            y = elt.y
            z = elt.z
            return Normal(
                self.m_inv.m[0][0] * x + self.m_inv.m[1][0] * y +
                self.m_inv.m[2][0] * z, self.m_inv.m[0][1] * x +
                self.m_inv.m[1][1] * y + self.m_inv.m[2][1] * z,
                self.m_inv.m[0][2] * x + self.m_inv.m[1][2] * y +
                self.m_inv.m[2][2] * z)
        elif isinstance(elt, RayDifferential):
            ray = RayDifferential.from_ray_differential(elt)
            ray.o = self(ray.o)
            ray.d = self(ray.d)
            ray.rx_origin = self(ray.rx_origin)
            ray.ry_origin = self(ray.ry_origin)
            ray.rx_direction = self(ray.rx_direction)
            ray.ry_direction = self(ray.ry_direction)
            return ray
        elif isinstance(elt, Ray):
            ray = Ray.from_ray(elt)
            ray.o = self(ray.o)
            ray.d = self(ray.d)
            return ray
        elif isinstance(elt, BBox):
            ret = BBox(self(Point(elt.p_min.x, elt.p_min.y, elt.p_min.z)))
            ret = union(ret, self(Point(elt.p_max.x, elt.p_min.y,
                                        elt.p_min.z)))
            ret = union(ret, self(Point(elt.p_min.x, elt.p_max.y,
                                        elt.p_min.z)))
            ret = union(ret, self(Point(elt.p_min.x, elt.p_min.y,
                                        elt.p_max.z)))
            ret = union(ret, self(Point(elt.p_min.x, elt.p_max.y,
                                        elt.p_max.z)))
            ret = union(ret, self(Point(elt.p_max.x, elt.p_max.y,
                                        elt.p_min.z)))
            ret = union(ret, self(Point(elt.p_max.x, elt.p_min.y,
                                        elt.p_max.z)))
            ret = union(ret, self(Point(elt.p_max.x, elt.p_max.y,
                                        elt.p_max.z)))
            return ret
Ejemplo n.º 29
0
    def test_transform_handedness(self):
        m1 = translate(Point(-17, 2, 31)) * scale(0.5, 6 , 1.4) * rotate(35, Vector(-15, 20, 0.2))
        self.assertFalse(m1.swap_handedness())

        m2 = translate(Point(5, 6, 7)) * scale(2, -3 , 4) * rotate(17, Vector(-1, 4, -2))
        self.assertTrue(m2.swap_handedness())
Ejemplo n.º 30
0
    def __init__(self, primitives, refine_immediately):
        """Default constructor for GridAccel."""
        # initialize self.primitives with primitives for grid
        if refine_immediately:
            self.primitives = []
            for primitive in primitives:
                primitive.fully_refine(self.primitives)
        else:
            self.primitives = list(primitives)

        # compute bounds and choose grid resolution
        self.bounds = BBox()
        for primitive in self.primitives:
            self.bounds = union(self.bounds, primitive.world_bound())
        delta = self.bounds.p_max - self.bounds.p_min

        # find voxels_per_unit_dist for grid
        max_axis = self.bounds.maximum_extent()
        inv_max_width = 1.0 / delta[max_axis]
        cube_root = 3.0 * pow(len(self.primitives), 1.0 / 3.0)
        voxels_per_unit_dist = cube_root * inv_max_width
        self.n_voxels = []
        for axis in range(3):
            self.n_voxels.append(
                clamp(round_to_int(delta[axis] * voxels_per_unit_dist), 1, 64))

        # compute voxel widths and allocate voxels
        self.width = Vector()
        self.inv_width = Vector()
        for axis in range(3):
            self.width[axis] = delta[axis] / self.n_voxels[axis]
            if self.width[axis] == 0.0:
                self.inv_width[axis] = 0.0
            else:
                self.inv_width[axis] = 1.0 / self.width[axis]
        nv = self.n_voxels[0] * self.n_voxels[1] * self.n_voxels[2]

        # array of voxels, initialized at None
        self.voxels = [None] * nv

        # add primitives to grid voxels
        for primitive in self.primitives:
            # find voxel extent of primitive
            primitive_bound = primitive.world_bound()
            v_min = []
            v_max = []
            for axis in range(3):
                v_min.append(self._pos_to_voxel(primitive_bound.p_min, axis))
                v_max.append(self._pos_to_voxel(primitive_bound.p_max, axis))

            # add primitive to overlapping voxels
            for z in range(v_min[2], v_max[2] + 1):
                for y in range(v_min[1], v_max[1] + 1):
                    for x in range(v_min[0], v_max[0] + 1):
                        index = self._offset(x, y, z)
                        if self.voxels[index] is None:
                            self.voxels[index] = Voxel(primitive)
                        else:
                            self.voxels[index].add_primitive(primitive)

        # create reader-writer mutex for grid
        self.rw_lock = DummyRWLock()