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
def generate_ray(self, sample): """Generate a Ray from the camera.""" # Generate raster and camera samples p_ras = Point(sample.image_x, sample.image_y, 0) p_camera = self.raster_to_camera(p_ras) ray = Ray(Point(0, 0, 0), normalize(Vector.from_point(p_camera)), 0.0, float('inf')) # Modify ray for depth of field if self.lens_radius > 0.0: # Sample point on lens lens_u, lens_v = concentric_sample_disk(sample.lens_u, sample.lens_v) lens_u *= self.lens_radius lens_v *= self.lens_radius # Compute point on plane of focus ft = self.focal_distance / ray.d.z p_focus = ray(ft) # Update ray for effect of lens ray.o = Point(lens_u, lens_v, 0.0) ray.d = normalize(p_focus - ray.o) ray.time = sample.time ray = self.camera_to_world(ray) return 1.0, ray
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)
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()
def setUp(self): self.v1 = Vector(1, 1, 1) self.v2 = Vector(2, 2, 2) self.p1 = Point(1, 1, 1) self.p2 = Point(2, 2, 2)
class TestGeometry(unittest.TestCase): def setUp(self): self.v1 = Vector(1, 1, 1) self.v2 = Vector(2, 2, 2) self.p1 = Point(1, 1, 1) self.p2 = Point(2, 2, 2) def get_random_point(self): return Point(float(random.randint(0,100)) / 20.0, float(random.randint(0,100)) / 20.0, float(random.randint(0,100)) / 20.0) def test_point(self): # operator[] p = Point(1.0, 2.0, 3.0) self.assertEqual(p[0], 1.0) self.assertEqual(p[1], 2.0) self.assertEqual(p[2], 3.0) self.assertEqual(self.p1 * 4, 2 * self.p2) self.assertEqual(self.p2 - self.p1, self.v1) # operator[] for assignments p = Point(1.0, 2.0, 3.0) for i in range(3): p[i] = 9.0 self.assertEqual(p[i], 9.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) 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) 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)) 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)) def test_bounding_box_1(self): # test default constructor b = BBox() self.assertEqual(b.p_min, Point(float('inf'), float('inf'), float('inf'))) self.assertEqual(b.p_max, Point(-float('inf'), -float('inf'), -float('inf'))) def test_bounding_box_2(self): # test constructor from one point p = self.get_random_point() b1 = BBox(p) self.assertEqual(b1.p_min, p) self.assertEqual(b1.p_min, b1.p_max) def test_bounding_box_3(self): # test constructor from two points p1 = self.get_random_point() p2 = self.get_random_point() b2 = BBox(p1, p2) for i in range(3): self.assertEqual(b2.p_min[i], min(p1[i], p2[i])) self.assertEqual(b2.p_max[i], max(p1[i], p2[i])) def test_bounding_box_4(self): # test copy constructor bbox = BBox(Point(5, 5, 5), Point(7, 7, 7)) bbox2 = BBox.from_bbox(bbox) self.assertEqual(bbox.p_min, bbox2.p_min) self.assertEqual(bbox.p_max, bbox2.p_max) p1 = Point(6, 5.5, 7) p2 = Point(6, 7.5, 7) p3 = Point(6, 6.5, 4.5) # test methods self.assertEqual(bbox.inside(p1), True) self.assertEqual(bbox.inside(p2), False) self.assertEqual(bbox.inside(p3), False) bbox.expand(1) self.assertEqual(bbox.inside(p1), True) self.assertEqual(bbox.inside(p2), True) self.assertEqual(bbox.inside(p3), True) def test_bounding_box_5(self): bbox1 = BBox(Point(0, -2, 0), Point(1, -1, 1)) p1 = Point(-3,3,0.5) bbox2 = union(bbox1, p1) self.assertEqual(bbox2.p_min, Point(-3, -2, 0)) self.assertEqual(bbox2.p_max, Point(1, 3, 1)) def test_bounding_box_6(self): bbox1 = BBox(Point(0, -2, 0), Point(1, -1, 1)) bbox2 = BBox(Point(-2, 0, -2), Point(-1, 1, -1)) bbox3 = union(bbox1, bbox2) self.assertEqual(bbox3.p_min, Point(-2, -2, -2)) self.assertEqual(bbox3.p_max, Point(1, 1, 1)) def test_bounding_box_7(self): bbox1 = BBox(Point(0, 0, 0), Point(2, 2, 2)) bbox2 = BBox(Point(2.5, 2.5, 2.5), Point(3, 3, 3)) self.assertEqual(bbox1.overlaps(bbox2), False) bbox3 = BBox(Point(-1, -1, -1), Point(0.5, 0.5, 0.5)) self.assertEqual(bbox1.overlaps(bbox3), True) def test_bounding_box_8(self): bbox = BBox(Point(0, 0, 0), Point(2, 3, 2)) p, r = bbox.bounding_sphere() self.assertEqual(p, Point(1,1.5,1)) self.assertEqual(r, math.sqrt(1.5*1.5+1+1)) 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)
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())
def setUp(self): self.q = Quaternion() self.q1 = Quaternion(Vector(0.0, 0.0, 1.0), 0.5) self.q2 = Quaternion(Vector(1.0, 2.0, 3.0), 0.5)
def test_constructor(self): self.assertEqual(self.q.v, Vector(0.0, 0.0, 0.0)) self.assertEqual(self.q.w, 1.0)
class TestGeometry(unittest.TestCase): def setUp(self): self.v1 = Vector(1, 1, 1) self.v2 = Vector(2, 2, 2) self.p1 = Point(1, 1, 1) self.p2 = Point(2, 2, 2) def get_random_point(self): return Point( float(random.randint(0, 100)) / 20.0, float(random.randint(0, 100)) / 20.0, float(random.randint(0, 100)) / 20.0) def test_point(self): # operator[] p = Point(1.0, 2.0, 3.0) self.assertEqual(p[0], 1.0) self.assertEqual(p[1], 2.0) self.assertEqual(p[2], 3.0) self.assertEqual(self.p1 * 4, 2 * self.p2) self.assertEqual(self.p2 - self.p1, self.v1) # operator[] for assignments p = Point(1.0, 2.0, 3.0) for i in range(3): p[i] = 9.0 self.assertEqual(p[i], 9.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) 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) 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)) 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)) def test_bounding_box_1(self): # test default constructor b = BBox() self.assertEqual(b.p_min, Point(float('inf'), float('inf'), float('inf'))) self.assertEqual(b.p_max, Point(-float('inf'), -float('inf'), -float('inf'))) def test_bounding_box_2(self): # test constructor from one point p = self.get_random_point() b1 = BBox(p) self.assertEqual(b1.p_min, p) self.assertEqual(b1.p_min, b1.p_max) def test_bounding_box_3(self): # test constructor from two points p1 = self.get_random_point() p2 = self.get_random_point() b2 = BBox(p1, p2) for i in range(3): self.assertEqual(b2.p_min[i], min(p1[i], p2[i])) self.assertEqual(b2.p_max[i], max(p1[i], p2[i])) def test_bounding_box_4(self): # test copy constructor bbox = BBox(Point(5, 5, 5), Point(7, 7, 7)) bbox2 = BBox.from_bbox(bbox) self.assertEqual(bbox.p_min, bbox2.p_min) self.assertEqual(bbox.p_max, bbox2.p_max) p1 = Point(6, 5.5, 7) p2 = Point(6, 7.5, 7) p3 = Point(6, 6.5, 4.5) # test methods self.assertEqual(bbox.inside(p1), True) self.assertEqual(bbox.inside(p2), False) self.assertEqual(bbox.inside(p3), False) bbox.expand(1) self.assertEqual(bbox.inside(p1), True) self.assertEqual(bbox.inside(p2), True) self.assertEqual(bbox.inside(p3), True) def test_bounding_box_5(self): bbox1 = BBox(Point(0, -2, 0), Point(1, -1, 1)) p1 = Point(-3, 3, 0.5) bbox2 = union(bbox1, p1) self.assertEqual(bbox2.p_min, Point(-3, -2, 0)) self.assertEqual(bbox2.p_max, Point(1, 3, 1)) def test_bounding_box_6(self): bbox1 = BBox(Point(0, -2, 0), Point(1, -1, 1)) bbox2 = BBox(Point(-2, 0, -2), Point(-1, 1, -1)) bbox3 = union(bbox1, bbox2) self.assertEqual(bbox3.p_min, Point(-2, -2, -2)) self.assertEqual(bbox3.p_max, Point(1, 1, 1)) def test_bounding_box_7(self): bbox1 = BBox(Point(0, 0, 0), Point(2, 2, 2)) bbox2 = BBox(Point(2.5, 2.5, 2.5), Point(3, 3, 3)) self.assertEqual(bbox1.overlaps(bbox2), False) bbox3 = BBox(Point(-1, -1, -1), Point(0.5, 0.5, 0.5)) self.assertEqual(bbox1.overlaps(bbox3), True) def test_bounding_box_8(self): bbox = BBox(Point(0, 0, 0), Point(2, 3, 2)) p, r = bbox.bounding_sphere() self.assertEqual(p, Point(1, 1.5, 1)) self.assertEqual(r, math.sqrt(1.5 * 1.5 + 1 + 1)) 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)