예제 #1
0
def quat_to_euler(q):
    name = _ek.detail.array_name('Array', q.Type, [3], q.IsScalar)
    module = _modules.get(q.__module__)
    Array3f = getattr(module, name)

    sinp = 2 * _ek.fmsub(q.w, q.y, q.z * q.x)
    gimbal_lock = _ek.abs(sinp) > (1.0 - 5e-8)

    # roll (x-axis rotation)
    q_y_2 = _ek.sqr(q.y)
    sinr_cosp = 2 * _ek.fmadd(q.w, q.x, q.y * q.z)
    cosr_cosp = _ek.fnmadd(2, _ek.fmadd(q.x, q.x, q_y_2), 1)
    roll = _ek.select(gimbal_lock, 2 * _ek.atan2(q.x, q.w),
                      _ek.atan2(sinr_cosp, cosr_cosp))

    # pitch (y-axis rotation)
    pitch = _ek.select(gimbal_lock, _ek.copysign(0.5 * _ek.Pi, sinp),
                       _ek.asin(sinp))

    # yaw (z-axis rotation)
    siny_cosp = 2 * _ek.fmadd(q.w, q.z, q.x * q.y)
    cosy_cosp = _ek.fnmadd(2, _ek.fmadd(q.z, q.z, q_y_2), 1)
    yaw = _ek.select(gimbal_lock, 0, _ek.atan2(siny_cosp, cosy_cosp))

    return Array3f(roll, pitch, yaw)
예제 #2
0
def test05_scalar(t):
    if not ek.is_array_v(t) or ek.array_size_v(t) == 0:
        return
    get_class(t.__module__)

    if ek.is_mask_v(t):
        assert ek.all_nested(t(True))
        assert ek.any_nested(t(True))
        assert ek.none_nested(t(False))
        assert ek.all_nested(t(False) ^ t(True))
        assert ek.all_nested(ek.eq(t(False), t(False)))
        assert ek.none_nested(ek.eq(t(True), t(False)))

    if ek.is_arithmetic_v(t):
        assert t(1) + t(1) == t(2)
        assert t(3) - t(1) == t(2)
        assert t(2) * t(2) == t(4)
        assert ek.min(t(2), t(3)) == t(2)
        assert ek.max(t(2), t(3)) == t(3)

        if ek.is_signed_v(t):
            assert t(2) * t(-2) == t(-4)
            assert ek.abs(t(-2)) == t(2)

        if ek.is_integral_v(t):
            assert t(6) // t(2) == t(3)
            assert t(7) % t(2) == t(1)
            assert t(7) >> 1 == t(3)
            assert t(7) << 1 == t(14)
            assert t(1) | t(2) == t(3)
            assert t(1) ^ t(3) == t(2)
            assert t(1) & t(3) == t(1)
        else:
            assert t(6) / t(2) == t(3)
            assert ek.sqrt(t(4)) == t(2)
            assert ek.fmadd(t(1), t(2), t(3)) == t(5)
            assert ek.fmsub(t(1), t(2), t(3)) == t(-1)
            assert ek.fnmadd(t(1), t(2), t(3)) == t(1)
            assert ek.fnmsub(t(1), t(2), t(3)) == t(-5)
            assert (t(1) & True) == t(1)
            assert (t(1) & False) == t(0)
            assert (t(1) | False) == t(1)

        assert ek.all_nested(t(3) > t(2))
        assert ek.all_nested(ek.eq(t(2), t(2)))
        assert ek.all_nested(ek.neq(t(3), t(2)))
        assert ek.all_nested(t(1) >= t(1))
        assert ek.all_nested(t(2) < t(3))
        assert ek.all_nested(t(1) <= t(1))
        assert ek.select(ek.eq(t(2), t(2)), t(4), t(5)) == t(4)
        assert ek.select(ek.eq(t(3), t(2)), t(4), t(5)) == t(5)
        t2 = t(2)
        assert ek.hsum(t2) == t.Value(2 * len(t2))
        assert ek.dot(t2, t2) == t.Value(4 * len(t2))
        assert ek.dot_async(t2, t2) == t(4 * len(t2))

        value = t(1)
        value[ek.eq(value, t(1))] = t(2)
        value[ek.eq(value, t(3))] = t(5)
        assert value == t(2)
