diff --git a/intern/cycles/scene/light.cpp b/intern/cycles/scene/light.cpp index 5ecf55d2442..0c6c84fae22 100644 --- a/intern/cycles/scene/light.cpp +++ b/intern/cycles/scene/light.cpp @@ -501,7 +501,7 @@ void LightManager::device_update_tree(Device *, if (node != reference) { /* Flatten the node with the subtree first so the subsequent instances know the index. */ std::swap(node->type, reference->type); - std::swap(node->inner.children, reference->inner.children); + std::swap(node->params, reference->params); } node->type &= ~LIGHT_TREE_INSTANCE; processed_mesh[reference] = node_index; @@ -524,16 +524,16 @@ void LightManager::device_update_tree(Device *, light_tree_nodes[node_index].num_emitters = -1; /* Fill in the stacks. */ left_indices.push(node_index); - right_nodes.push(node->inner.children[LightTree::right].get()); - node = node->inner.children[LightTree::left].get(); + right_nodes.push(node->get_inner().children[LightTree::right].get()); + node = node->get_inner().children[LightTree::left].get(); continue; } if (node->is_leaf() || node->is_distant()) { - light_tree_nodes[node_index].num_emitters = node->leaf.num_emitters; - light_tree_nodes[node_index].leaf.first_emitter = node->leaf.first_emitter_index; + light_tree_nodes[node_index].num_emitters = node->get_leaf().num_emitters; + light_tree_nodes[node_index].leaf.first_emitter = node->get_leaf().first_emitter_index; - for (int i = 0; i < node->leaf.num_emitters; i++) { - int emitter_index = i + node->leaf.first_emitter_index; + for (int i = 0; i < node->get_leaf().num_emitters; i++) { + int emitter_index = i + node->get_leaf().first_emitter_index; const LightTreeEmitter &emitter = light_tree.get_emitter(emitter_index); light_tree_emitters[emitter_index].energy = emitter.measure.energy; diff --git a/intern/cycles/scene/light_tree.cpp b/intern/cycles/scene/light_tree.cpp index e12512faeb7..385410d7e7a 100644 --- a/intern/cycles/scene/light_tree.cpp +++ b/intern/cycles/scene/light_tree.cpp @@ -385,11 +385,11 @@ LightTreeNode *LightTree::build(Scene *scene, DeviceScene *dscene) task_pool.wait_work(); /* All distant lights are grouped to the right child as a leaf node. */ - root_->inner.children[right] = create_node(LightTreeMeasure::empty, 1); + root_->get_inner().children[right] = create_node(LightTreeMeasure::empty, 1); for (int i = 0; i < num_distant_lights; i++) { - root_->inner.children[right]->add(distant_lights_[i]); + root_->get_inner().children[right]->add(distant_lights_[i]); } - root_->inner.children[right]->make_distant(num_local_lights, num_distant_lights); + root_->get_inner().children[right]->make_distant(num_local_lights, num_distant_lights); std::move(distant_lights_.begin(), distant_lights_.end(), std::back_inserter(emitters_)); return root_.get(); @@ -413,8 +413,8 @@ void LightTree::recursive_build(const Child child, node = inner; } else { - inner->inner.children[child] = create_node(LightTreeMeasure::empty, bit_trail); - node = inner->inner.children[child].get(); + inner->get_inner().children[child] = create_node(LightTreeMeasure::empty, bit_trail); + node = inner->get_inner().children[child].get(); } /* Find the best place to split the emitters into 2 nodes. diff --git a/intern/cycles/scene/light_tree.h b/intern/cycles/scene/light_tree.h index 5c3ec61ba1b..7f753b8ce08 100644 --- a/intern/cycles/scene/light_tree.h +++ b/intern/cycles/scene/light_tree.h @@ -7,6 +7,8 @@ #include "scene/light.h" #include "scene/scene.h" +#include + #include "util/boundbox.h" #include "util/task.h" #include "util/types.h" @@ -193,58 +195,73 @@ struct LightTreeNode { * leaf or an inner node. */ int type = LIGHT_TREE_INNER; - union { - struct { - int num_emitters; /* The number of emitters a leaf node stores. */ - int first_emitter_index; /* Index to first emitter. */ - } leaf; - - struct { - /* Inner node has two children. */ - unique_ptr children[2] = {nullptr, nullptr}; - } inner; - - struct { - /* A reference to the root node of the subtree. */ - LightTreeNode *reference; - } instance; + struct Leaf { + int num_emitters = -1; /* The number of emitters a leaf node stores. */ + int first_emitter_index = -1; /* Index to first emitter. */ }; - ~LightTreeNode() - { - if (is_inner()) { - inner.children[0] = nullptr; - inner.children[1] = nullptr; - } - } + struct Inner { + /* Inner node has two children. */ + unique_ptr children[2]; + }; + + struct Instance { + LightTreeNode *reference = nullptr; + }; + + std::variant params; LightTreeNode(const LightTreeMeasure &measure, const uint &bit_trial) - : measure(measure), bit_trail(bit_trial) + : measure(measure), bit_trail(bit_trial), params(Inner()) { } + ~LightTreeNode() = default; + __forceinline void add(const LightTreeEmitter &emitter) { measure.add(emitter.measure); } + inline Leaf &get_leaf() + { + return std::get(params); + } + inline Inner &get_inner() + { + return std::get(params); + } + inline Instance &get_instance() + { + return std::get(params); + } + void make_leaf(const int &first_emitter_index, const int &num_emitters) { - this->leaf.first_emitter_index = first_emitter_index; - this->leaf.num_emitters = num_emitters; + params = Leaf(); + Leaf &leaf = get_leaf(); + + leaf.first_emitter_index = first_emitter_index; + leaf.num_emitters = num_emitters; type = LIGHT_TREE_LEAF; } void make_distant(const int &first_emitter_index, const int &num_emitters) { - this->leaf.first_emitter_index = first_emitter_index; - this->leaf.num_emitters = num_emitters; + params = Leaf(); + Leaf &leaf = get_leaf(); + + leaf.first_emitter_index = first_emitter_index; + leaf.num_emitters = num_emitters; type = LIGHT_TREE_DISTANT; } void make_instance(LightTreeNode *reference, const int &object_id) { - this->instance.reference = reference; + params = Instance(); + Instance &instance = get_instance(); + + instance.reference = reference; this->object_id = object_id; type = LIGHT_TREE_INSTANCE; } @@ -253,7 +270,7 @@ struct LightTreeNode { { assert(is_instance()); if (type == LIGHT_TREE_INSTANCE) { - return instance.reference; + return get_instance().reference; } return this; }