Exemplo n.º 1
0
void AssemblyTree::rebuild_assembly_tree()
{
    // Clear the current tree.
    clear();
    m_assembly_instances.clear();

    Statistics statistics;

    // Collect all assembly instances of the scene.
    AABBVector assembly_instance_bboxes;
    collect_assembly_instances(assembly_instance_bboxes);

    RENDERER_LOG_INFO(
        "building assembly tree (%s %s)...",
        pretty_int(m_assembly_instances.size()).c_str(),
        plural(m_assembly_instances.size(), "assembly instance").c_str());

    // Create the partitioner.
    typedef bvh::SAHPartitioner<AABBVector> Partitioner;
    Partitioner partitioner(
        assembly_instance_bboxes,
        AssemblyTreeMaxLeafSize,
        AssemblyTreeInteriorNodeTraversalCost,
        AssemblyTreeTriangleIntersectionCost);

    // Build the assembly tree.
    typedef bvh::Builder<AssemblyTree, Partitioner> Builder;
    Builder builder;
    builder.build<DefaultWallclockTimer>(*this, partitioner, m_assembly_instances.size(), AssemblyTreeMaxLeafSize);
    statistics.insert_time("build time", builder.get_build_time());
    statistics.merge(bvh::TreeStatistics<AssemblyTree>(*this, AABB3d(m_scene.compute_bbox())));

    if (!m_assembly_instances.empty())
    {
        const vector<size_t>& ordering = partitioner.get_item_ordering();
        assert(m_assembly_instances.size() == ordering.size());

        // Reorder the assembly instances according to the tree ordering.
        vector<const AssemblyInstance*> temp_assembly_instances(ordering.size());
        small_item_reorder(
            &m_assembly_instances[0],
            &temp_assembly_instances[0],
            &ordering[0],
            ordering.size());

        // Store assembly instances in the tree leaves whenever possible.
        store_assembly_instances_in_leaves(statistics);
    }

    // Print assembly tree statistics.
    RENDERER_LOG_DEBUG("%s",
        StatisticsVector::make(
            "assembly tree statistics",
            statistics).to_string().c_str());
}
Exemplo n.º 2
0
    // Partition a set of items into two distinct sets.
    // Return end if the set is not to be partitioned.
    size_t partition(
        vector<UniqueID>&   items,
        vector<GAABB3>&     bboxes,
        const size_t        begin,
        const size_t        end,
        const GAABB3&       bbox)
    {
        const size_t count = end - begin;
        assert(count > 1);

        // Ensure that sufficient memory is allocated for the working arrays.
        ensure_size(m_indices, count);
        ensure_size(m_left_bboxes, count);
        ensure_size(m_temp_items, count);
        ensure_size(m_temp_bboxes, count);

        // Create the set of indices.
        for (size_t i = 0; i < count; ++i)
            m_indices[i] = i;

        GScalar best_split_cost = numeric_limits<GScalar>::max();
        size_t best_split_dim = 0;
        size_t best_split_pivot = 0;
        GAABB3 group_bbox;

        for (size_t dim = 0; dim < 3; ++dim)
        {
            // Sort the items according to their bounding boxes.
            BboxSortPredicate predicate(bboxes, begin, dim);
            sort(&m_indices[0], &m_indices[0] + count, predicate);

            // Left-to-right sweep to accumulate bounding boxes.
            group_bbox.invalidate();
            for (size_t i = 0; i < count; ++i)
            {
                group_bbox.insert(bboxes[begin + m_indices[i]]);
                m_left_bboxes[i] = group_bbox;
            }

            // Right-to-left sweep to accumulate bounding boxes and evaluate SAH.
            group_bbox.invalidate();
            for (size_t i = count - 1; i > 0; --i)
            {
                // Get left and right bounding boxes.
                const GAABB3& left_bbox = m_left_bboxes[i - 1];
                group_bbox.insert(bboxes[begin + m_indices[i]]);

                // Compute the cost of this partition.
                const GScalar left_cost = left_bbox.half_surface_area() * i;
                const GScalar right_cost = group_bbox.half_surface_area() * (count - i);
                const GScalar split_cost = left_cost + right_cost;

                // Keep track of the partition with the lowest cost.
                if (best_split_cost > split_cost)
                {
                    best_split_cost = split_cost;
                    best_split_dim = dim;
                    best_split_pivot = i;
                }
            }
        }

        // Just split in half if the cost of the best partition is too high.
        const GScalar leaf_cost = bbox.half_surface_area() * count;
        if (best_split_cost >= leaf_cost)
            return (begin + end) / 2;

        // Sort the indices according to the item bounding boxes.
        BboxSortPredicate predicate(bboxes, begin, best_split_dim);
        sort(&m_indices[0], &m_indices[0] + count, predicate);

        // Reorder the items.
        small_item_reorder(&items[begin], &m_temp_items[0], &m_indices[0], count);
        small_item_reorder(&bboxes[begin], &m_temp_bboxes[0], &m_indices[0], count);

        assert(begin + best_split_pivot < end);
        return begin + best_split_pivot;
    }
Exemplo n.º 3
0
void CurveTree::reorder_curve_keys(const vector<size_t>& ordering)
{
    vector<CurveKey> temp_keys(m_curve_keys.size());
    small_item_reorder(&m_curve_keys[0], &temp_keys[0], &ordering[0], ordering.size());
}