コード例 #1
0
 TwoTransformsFixture()
     : m_expected_first_transform(Matrix4d::translation(Vector3d(1.0, 2.0, 3.0)))
     , m_expected_second_transform(Matrix4d::translation(Vector3d(4.0, 5.0, 6.0)))
 {
     m_sequence.set_transform(1.0, m_expected_first_transform);
     m_sequence.set_transform(3.0, m_expected_second_transform);
     m_sequence.prepare();
 }
コード例 #2
0
TransformSequence TransformSequence::operator*(const TransformSequence& rhs) const
{
    TransformSequence result;

    size_t lhs_i = 0, rhs_i = 0;
    Transformd scratch;

    while (lhs_i < m_size && rhs_i < rhs.m_size)
    {
        const double lhs_t = m_keys[lhs_i].m_time;
        const double rhs_t = rhs.m_keys[rhs_i].m_time;

        if (lhs_t == rhs_t)
        {
            result.set_transform(lhs_t, m_keys[lhs_i].m_transform * rhs.m_keys[rhs_i].m_transform);
            ++lhs_i;
            ++rhs_i;
        }
        else if (lhs_t < rhs_t)
        {
            result.set_transform(lhs_t, m_keys[lhs_i].m_transform * rhs.evaluate(lhs_t, scratch));
            ++lhs_i;
        }
        else
        {
            result.set_transform(rhs_t, evaluate(rhs_t, scratch) * rhs.m_keys[rhs_i].m_transform);
            ++rhs_i;
        }
    }

    while (lhs_i < m_size)
    {
        const double lhs_t = m_keys[lhs_i].m_time;
        result.set_transform(lhs_t, m_keys[lhs_i].m_transform * rhs.evaluate(lhs_t, scratch));
        ++lhs_i;
    }

    while (rhs_i < rhs.m_size)
    {
        const double rhs_t = rhs.m_keys[rhs_i].m_time;
        result.set_transform(rhs_t, evaluate(rhs_t, scratch) * rhs.m_keys[rhs_i].m_transform);
        ++rhs_i;
    }

    return result;
}
コード例 #3
0
ファイル: lightsampler.cpp プロジェクト: docwhite/appleseed
void LightSampler::collect_emitting_triangles(
    const Assembly&                     assembly,
    const AssemblyInstance&             assembly_instance,
    const TransformSequence&            transform_sequence)
{
    // Loop over the object instances of the assembly.
    const size_t object_instance_count = assembly.object_instances().size();
    for (size_t object_instance_index = 0; object_instance_index < object_instance_count; ++object_instance_index)
    {
        // Retrieve the object instance.
        const ObjectInstance* object_instance = assembly.object_instances().get_by_index(object_instance_index);

        // Retrieve the materials of the object instance.
        const MaterialArray& front_materials = object_instance->get_front_materials();
        const MaterialArray& back_materials = object_instance->get_back_materials();

        // Skip object instances without light-emitting materials.
        if (!has_emitting_materials(front_materials) && !has_emitting_materials(back_materials))
            continue;

        double object_area = 0.0;

        // Compute the object space to world space transformation.
        // todo: add support for moving light-emitters.
        const Transformd& object_instance_transform = object_instance->get_transform();
        const Transformd& assembly_instance_transform = transform_sequence.get_earliest_transform();
        const Transformd global_transform = assembly_instance_transform * object_instance_transform;

        // Retrieve the object.
        Object& object = object_instance->get_object();

        // Retrieve the region kit of the object.
        Access<RegionKit> region_kit(&object.get_region_kit());

        // Loop over the regions of the object.
        const size_t region_count = region_kit->size();
        for (size_t region_index = 0; region_index < region_count; ++region_index)
        {
            // Retrieve the region.
            const IRegion* region = (*region_kit)[region_index];

            // Retrieve the tessellation of the region.
            Access<StaticTriangleTess> tess(&region->get_static_triangle_tess());

            // Loop over the triangles of the region.
            const size_t triangle_count = tess->m_primitives.size();
            for (size_t triangle_index = 0; triangle_index < triangle_count; ++triangle_index)
            {
                // Fetch the triangle.
                const Triangle& triangle = tess->m_primitives[triangle_index];

                // Skip triangles without a material.
                if (triangle.m_pa == Triangle::None)
                    continue;

                // Fetch the materials assigned to this triangle.
                const size_t pa_index = static_cast<size_t>(triangle.m_pa);
                const Material* front_material =
                    pa_index < front_materials.size() ? front_materials[pa_index] : 0;
                const Material* back_material =
                    pa_index < back_materials.size() ? back_materials[pa_index] : 0;

                // Skip triangles that don't emit light.
                if ((front_material == 0 || front_material->has_emission() == false) &&
                    (back_material == 0 || back_material->has_emission() == false))
                    continue;

                // Retrieve object instance space vertices of the triangle.
                const GVector3& v0_os = tess->m_vertices[triangle.m_v0];
                const GVector3& v1_os = tess->m_vertices[triangle.m_v1];
                const GVector3& v2_os = tess->m_vertices[triangle.m_v2];

                // Transform triangle vertices to assembly space.
                const GVector3 v0_as = object_instance_transform.point_to_parent(v0_os);
                const GVector3 v1_as = object_instance_transform.point_to_parent(v1_os);
                const GVector3 v2_as = object_instance_transform.point_to_parent(v2_os);

                // Compute the support plane of the hit triangle in assembly space.
                const GTriangleType triangle_geometry(v0_as, v1_as, v2_as);
                TriangleSupportPlaneType triangle_support_plane;
                triangle_support_plane.initialize(TriangleType(triangle_geometry));

                // Transform triangle vertices to world space.
                const Vector3d v0(assembly_instance_transform.point_to_parent(v0_as));
                const Vector3d v1(assembly_instance_transform.point_to_parent(v1_as));
                const Vector3d v2(assembly_instance_transform.point_to_parent(v2_as));

                // Compute the geometric normal to the triangle and the area of the triangle.
                Vector3d geometric_normal = cross(v1 - v0, v2 - v0);
                const double geometric_normal_norm = norm(geometric_normal);
                if (geometric_normal_norm == 0.0)
                    continue;
                const double rcp_geometric_normal_norm = 1.0 / geometric_normal_norm;
                const double rcp_area = 2.0 * rcp_geometric_normal_norm;
                const double area = 0.5 * geometric_normal_norm;
                geometric_normal *= rcp_geometric_normal_norm;
                assert(is_normalized(geometric_normal));

                // Retrieve object instance space vertex normals.
                Vector3d n0_os, n1_os, n2_os;

                if (triangle.m_n0 != Triangle::None &&
                    triangle.m_n1 != Triangle::None &&
                    triangle.m_n2 != Triangle::None)
                {
                    n0_os = Vector3d(tess->m_vertex_normals[triangle.m_n0]);
                    n1_os = Vector3d(tess->m_vertex_normals[triangle.m_n1]);
                    n2_os = Vector3d(tess->m_vertex_normals[triangle.m_n2]);
                }
                else
                    n0_os = n1_os = n2_os = geometric_normal;

                // Transform vertex normals to world space.
                const Vector3d n0(normalize(global_transform.normal_to_parent(n0_os)));
                const Vector3d n1(normalize(global_transform.normal_to_parent(n1_os)));
                const Vector3d n2(normalize(global_transform.normal_to_parent(n2_os)));

                for (size_t side = 0; side < 2; ++side)
                {
                    // Retrieve the material; skip sides without a material or without emission.
                    const Material* material = side == 0 ? front_material : back_material;
                    if (material == 0 || material->has_emission() == false)
                        continue;

                    // Retrieve the EDF and get the importance multiplier.
                    double importance_multiplier = 1.0;
                    if (const EDF* edf = material->get_uncached_edf())
                        importance_multiplier = edf->get_uncached_importance_multiplier();

                    // Accumulate the object area for OSL shaders.
                    object_area += area;

                    // Compute the probability density of this triangle.
                    const double triangle_importance = m_params.m_importance_sampling ? area : 1.0;
                    const double triangle_prob = triangle_importance * importance_multiplier;

                    // Create a light-emitting triangle.
                    EmittingTriangle emitting_triangle;
                    emitting_triangle.m_assembly_instance = &assembly_instance;
                    emitting_triangle.m_object_instance_index = object_instance_index;
                    emitting_triangle.m_region_index = region_index;
                    emitting_triangle.m_triangle_index = triangle_index;
                    emitting_triangle.m_v0 = v0;
                    emitting_triangle.m_v1 = v1;
                    emitting_triangle.m_v2 = v2;
                    emitting_triangle.m_n0 = side == 0 ? n0 : -n0;
                    emitting_triangle.m_n1 = side == 0 ? n1 : -n1;
                    emitting_triangle.m_n2 = side == 0 ? n2 : -n2;
                    emitting_triangle.m_geometric_normal = side == 0 ? geometric_normal : -geometric_normal;
                    emitting_triangle.m_triangle_support_plane = triangle_support_plane;
                    emitting_triangle.m_rcp_area = rcp_area;
                    emitting_triangle.m_triangle_prob = 0.0;    // will be initialized once the emitting triangle CDF is built
                    emitting_triangle.m_material = material;

                    // Store the light-emitting triangle.
                    const size_t emitting_triangle_index = m_emitting_triangles.size();
                    m_emitting_triangles.push_back(emitting_triangle);

                    // Insert the light-emitting triangle into the CDF.
                    m_emitting_triangles_cdf.insert(emitting_triangle_index, triangle_prob);
                }
            }
        }

#ifdef APPLESEED_WITH_OSL
        store_object_area_in_shadergroups(
            &assembly_instance,
            object_instance,
            object_area,
            front_materials);

        store_object_area_in_shadergroups(
            &assembly_instance,
            object_instance,
            object_area,
            back_materials);
#endif
    }
}