Beispiel #1
0
void LightSampler::collect_emitting_triangles(
    const Scene&            scene,
    const AssemblyInstance& assembly_instance)
{
    // Loop over the object instances of the assembly.
    const Assembly& assembly = assembly_instance.get_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;

        // 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 =
            assembly_instance.transform_sequence().empty()
                ? Transformd(Matrix4d::identity())
                : assembly_instance.transform_sequence().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];
                const size_t pa_index = static_cast<size_t>(triangle.m_pa);

                // Fetch the materials assigned to this triangle.
                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->get_edf() == 0) &&
                    (back_material == 0 || back_material->get_edf() == 0))
                    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.
                const GVector3& n0_os = tess->m_vertex_normals[triangle.m_n0];
                const GVector3& n1_os = tess->m_vertex_normals[triangle.m_n1];
                const GVector3& n2_os = tess->m_vertex_normals[triangle.m_n2];

                // 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)
                {
                    const Material* material = side == 0 ? front_material : back_material;
                    const Vector3d side_geometric_normal = side == 0 ? geometric_normal : -geometric_normal;
                    const Vector3d side_n0 = side == 0 ? n0 : -n0;
                    const Vector3d side_n1 = side == 0 ? n1 : -n1;
                    const Vector3d side_n2 = side == 0 ? n2 : -n2;

                    // Skip sides without a light-emitting material.
                    if (material == 0 || material->get_edf() == 0)
                        continue;

                    // 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_n0;
                    emitting_triangle.m_n1 = side_n1;
                    emitting_triangle.m_n2 = side_n2;
                    emitting_triangle.m_geometric_normal = side_geometric_normal;
                    emitting_triangle.m_triangle_support_plane = triangle_support_plane;
                    emitting_triangle.m_rcp_area = rcp_area;
                    emitting_triangle.m_edf = material->get_edf();

                    // 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 CDFs.
                    m_emitter_cdf.insert(emitting_triangle_index + m_lights.size(), area);
                    m_emitting_triangle_cdf.insert(emitting_triangle_index, area);

                    // Keep track of the total area of the light-emitting triangles.
                    m_total_emissive_area += area;
                }
            }
        }
    }
}
void CameraController::update_camera_transform()
{
    // Moving the camera kills camera motion blur.
    m_camera->transform_sequence().clear();
    m_camera->transform_sequence().set_transform(0.0, Transformd(m_controller.get_transform()));
}
Beispiel #3
0
bool AnimationPath::load(const char* filename, const Format format)
{
    m_keyframes.clear();

    AutoClosingFile file(filename, "rt");

    if (file == 0)
    {
        LOG_ERROR(m_logger, "could not read animation path file %s.", filename);
        return false;
    }

    char header[1000];

    if (fgets(header, sizeof(header), file) == 0)
    {
        LOG_ERROR(m_logger, "could not read animation path file %s.", filename);
        return false;
    }

    if (strcmp(header, "frame pos_x pos_y pos_z rot_x rot_y rot_z rot_w\n"))
    {
        LOG_ERROR(m_logger, "%s is not a valid animation path file.", filename);
        return false;
    }

    int line = 2;

    while (!feof(file))
    {
        int frame;
        Vector3d position;
        Quaterniond orientation;

        const int fields_read =
            fscanf(
                file,
                "%d %lf %lf %lf %lf %lf %lf %lf\n",
                &frame,
                &position.x, &position.y, &position.z,
                &orientation.v.x, &orientation.v.y, &orientation.v.z, &orientation.s);

        if (fields_read != 8)
        {
            LOG_ERROR(
                m_logger,
                "while reading animation path file %s: at line %d: parse error.",
                filename,
                line);
            return false;
        }

        const int expected_frame = line - 2;

        if (frame != expected_frame)
        {
            LOG_ERROR(
                m_logger,
                "while reading animation path file %s: at line %d: expected frame %d, got frame %d.",
                filename,
                line,
                expected_frame,
                frame);
            return false;
        }

        if (!feq(norm(orientation), 1.0, 1.0e-4))
        {
            LOG_ERROR(
                m_logger,
                "while reading animation path file %s: at line %d: invalid rotation.",
                filename,
                line);
            return false;
        }

        orientation = normalize(orientation);

        if (format == Autodesk3dsMax)
        {
            position = from_3ds_max(position);
            orientation.v = from_3ds_max(orientation.v);

            m_keyframes.push_back(
                Transformd(
                    Matrix4d::translation(position) *
                    Matrix4d::rotation(orientation) *
                    Matrix4d::rotation(Vector3d(1.0, 0.0, 0.0), -HalfPi)));
        }
        else
        {
            m_keyframes.push_back(
                Transformd(
                    Matrix4d::translation(position) *
                    Matrix4d::rotation(orientation)));
        }

        ++line;
    }

    LOG_INFO(
        m_logger,
        "read %d keyframe%s from animation path file %s.",
        m_keyframes.size(),
        m_keyframes.size() > 1 ? "s" : "",
        filename);

    return true;
}
Beispiel #4
0
// Create a new instance of the default project.
auto_release_ptr<Project> DefaultProjectFactory::create()
{
    // Create a project.
    auto_release_ptr<Project> project(ProjectFactory::create("default"));

    // Add default configurations to the project.
    project->add_default_configurations();

    // Create a scene.
    auto_release_ptr<Scene> scene(SceneFactory::create());

    // Create an assembly.
    auto_release_ptr<Assembly> assembly(
        AssemblyFactory::create("assembly", ParamArray()));

    // Create an instance of the assembly and insert it into the scene.
    scene->assembly_instances().insert(
        AssemblyInstanceFactory::create(
            "assembly_inst",
            ParamArray(),
            *assembly,
            Transformd(Matrix4d::identity())));

    // Insert the assembly into the scene.
    scene->assemblies().insert(assembly);

    //
    // Camera.
    //

    {
        // Create a pinhole camera.
        // Film dimensions are 0.980 in × 0.735 in (24.892 mm x 18.669 mm).
        // Reference: http://en.wikipedia.org/wiki/Aspect_ratio_(image).
        ParamArray params;
        params.insert("film_dimensions", "0.024892 0.018669");
        params.insert("focal_length", "0.035");
        auto_release_ptr<Camera> camera(
            PinholeCameraFactory().create("camera", params));

        // Attach the camera to the scene.
        scene->set_camera(camera);
    }

    //
    // Frame.
    //

    {
        // Create a frame.
        ParamArray params;
        params.insert("camera", scene->get_camera()->get_name());
        params.insert("resolution", "640 480");
        params.insert("color_space", "srgb");
        auto_release_ptr<Frame> frame(FrameFactory::create("beauty", params));

        // Attach the frame to the project.
        project->set_frame(frame);
    }

    // Attach the scene to the project.
    project->set_scene(scene);

    // Return the newly created project.
    return project;
}