예제 #3
0
파일: matrix.py 프로젝트: YangWang92/enoki
def det(m):
    if not _ek.is_matrix_v(m):
        raise Exception("Unsupported target type!")

    if m.Size == 1:
        return m[0, 0]
    elif m.Size == 2:
        return _ek.fmsub(m[0, 0], m[1, 1], m[0, 1] * m[1, 0])
    elif m.Size == 3:
        return _ek.dot(m[0], _ek.cross(m[1], m[2]))
    elif m.Size == 4:
        col0, col1, col2, col3 = m

        col1 = _ek.shuffle((2, 3, 0, 1), col1)
        col3 = _ek.shuffle((2, 3, 0, 1), col3)

        temp = _ek.shuffle((1, 0, 3, 2), col2 * col3)
        row0 = col1 * temp
        temp = _ek.shuffle((2, 3, 0, 1), temp)
        row0 = _ek.fmsub(col1, temp, row0)

        temp = _ek.shuffle((1, 0, 3, 2), col1 * col2)
        row0 = _ek.fmadd(col3, temp, row0)
        temp = _ek.shuffle((2, 3, 0, 1), temp)
        row0 = _ek.fnmadd(col3, temp, row0)

        col1 = _ek.shuffle((2, 3, 0, 1), col1)
        col2 = _ek.shuffle((2, 3, 0, 1), col2)
        temp = _ek.shuffle((1, 0, 3, 2), col1 * col3)
        row0 = _ek.fmadd(col2, temp, row0)
        temp = _ek.shuffle((2, 3, 0, 1), temp)
        row0 = _ek.fnmadd(col2, temp, row0)

        return _ek.dot(col0, row0)
    else:
        raise Exception('Unsupported array size!')
