def test04_div(): a = C(1, 3) b = C(5, 7) c = a / b d = C(13 / 37, 4 / 37) assert ek.allclose(c, d) assert a / 2 == C(1 / 2, 3 / 2)
def test04_transform_point(variant_scalar_rgb): from mitsuba.core import Transform4f A = np.eye(4) A[3, 3] = 2 assert ek.allclose(Transform4f(A).transform_point([2, 4, 6]), [1, 2, 3]) try: mitsuba.set_variant("packet_rgb") from mitsuba.core import Transform4f as Transform4fX except: return assert ek.allclose( Transform4fX(A).transform_point([[2, 4], [4, 6], [6, 8]]), [[1, 2], [2, 3], [3, 4]])
def test01_create(variant_scalar_rgb): from mitsuba.core import xml, ScalarTransform4f s = xml.load_dict({"type" : "cylinder"}) assert s is not None assert s.primitive_count() == 1 assert ek.allclose(s.surface_area(), 2*ek.pi) # Test transforms order in constructor rot = ScalarTransform4f.rotate([1.0, 0.0, 0.0], 35) s1 = xml.load_dict({ "type" : "cylinder", "radius" : 2.0, "p0" : [1, 0, 0], "p1" : [1, 0, 2], "to_world" : rot }) s2 = xml.load_dict({ "type" : "cylinder", "to_world" : rot * ScalarTransform4f.translate([1, 0, 0]) * ScalarTransform4f.scale(2) }) assert str(s1) == str(s2)
def test_sample_ray(variant_scalar_rgb, direction): import enoki as ek from mitsuba.core import Vector2f, Vector3f emitter = make_emitter(direction=direction) direction = Vector3f(direction) time = 1.0 wavelength_sample = 0.3 directional_sample = [0.3, 0.2] for spatial_sample in [ [0.85, 0.13], [0.16, 0.50], [0.00, 1.00], [0.32, 0.87], [0.16, 0.44], [0.17, 0.44], [0.22, 0.81], [0.12, 0.82], [0.99, 0.42], [0.72, 0.40], [0.01, 0.61], ]: ray, _ = emitter.sample_ray( time, wavelength_sample, spatial_sample, directional_sample) # Check that ray direction is what is expected assert ek.allclose(ray.d, direction / ek.norm(direction)) # Check that ray origin is outside of bounding sphere # Bounding sphere is centered at world origin and has radius 1 without scene assert ek.norm(ray.o) >= 1.
def test04_normal_weighting_scheme(variant_scalar_rgb): from mitsuba.core import Struct, float_dtype, Vector3f from mitsuba.render import Mesh import numpy as np """Tests the weighting scheme that is used to compute surface normals.""" m = Mesh("MyMesh", 5, 2, has_vertex_normals=True) vertices = m.vertex_positions_buffer() normals = m.vertex_normals_buffer() a, b = 1.0, 0.5 vertices[:] = [0, 0, 0, -a, 1, 0, a, 1, 0, -b, 0, 1, b, 0, 1] n0 = Vector3f(0.0, 0.0, -1.0) n1 = Vector3f(0.0, 1.0, 0.0) angle_0 = ek.pi / 2.0 angle_1 = ek.acos(3.0 / 5.0) n2 = n0 * angle_0 + n1 * angle_1 n2 /= ek.norm(n2) n = np.vstack([n2, n0, n0, n1, n1]).transpose() m.faces_buffer()[:] = [0, 1, 2, 0, 3, 4] m.recompute_vertex_normals() for i in range(5): assert ek.allclose(normals[i*3:(i+1)*3], n[:, i], 5e-4)
def test01_create(variant_scalar_rgb): from mitsuba.core import xml s = xml.load_dict({"type": "sphere"}) assert s is not None assert s.primitive_count() == 1 assert ek.allclose(s.surface_area(), 4 * ek.pi)
def check_scene(int_name, scene_name, is_empty=False): from mitsuba.core.xml import load_string from mitsuba.core import Bitmap, Struct variant_name = mitsuba.variant() print("variant_name:", variant_name) integrator = make_integrator(int_name, "") scene = SCENES[scene_name]['factory']() integrator_type = { 'direct': 'direct', 'depth': 'depth', # All other integrators: 'full' }.get(int_name, 'full') sensor = scene.sensors()[0] avg = SCENES[scene_name][integrator_type] film = sensor.film() status = integrator.render(scene, sensor) assert status, "Rendering ({}) failed".format(variant_name) if False: _save(film, int_name, suffix='_' + variant_name) converted = film.bitmap(raw=True).convert(Bitmap.PixelFormat.RGBA, Struct.Type.Float32, False) values = np.array(converted, copy=False) means = np.mean(values, axis=(0, 1)) # Very noisy images, so we add a tolerance assert ek.allclose(means, avg, rtol=5e-2), \ "Mismatch: {} integrator, {} scene, {}".format( int_name, scene_name, variant_name) return np.array(film.bitmap(raw=False), copy=True)
def check_inverse(func, inverse): for x in ek.linspace(Float, 1e-6, 1-1e-6, 10): for y in ek.linspace(Float, 1e-6, 1-1e-6, 10): p1 = np.array([x, y]) p2 = func(p1) p3 = inverse(p2) assert(ek.allclose(p1, p3, atol=1e-5))
def test03_mueller_to_world_to_local(variant_scalar_mono_polarized): """ At a few places, coordinate changes between local BSDF reference frame and world coordinates need to take place. This change also needs to be applied to Mueller matrices used in computations involving polarization state. In practice, this is always a simple rotation of reference Stokes vectors (for incident & outgoing directions) of the Mueller matrix. To test this behavior we take any Mueller matrix (e.g. linear polarizer) for some arbitrary incident/outgoing directions in world coordinates and compute the round trip going to local frame and back again. """ from mitsuba.core import Frame3f, UnpolarizedSpectrum from mitsuba.render import SurfaceInteraction3f from mitsuba.render.mueller import linear_polarizer import numpy as np si = SurfaceInteraction3f() si.sh_frame = Frame3f(ek.normalize([1.0, 1.0, 1.0])) M = linear_polarizer(UnpolarizedSpectrum(1.0)) # Random incident and outgoing directions wi_world = ek.normalize([0.2, 0.0, 1.0]) wo_world = ek.normalize([0.0, -0.8, 1.0]) wi_local = si.to_local(wi_world) wo_local = si.to_local(wo_world) M_local = si.to_local_mueller(M, wi_world, wo_world) M_world = si.to_world_mueller(M_local, wi_local, wo_local) assert ek.allclose(M, M_world, atol=1e-5)
def test19_gather_fwd(m): x = ek.linspace(m.Float, -1, 1, 10) ek.enable_grad(x) y = ek.gather(m.Float, x * x, m.UInt(1, 1, 2, 3)) ek.forward(x) ref = [-1.55556, -1.55556, -1.11111, -0.666667] assert ek.allclose(ek.grad(y), ref)
def test_map_unit_cube(mode_mono): """ Returns a transformation that maps old cube vertices to new cube vertices. """ trafo = map_unit_cube(1, 2, 3, 4, 5, 6) vertices = [ [0, 0, 0], [1, 0, 0], [0, 1, 0], [1, 1, 0], [0, 0, 1], [1, 0, 1], [0, 1, 1], [1, 1, 1], ] new_vertices = [ [1, 3, 5], [2, 3, 5], [1, 4, 5], [2, 4, 5], [1, 3, 6], [2, 3, 6], [1, 4, 6], [2, 4, 6], ] for vertex, new_vertex in zip(vertices, new_vertices): assert ek.allclose( trafo.transform_point(vertex), new_vertex, )
def test02_eval_grad(variant_scalar_rgb): # Tests evaluating the texture gradient under different rotation from mitsuba.render import SurfaceInteraction3f from mitsuba.core.xml import load_string from mitsuba.core import Vector2f import numpy as np import enoki as ek delta = 1e-4 si = SurfaceInteraction3f() for u01 in np.random.rand(10, 1): angle = 360.0*u01[0] bitmap = load_string(""" <texture type="bitmap" version="2.0.0"> <string name="filename" value="resources/data/common/textures/noise_8x8.png"/> <transform name="to_uv"> <rotate angle="%f"/> </transform> </texture>""" % angle).expand()[0] for uv in np.random.rand(10, 2): si.uv = Vector2f(uv) f = bitmap.eval_1(si) si.uv = uv + Vector2f(delta, 0) fu = bitmap.eval_1(si) si.uv = uv + Vector2f(0, delta) fv = bitmap.eval_1(si) gradient_finite_difference = Vector2f((fu - f)/delta, (fv - f)/delta) gradient_analytic = bitmap.eval_1_grad(si) assert ek.allclose(0, ek.abs(gradient_finite_difference/gradient_analytic - 1.0), atol = 1e04)
def test03_ply_computed_normals(variant_scalar_rgb): from mitsuba.core import Vector3f from mitsuba.core.xml import load_string """Checks(automatic) vertex normal computation for a PLY file that doesn't have them.""" shape = load_string(""" <shape type="ply" version="0.5.0"> <string name="filename" value="data/triangle.ply"/> </shape> """) vertices = shape.vertices() assert shape.has_vertex_normals() # Normals are stored in half precision assert ek.allclose(vertices['nx'], [-1, -1, -1]) assert ek.allclose(vertices['ny'], [0, 0, 0]) assert ek.allclose(vertices['nz'], [0, 0, 0])
def test03_ray_intersect_transform(variant_scalar_rgb): from mitsuba.core import xml, Ray3f, Transform4f for r in [1, 3]: s = xml.load_dict({ "type": "sphere", "radius": r, "to_world": Transform4f.translate([0, 1, 0]) * Transform4f.rotate([0, 1, 0], 30.0) }) # grid size n = 21 inv_n = 1.0 / n for x in range(n): for y in range(n): x_coord = r * (2 * (x * inv_n) - 1) y_coord = r * (2 * (y * inv_n) - 1) ray = Ray3f(o=[x_coord, y_coord + 1, -8], d=[0.0, 0.0, 1.0], time=0.0, wavelengths=[]) si_found = s.ray_test(ray) assert si_found == (x_coord ** 2 + y_coord ** 2 <= r * r) \ or ek.abs(x_coord ** 2 + y_coord ** 2 - r * r) < 1e-8 if si_found: si = s.ray_intersect(ray) ray_u = Ray3f(ray) ray_v = Ray3f(ray) eps = 1e-4 ray_u.o += si.dp_du * eps ray_v.o += si.dp_dv * eps si_u = s.ray_intersect(ray_u) si_v = s.ray_intersect(ray_v) if si_u.is_valid(): du = (si_u.uv - si.uv) / eps assert ek.allclose(du, [1, 0], atol=2e-2) if si_v.is_valid(): dv = (si_v.uv - si.uv) / eps assert ek.allclose(dv, [0, 1], atol=2e-2)
def test_sample_ray(variant_packet_spectral, spectrum_key, wavelength_sample, pos_sample, cutoff_angle, lookat): # Check the correctness of the sample_ray() method from mitsuba.core import warp, sample_shifted, Transform4f from mitsuba.render import SurfaceInteraction3f cutoff_angle_rad = cutoff_angle / 180 * ek.pi cos_cutoff_angle_rad = ek.cos(cutoff_angle_rad) beam_width_rad = cutoff_angle_rad * 0.75 inv_transition_width = 1 / (cutoff_angle_rad - beam_width_rad) emitter, spectrum = create_emitter_and_spectrum(lookat, cutoff_angle, spectrum_key) eval_t = 0.3 trafo = Transform4f(emitter.world_transform().eval(eval_t)) # Sample a local direction and calculate local angle dir_sample = pos_sample # not being used anyway local_dir = warp.square_to_uniform_cone(pos_sample, cos_cutoff_angle_rad) angle = ek.acos(local_dir[2]) angle = ek.select( ek.abs(angle - beam_width_rad) < 1e-3, beam_width_rad, angle) angle = ek.select( ek.abs(angle - cutoff_angle_rad) < 1e-3, cutoff_angle_rad, angle) # Sample a ray (position, direction, wavelengths) from the emitter ray, res = emitter.sample_ray(eval_t, wavelength_sample, pos_sample, dir_sample) # Sample wavelengths on the spectrum it = SurfaceInteraction3f.zero() wav, spec = spectrum.sample_spectrum(it, sample_shifted(wavelength_sample)) it.wavelengths = wav spec = spectrum.eval(it) spec = ek.select( angle <= beam_width_rad, spec, spec * ((cutoff_angle_rad - angle) * inv_transition_width)) spec = ek.select(angle <= cutoff_angle_rad, spec, 0) assert ek.allclose( res, spec / warp.square_to_uniform_cone_pdf( trafo.inverse().transform_vector(ray.d), cos_cutoff_angle_rad)) assert ek.allclose(ray.time, eval_t) assert ek.all(local_dir.z >= cos_cutoff_angle_rad) assert ek.allclose(ray.wavelengths, wav) assert ek.allclose(ray.d, trafo.transform_vector(local_dir)) assert ek.allclose(ray.o, lookat.transform_point(0))
def test01_ray_intersect(variant_scalar_rgb, shape): from mitsuba.core import Ray3f from mitsuba.render import HitComputeFlags s, s_inst = example_scene(shape) # grid size n = 21 inv_n = 1.0 / n for x in range(n): for y in range(n): x_coord = (2 * (x * inv_n) - 1) y_coord = (2 * (y * inv_n) - 1) ray = Ray3f(o=[x_coord, y_coord + 1, -8], d=[0.0, 0.0, 1.0], time=0.0, wavelengths=[]) si_found = s.ray_test(ray) si_found_inst = s_inst.ray_test(ray) assert si_found == si_found_inst if si_found: si = s.ray_intersect( ray, HitComputeFlags.All | HitComputeFlags.dNSdUV) si_inst = s_inst.ray_intersect( ray, HitComputeFlags.All | HitComputeFlags.dNSdUV) assert si.prim_index == si_inst.prim_index assert si.instance is None assert si_inst.instance is not None assert ek.allclose(si.t, si_inst.t, atol=2e-2) assert ek.allclose(si.time, si_inst.time, atol=2e-2) assert ek.allclose(si.p, si_inst.p, atol=2e-2) assert ek.allclose(si.sh_frame.n, si_inst.sh_frame.n, atol=2e-2) assert ek.allclose(si.dp_du, si_inst.dp_du, atol=2e-2) assert ek.allclose(si.dp_dv, si_inst.dp_dv, atol=2e-2) assert ek.allclose(si.uv, si_inst.uv, atol=2e-2) assert ek.allclose(si.wi, si_inst.wi, atol=2e-2) if ek.norm(si.dn_du) > 0.0 and ek.norm(si.dn_dv) > 0.0: assert ek.allclose(si.dn_du, si_inst.dn_du, atol=2e-2) assert ek.allclose(si.dn_dv, si_inst.dn_dv, atol=2e-2)
def test22_scatter_rev(m): for i in range(3): idx1 = ek.arange(m.UInt, 5) idx2 = ek.arange(m.UInt, 4) + 3 x = ek.linspace(m.Float, 0, 1, 5) y = ek.linspace(m.Float, 1, 2, 4) buf = ek.zero(m.Float, 10) if i % 2 == 0: ek.enable_grad(buf) if i // 2 == 0: ek.enable_grad(x, y) x.label = "x" y.label = "y" buf.label = "buf" buf2 = m.Float(buf) ek.scatter(buf2, x, idx1) ek.eval(buf2) ek.scatter(buf2, y, idx2) ref_buf = m.Float(0.0000, 0.2500, 0.5000, 1.0000, 1.3333, 1.6667, 2.0000, 0.0000, 0.0000, 0.0000) assert ek.allclose(ref_buf, buf2, atol=1e-4) assert ek.allclose(ref_buf, buf, atol=1e-4) s = ek.dot_async(buf2, buf2) ek.backward(s) ref_x = m.Float(0.0000, 0.5000, 1.0000, 0.0000, 0.0000) ref_y = m.Float(2.0000, 2.6667, 3.3333, 4.0000) if i // 2 == 0: assert ek.allclose(ek.grad(y), ek.detach(ref_y), atol=1e-4) assert ek.allclose(ek.grad(x), ek.detach(ref_x), atol=1e-4) else: assert ek.grad(x) == 0 assert ek.grad(y) == 0 if i % 2 == 0: assert ek.allclose(ek.grad(buf), 0, atol=1e-4) else: assert ek.grad(buf) == 0
def test09_hsum_2_rev(m): x = ek.linspace(m.Float, 0, 1, 11) ek.enable_grad(x) z = ek.hsum_async(ek.hsum_async(x * x) * x * x) ek.backward(z) assert ek.allclose( ek.grad(x), [0., 1.54, 3.08, 4.62, 6.16, 7.7, 9.24, 10.78, 12.32, 13.86, 15.4])
def test50_gather_fwd_eager(m): with EagerMode(): x = ek.linspace(m.Float, -1, 1, 10) ek.enable_grad(x) ek.set_grad(x, 1) y = ek.gather(m.Float, x * x, m.UInt(1, 1, 2, 3)) ref = [-1.55556, -1.55556, -1.11111, -0.666667] assert ek.allclose(ek.grad(y), ref)
def test02_pdf(variant_scalar_rgb, interaction): from mitsuba.core.math import InvPi from mitsuba.render import BSDFContext from mitsuba.core.xml import load_string bsdf = load_string("""<bsdf version="2.0.0" type="twosided"> <bsdf type="diffuse"/> </bsdf>""") interaction.wi = [0, 0, 1] ctx = BSDFContext() p_pdf = bsdf.pdf(ctx, interaction, [0, 0, 1]) assert ek.allclose(p_pdf, InvPi) p_pdf = bsdf.pdf(ctx, interaction, [0, 0, -1]) assert ek.allclose(p_pdf, 0.0)
def test18_gather(m): x = ek.linspace(m.Float, -1, 1, 10) ek.enable_grad(x) y = ek.gather(m.Float, x * x, m.UInt(1, 1, 2, 3)) z = ek.hsum_async(y) ek.backward(z) ref = [0, -1.55556 * 2, -1.11111, -0.666667, 0, 0, 0, 0, 0, 0] assert ek.allclose(ek.grad(x), ref)
def test_invert_1d(variant_scalar_rgb): from mitsuba.core import spline values = Float([0.0, 0.25, 0.5, 0.75, 1.0]) assert (ek.allclose( spline.invert_1d(0, 1, values, spline.eval_1d(0, 1, values, 0.6)), 0.6)) values = Float([0.1, 0.2, 0.3, 0.35, 1]) assert (ek.allclose( spline.invert_1d(0, 1, values, spline.eval_1d(0, 1, values, 0.26)), 0.26)) assert (ek.allclose( spline.invert_1d(0, 1, values, spline.eval_1d(0, 1, values, 0.46)), 0.46)) assert (ek.allclose( spline.invert_1d(0, 1, values, spline.eval_1d(0, 1, values, 0.86)), 0.86))
def test_sample_1d_non_uniform(variant_scalar_rgb): from mitsuba.core import spline nodes = Float([0.0, 0.25, 0.5, 0.75, 1.0]) values = Float([0.0, 0.25, 0.5, 0.75, 1.0]) for i in range(10): res = spline.sample_1d(2 * nodes, values, spline.integrate_1d(2 * nodes, values), i / 10) assert (ek.allclose(res[1], res[2])) values = Float([1.0, 1.0, 1.0, 1.0, 1.0]) res = spline.sample_1d(nodes, values, spline.integrate_1d(nodes, values), 0.5) assert (ek.allclose(res[0], 0.5)) assert (ek.allclose(res[1], 1)) assert (ek.allclose(res[2], 1))
def test01_create(variant_scalar_rgb): if mitsuba.core.MTS_ENABLE_EMBREE: pytest.skip("EMBREE enabled") s = example_sphere() assert s is not None assert s.primitive_count() == 1 assert ek.allclose(s.surface_area(), 4 * ek.pi)
def test02_gauss_legendre(variant_scalar_rgb): from mitsuba.core.quad import gauss_legendre assert ek.allclose(gauss_legendre(1), [[0], [2]]) assert ek.allclose( gauss_legendre(2), [[-ek.sqrt(1.0 / 3.0), ek.sqrt(1.0 / 3.0)], [1, 1]]) assert ek.allclose( gauss_legendre(3), [[-ek.sqrt(3.0 / 5.0), 0, ek.sqrt(3.0 / 5.0)], [5.0 / 9.0, 8.0 / 9.0, 5.0 / 9.0]]) assert ek.allclose(gauss_legendre(4), [[ -0.861136, -0.339981, 0.339981, 0.861136, ], [0.347855, 0.652145, 0.652145, 0.347855]])
def test43_custom_reverse(m): d = m.Array3f(1, 2, 3) ek.enable_grad(d) d2 = ek.custom(Normalize, d) ek.set_grad(d2, m.Array3f(5, 6, 7)) ek.enqueue(d2) ek.traverse(m.Float, reverse=True) assert ek.allclose(ek.grad(d), m.Array3f(0.610883, 0.152721, -0.305441))
def test05_differentiable_surface_interaction_ray_forward( variant_gpu_autodiff_rgb): from mitsuba.core import xml, Ray3f, Vector3f, UInt32 shape = xml.load_dict({'type': 'sphere'}) ray = Ray3f(Vector3f(0.0, -10.0, 0.0), Vector3f(0.0, 1.0, 0.0), 0, []) pi = shape.ray_intersect_preliminary(ray) ek.set_requires_gradient(ray.o) ek.set_requires_gradient(ray.d) # If the ray origin is shifted along the x-axis, so does si.p si = pi.compute_surface_interaction(ray) ek.forward(ray.o.x) assert ek.allclose(ek.gradient(si.p), [1, 0, 0]) # If the ray origin is shifted along the z-axis, so does si.p si = pi.compute_surface_interaction(ray) ek.forward(ray.o.z) assert ek.allclose(ek.gradient(si.p), [0, 0, 1]) # If the ray origin is shifted along the y-axis, so does si.t si = pi.compute_surface_interaction(ray) ek.forward(ray.o.y) assert ek.allclose(ek.gradient(si.t), -1) # If the ray direction is shifted along the x-axis, so does si.p si = pi.compute_surface_interaction(ray) ek.forward(ray.d.x) assert ek.allclose(ek.gradient(si.p), [9, 0, 0]) # If the ray origin is shifted tangent to the sphere (azimuth), so si.uv.x move by 1 / 2pi ek.set_requires_gradient(ray.o) si = shape.ray_intersect(ray) ek.forward(ray.o.x) assert ek.allclose(ek.gradient(si.uv), [1 / (2.0 * ek.pi), 0]) # If the ray origin is shifted tangent to the sphere (inclination), so si.uv.y move by 2 / 2pi ek.set_requires_gradient(ray.o) si = shape.ray_intersect(ray) ek.forward(ray.o.z) assert ek.allclose(ek.gradient(si.uv), [0, -2 / (2.0 * ek.pi)]) # # If the ray origin is shifted along the x-axis, so does si.n ek.set_requires_gradient(ray.o) si = shape.ray_intersect(ray) ek.forward(ray.o.x) assert ek.allclose(ek.gradient(si.n), [1, 0, 0]) # # If the ray origin is shifted along the z-axis, so does si.n ek.set_requires_gradient(ray.o) si = shape.ray_intersect(ray) ek.forward(ray.o.z) assert ek.allclose(ek.gradient(si.n), [0, 0, 1])
def test_construct(variant_scalar_rgb): from mitsuba.core.xml import load_string # Test construct from to_world only_to_world = xml_sensor( params=xml_lookat(origin="0,0,0", target="0,1,0")) sensor = load_string(only_to_world) assert not sensor.bbox().valid() # Degenerate bounding box assert ek.allclose( sensor.world_transform().eval(0.).matrix, [[-1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]]) # Test construct from origin and direction origin_direction = xml_sensor(params=xml_origin("0,0,0") + xml_direction("0,1,0")) sensor = load_string(origin_direction) assert not sensor.bbox().valid() # Degenerate bounding box assert ek.allclose( sensor.world_transform().eval(0.).matrix, [[0, 0, 1, 0], [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1]]) # Test to_world overriding direction + origin to_world_origin_direction = xml_sensor( params=xml_lookat(origin="0,0,0", target="0,1,0") + xml_origin("1,0,0") + xml_direction("4,1,0")) sensor = load_string(to_world_origin_direction) assert not sensor.bbox().valid() # Degenerate bounding box assert ek.allclose( sensor.world_transform().eval(0.).matrix, [[-1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]]) # Test raise on missing direction or origin only_direction = xml_sensor(params=xml_direction("0,1,0")) with pytest.raises(RuntimeError): sensor = load_string(only_direction) only_origin = xml_sensor(params=xml_origin("0,1,0")) with pytest.raises(RuntimeError): sensor = load_string(only_origin) # Test raise on wrong film size with pytest.raises(RuntimeError): sensor = example_sensor(params=xml_lookat(origin="0,0,-2", target="0,0,0"), pixels=2)
def test09_trig(): for i in range(-5, 5): for j in range(-5, 5): a = ek.sin(C(i, j)) b = C(cmath.sin(complex(i, j))) assert ek.allclose(a, b) a = ek.cos(C(i, j)) b = C(cmath.cos(complex(i, j))) assert ek.allclose(a, b) sa, ca = ek.sincos(C(i, j)) sb = C(cmath.sin(complex(i, j))) cb = C(cmath.cos(complex(i, j))) assert ek.allclose(sa, sb) assert ek.allclose(ca, cb) # Python appears to handle the branch cuts # differently from Enoki, C, and Mathematica.. a = ek.asin(C(i, j + 0.1)) b = C(cmath.asin(complex(i, j + 0.1))) assert ek.allclose(a, b) a = ek.acos(C(i, j + 0.1)) b = C(cmath.acos(complex(i, j + 0.1))) assert ek.allclose(a, b) if abs(j) != 1 or i != 0: a = ek.atan(C(i, j)) b = C(cmath.atan(complex(i, j))) assert ek.allclose(a, b, atol=1e-7)
def test_sample_ray(variant_scalar_rgb, direction, origin): sample1 = [0.32, 0.87] sample2 = [0.16, 0.44] direction_str = ",".join([str(x) for x in direction]) origin_str = ",".join([str(x) for x in origin]) sensor = example_sensor(params=xml_direction(direction_str) + xml_origin(origin_str)) # Test regular ray sampling ray = sensor.sample_ray(1., 1., sample1, sample2, True) assert ek.allclose(ray[0].o, origin) assert ek.allclose(ray[0].d, ek.normalize(direction)) # Test ray differential sampling ray = sensor.sample_ray_differential(1., 1., sample2, sample1, True) assert ek.allclose(ray[0].o, origin) assert ek.allclose(ray[0].d, ek.normalize(direction)) assert not ray[0].has_differentials