예제 #4
0
def test04_operators():
    I3 = ek.scalar.Array3i
    F3 = ek.scalar.Array3f

    assert (I3(1, 2, 3) + I3(0, 1, 0) == I3(1, 3, 3))
    assert (I3(1, 2, 3) - I3(0, 1, 0) == I3(1, 1, 3))
    assert (I3(1, 2, 3) * I3(0, 1, 0) == I3(0, 2, 0))
    assert (I3(1, 2, 3) // I3(2, 2, 2) == I3(0, 1, 1))
    assert (I3(1, 2, 3) % I3(2, 2, 2) == I3(1, 0, 1))
    assert (I3(1, 2, 3) << 1 == I3(2, 4, 6))
    assert (I3(1, 2, 3) >> 1 == I3(0, 1, 1))
    assert (I3(1, 2, 3) & 1 == I3(1, 0, 1))
    assert (I3(1, 2, 3) | 1 == I3(1, 3, 3))
    assert (I3(1, 2, 3) ^ 1 == I3(0, 3, 2))
    assert (-I3(1, 2, 3) == I3(-1, -2, -3))
    assert (~I3(1, 2, 3) == I3(-2, -3, -4))
    assert (ek.abs(I3(1, -2, 3)) == I3(1, 2, 3))
    assert (abs(I3(1, -2, 3)) == I3(1, 2, 3))
    assert (ek.abs(I3(1, -2, 3)) == I3(1, 2, 3))
    assert (ek.fmadd(F3(1, 2, 3), F3(2, 3, 1), F3(1, 1, 1)) == F3(3, 7, 4))
    assert (ek.fmsub(F3(1, 2, 3), F3(2, 3, 1), F3(1, 1, 1)) == F3(1, 5, 2))
    assert (ek.fnmadd(F3(1, 2, 3), F3(2, 3, 1), F3(1, 1, 1)) == F3(-1, -5, -2))
    assert (ek.fnmsub(F3(1, 2, 3), F3(2, 3, 1), F3(1, 1, 1)) == F3(-3, -7, -4))
예제 #5
0
def mul_(a0, a1):
    if not a0.IsArithmetic:
        raise Exception("mul(): requires arithmetic operands!")

    if _ek.array_depth_v(a1) < _ek.array_depth_v(a0):
        # Avoid type promotion in scalars multiplication, which would
        # be costly for special types (matrices, quaternions, etc.)
        sr = len(a0)
        ar = a0.empty_(sr if a0.Size == Dynamic else 0)
        for i in range(len(a0)):
            ar[i] = a0[i] * a1
        return ar

    ar, sr = _check2(a0, a1)
    if not a0.IsSpecial:
        for i in range(sr):
            ar[i] = a0[i] * a1[i]
    elif a0.IsComplex:
        ar.real = _ek.fmsub(a0.real, a1.real, a0.imag * a1.imag)
        ar.imag = _ek.fmadd(a0.real, a1.imag, a0.imag * a1.real)
    elif a0.IsQuaternion:
        tbl = (4, 3, -2, 1, -3, 4, 1, 2, 2, -1, 4, 3, -1, -2, -3, 4)
        for i in range(4):
            accum = 0
            for j in range(4):
                idx = tbl[i * 4 + j]
                value = a1[abs(idx) - 1]
                accum = _ek.fmadd(a0[j], value if idx > 0 else -value, accum)
            ar[i] = accum
    elif a0.IsMatrix:
        raise Exception(
            "mul(): please use the matrix multiplication operator '@' instead."
        )
    else:
        raise Exception("mul(): unsupported array type!")
    return ar
예제 #6
0
파일: matrix.py 프로젝트: YangWang92/enoki
def quat_to_euler(q):
    q_y_2 = _ek.sqr(q.y)

    sinr_cosp = 2 * _ek.fmadd(q.w, q.x, q.y * q.z)
    cosr_cosp = _ek.fnmadd(2, _ek.fmadd(q.x, q.x, q_y_2), 1)
    roll = _ek.atan2(sinr_cosp, cosr_cosp)

    # pitch (y-axis rotation)
    sinp = 2 * _ek.fmsub(q.w, q.y, q.z * q.x)
    if (_ek.abs(sinp) >= 1.0):
        pitch = _ek.copysign(0.5 * _ek.Pi, sinp)
    else:
        pitch = _ek.asin(sinp)

    # yaw (z-axis rotation)
    siny_cosp = 2 * _ek.fmadd(q.w, q.z, q.x * q.y)
    cosy_cosp = _ek.fnmadd(2, _ek.fmadd(q.z, q.z, q_y_2), 1)
    yaw = _ek.atan2(siny_cosp, cosy_cosp)

    name = _ek.detail.array_name('Array', q.Type, [3], q.IsScalar)
    module = _modules.get(q.__module__)
    Array3f = getattr(module, name)

    return Array3f(roll, pitch, yaw)
예제 #7
0
def outgoing_direction(n_phi,
                       n_theta,
                       Dvis_sampler,
                       theta_i,
                       phi_i,
                       isotropic,
                       theta_max=np.pi / 2,
                       all=False):
    from mitsuba.core import Vector2f, Frame3f
    from mitsuba.core import MarginalContinuous2D2

    print("Max theta angle is %f deg." % np.degrees(theta_max))

    phi_o = np.zeros((phi_i.size, theta_i.size, n_phi, n_theta))
    theta_o = np.zeros((phi_i.size, theta_i.size, n_phi, n_theta))
    invalid = np.ones((phi_i.size, theta_i.size, n_phi, n_theta), dtype='bool')
    active = np.ones((phi_i.size, theta_i.size, n_phi, n_theta), dtype='bool')

    # Create uniform samples
    u_0 = np.linspace(0, 1, n_theta)
    u_1 = np.linspace(0, 1, n_phi)
    samples = Vector2f(np.tile(u_0, n_phi), np.repeat(u_1, n_theta))

    # Construct projected surface area interpolant data structure
    params = [phi_i.tolist(), theta_i.tolist()]
    m_vndf = MarginalContinuous2D2(Dvis_sampler, params, normalize=True)

    for i in range(phi_i.size):
        for j in range(theta_i.size):
            # Warp uniform samples by VNDF distribution (G1 mapping)
            u_m, ndf_pdf = m_vndf.sample(samples, [phi_i[i], theta_i[j]])
            # Convert samples to radians (G2 mapping)
            theta_m = u2theta(u_m.x)  # [0, 1] -> [0, pi]
            phi_m = u2phi(u_m.y)  # [0, 1] -> [0, 2pi]
            if isotropic:
                phi_m += phi_i[i]
            # Phase vector
            m = spherical2cartesian(theta_m, phi_m)
            # Incident direction
            wi = spherical2cartesian(theta_i[j], phi_i[i])
            # Outgoing direction (reflection over phase vector)
            wo = ek.fmsub(m, 2.0 * ek.dot(m, wi), wi)
            tmp1, tmp2 = cartesian2spherical(wo)
            # Remove invalid directions
            act = u_m.y > 0  # covered twice [-pi = pi]
            inv = Frame3f.cos_theta(wo) < 0  # below surface plane
            act &= np.invert(inv)  # above surface plane
            act &= tmp1 <= (theta_max + EPSILON)  # further angular restriction
            if isotropic:
                act &= tmp2 >= 0
            if not all:
                tmp1[~act] = 0
                tmp2[~act] = 0
            else:
                tmp1[inv] = 0
                tmp2[inv] = 0

            # Fit to datashape
            act = np.reshape(act, (n_phi, n_theta))
            inv = np.reshape(inv, (n_phi, n_theta))
            tmp1 = np.reshape(tmp1, (n_phi, n_theta))
            tmp2 = np.reshape(tmp2, (n_phi, n_theta))

            # Append
            active[i, j] = act
            invalid[i, j] = inv
            theta_o[i, j] = tmp1
            phi_o[i, j] = tmp2
    return [theta_o, phi_o, active, invalid]
예제 #8
0
파일: matrix.py 프로젝트: YangWang92/enoki
def inverse_transpose(m):
    if not _ek.is_matrix_v(m):
        raise Exception("Unsupported target type!")

    t = type(m)
    if m.Size == 1:
        return t(_ek.rcp(m[0, 0]))
    elif m.Size == 2:
        inv_det = _ek.rcp(_ek.fmsub(m[0, 0], m[1, 1], m[0, 1] * m[1, 0]))
        return t(m[1, 1] * inv_det, -m[1, 0] * inv_det, -m[0, 1] * inv_det,
                 m[0, 0] * inv_det)
    elif m.Size == 3:
        col0, col1, col2 = m
        row0 = _ek.cross(col1, col2)
        row1 = _ek.cross(col2, col0)
        row2 = _ek.cross(col0, col1)
        inv_det = _ek.rcp(_ek.dot(col0, row0))

        return t(row0 * inv_det, row1 * inv_det, row2 * inv_det)

    elif m.Size == 4:
        col0, col1, col2, col3 = m

        col1 = _ek.shuffle((2, 3, 0, 1), col1)
        col3 = _ek.shuffle((2, 3, 0, 1), col3)

        temp = _ek.shuffle((1, 0, 3, 2), col2 * col3)
        row0 = col1 * temp
        row1 = col0 * temp
        temp = _ek.shuffle((2, 3, 0, 1), temp)
        row0 = _ek.fmsub(col1, temp, row0)
        row1 = _ek.shuffle((2, 3, 0, 1), _ek.fmsub(col0, temp, row1))

        temp = _ek.shuffle((1, 0, 3, 2), col1 * col2)
        row0 = _ek.fmadd(col3, temp, row0)
        row3 = col0 * temp
        temp = _ek.shuffle((2, 3, 0, 1), temp)
        row0 = _ek.fnmadd(col3, temp, row0)
        row3 = _ek.shuffle((2, 3, 0, 1), _ek.fmsub(col0, temp, row3))

        temp = _ek.shuffle((1, 0, 3, 2),
                           _ek.shuffle((2, 3, 0, 1), col1) * col3)
        col2 = _ek.shuffle((2, 3, 0, 1), col2)
        row0 = _ek.fmadd(col2, temp, row0)
        row2 = col0 * temp
        temp = _ek.shuffle((2, 3, 0, 1), temp)
        row0 = _ek.fnmadd(col2, temp, row0)
        row2 = _ek.shuffle((2, 3, 0, 1), _ek.fmsub(col0, temp, row2))

        temp = _ek.shuffle((1, 0, 3, 2), col0 * col1)
        row2 = _ek.fmadd(col3, temp, row2)
        row3 = _ek.fmsub(col2, temp, row3)
        temp = _ek.shuffle((2, 3, 0, 1), temp)
        row2 = _ek.fmsub(col3, temp, row2)
        row3 = _ek.fnmadd(col2, temp, row3)

        temp = _ek.shuffle((1, 0, 3, 2), col0 * col3)
        row1 = _ek.fnmadd(col2, temp, row1)
        row2 = _ek.fmadd(col1, temp, row2)
        temp = _ek.shuffle((2, 3, 0, 1), temp)
        row1 = _ek.fmadd(col2, temp, row1)
        row2 = _ek.fnmadd(col1, temp, row2)

        temp = _ek.shuffle((1, 0, 3, 2), col0 * col2)
        row1 = _ek.fmadd(col3, temp, row1)
        row3 = _ek.fnmadd(col1, temp, row3)
        temp = _ek.shuffle((2, 3, 0, 1), temp)
        row1 = _ek.fnmadd(col3, temp, row1)
        row3 = _ek.fmadd(col1, temp, row3)

        inv_det = _ek.rcp(_ek.dot(col0, row0))

        return t(row0 * inv_det, row1 * inv_det, row2 * inv_det,
                 row3 * inv_det)
    else:
        raise Exception('Unsupported array size!')