diff options
Diffstat (limited to 'intern/cycles/bvh/bvh8.cpp')
-rw-r--r-- | intern/cycles/bvh/bvh8.cpp | 852 |
1 files changed, 415 insertions, 437 deletions
diff --git a/intern/cycles/bvh/bvh8.cpp b/intern/cycles/bvh/bvh8.cpp index af930b2f2df..e812d806b94 100644 --- a/intern/cycles/bvh/bvh8.cpp +++ b/intern/cycles/bvh/bvh8.cpp @@ -36,8 +36,7 @@ CCL_NAMESPACE_BEGIN -BVH8::BVH8(const BVHParams& params_, const vector<Object*>& objects_) -: BVH(params_, objects_) +BVH8::BVH8(const BVHParams ¶ms_, const vector<Object *> &objects_) : BVH(params_, objects_) { } @@ -45,159 +44,148 @@ namespace { BVHNode *bvh_node_merge_children_recursively(const BVHNode *node) { - if(node->is_leaf()) { - return new LeafNode(*reinterpret_cast<const LeafNode *>(node)); - } - /* Collect nodes of two layer deeper, allowing us to have more childrem in - * an inner layer. */ - assert(node->num_children() <= 2); - const BVHNode *children[8]; - const BVHNode *child0 = node->get_child(0); - const BVHNode *child1 = node->get_child(1); - int num_children = 0; - if(child0->is_leaf()) { - children[num_children++] = child0; - } - else { - const BVHNode *child00 = child0->get_child(0), - *child01 = child0->get_child(1); - if(child00->is_leaf()) { - children[num_children++] = child00; - } - else { - children[num_children++] = child00->get_child(0); - children[num_children++] = child00->get_child(1); - } - if(child01->is_leaf()) { - children[num_children++] = child01; - } - else { - children[num_children++] = child01->get_child(0); - children[num_children++] = child01->get_child(1); - } - } - if(child1->is_leaf()) { - children[num_children++] = child1; - } - else { - const BVHNode *child10 = child1->get_child(0), - *child11 = child1->get_child(1); - if(child10->is_leaf()) { - children[num_children++] = child10; - } - else { - children[num_children++] = child10->get_child(0); - children[num_children++] = child10->get_child(1); - } - if(child11->is_leaf()) { - children[num_children++] = child11; - } - else { - children[num_children++] = child11->get_child(0); - children[num_children++] = child11->get_child(1); - } - } - /* Merge children in subtrees. */ - BVHNode *children4[8]; - for(int i = 0; i < num_children; ++i) { - children4[i] = bvh_node_merge_children_recursively(children[i]); - } - /* Allocate new node. */ - BVHNode *node8 = new InnerNode(node->bounds, children4, num_children); - /* TODO(sergey): Consider doing this from the InnerNode() constructor. - * But in order to do this nicely need to think of how to pass all the - * parameters there. */ - if(node->is_unaligned) { - node8->is_unaligned = true; - node8->aligned_space = new Transform(); - *node8->aligned_space = *node->aligned_space; - } - return node8; + if (node->is_leaf()) { + return new LeafNode(*reinterpret_cast<const LeafNode *>(node)); + } + /* Collect nodes of two layer deeper, allowing us to have more childrem in + * an inner layer. */ + assert(node->num_children() <= 2); + const BVHNode *children[8]; + const BVHNode *child0 = node->get_child(0); + const BVHNode *child1 = node->get_child(1); + int num_children = 0; + if (child0->is_leaf()) { + children[num_children++] = child0; + } + else { + const BVHNode *child00 = child0->get_child(0), *child01 = child0->get_child(1); + if (child00->is_leaf()) { + children[num_children++] = child00; + } + else { + children[num_children++] = child00->get_child(0); + children[num_children++] = child00->get_child(1); + } + if (child01->is_leaf()) { + children[num_children++] = child01; + } + else { + children[num_children++] = child01->get_child(0); + children[num_children++] = child01->get_child(1); + } + } + if (child1->is_leaf()) { + children[num_children++] = child1; + } + else { + const BVHNode *child10 = child1->get_child(0), *child11 = child1->get_child(1); + if (child10->is_leaf()) { + children[num_children++] = child10; + } + else { + children[num_children++] = child10->get_child(0); + children[num_children++] = child10->get_child(1); + } + if (child11->is_leaf()) { + children[num_children++] = child11; + } + else { + children[num_children++] = child11->get_child(0); + children[num_children++] = child11->get_child(1); + } + } + /* Merge children in subtrees. */ + BVHNode *children4[8]; + for (int i = 0; i < num_children; ++i) { + children4[i] = bvh_node_merge_children_recursively(children[i]); + } + /* Allocate new node. */ + BVHNode *node8 = new InnerNode(node->bounds, children4, num_children); + /* TODO(sergey): Consider doing this from the InnerNode() constructor. + * But in order to do this nicely need to think of how to pass all the + * parameters there. */ + if (node->is_unaligned) { + node8->is_unaligned = true; + node8->aligned_space = new Transform(); + *node8->aligned_space = *node->aligned_space; + } + return node8; } } // namespace BVHNode *BVH8::widen_children_nodes(const BVHNode *root) { - if(root == NULL) { - return NULL; - } - if(root->is_leaf()) { - return const_cast<BVHNode *>(root); - } - BVHNode *root8 = bvh_node_merge_children_recursively(root); - /* TODO(sergey): Pack children nodes to parents which has less that 4 - * children. */ - return root8; + if (root == NULL) { + return NULL; + } + if (root->is_leaf()) { + return const_cast<BVHNode *>(root); + } + BVHNode *root8 = bvh_node_merge_children_recursively(root); + /* TODO(sergey): Pack children nodes to parents which has less that 4 + * children. */ + return root8; } -void BVH8::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf) +void BVH8::pack_leaf(const BVHStackEntry &e, const LeafNode *leaf) { - float4 data[BVH_ONODE_LEAF_SIZE]; - memset(data, 0, sizeof(data)); - if(leaf->num_triangles() == 1 && pack.prim_index[leaf->lo] == -1) { - /* object */ - data[0].x = __int_as_float(~(leaf->lo)); - data[0].y = __int_as_float(0); - } - else { - /* triangle */ - data[0].x = __int_as_float(leaf->lo); - data[0].y = __int_as_float(leaf->hi); - } - data[0].z = __uint_as_float(leaf->visibility); - if(leaf->num_triangles() != 0) { - data[0].w = __uint_as_float(pack.prim_type[leaf->lo]); - } - - memcpy(&pack.leaf_nodes[e.idx], data, sizeof(float4)*BVH_ONODE_LEAF_SIZE); + float4 data[BVH_ONODE_LEAF_SIZE]; + memset(data, 0, sizeof(data)); + if (leaf->num_triangles() == 1 && pack.prim_index[leaf->lo] == -1) { + /* object */ + data[0].x = __int_as_float(~(leaf->lo)); + data[0].y = __int_as_float(0); + } + else { + /* triangle */ + data[0].x = __int_as_float(leaf->lo); + data[0].y = __int_as_float(leaf->hi); + } + data[0].z = __uint_as_float(leaf->visibility); + if (leaf->num_triangles() != 0) { + data[0].w = __uint_as_float(pack.prim_type[leaf->lo]); + } + + memcpy(&pack.leaf_nodes[e.idx], data, sizeof(float4) * BVH_ONODE_LEAF_SIZE); } -void BVH8::pack_inner(const BVHStackEntry& e, - const BVHStackEntry *en, - int num) +void BVH8::pack_inner(const BVHStackEntry &e, const BVHStackEntry *en, int num) { - bool has_unaligned = false; - /* Check whether we have to create unaligned node or all nodes are aligned - * and we can cut some corner here. - */ - if(params.use_unaligned_nodes) { - for(int i = 0; i < num; i++) { - if(en[i].node->is_unaligned) { - has_unaligned = true; - break; - } - } - } - if(has_unaligned) { - /* There's no unaligned children, pack into AABB node. */ - pack_unaligned_inner(e, en, num); - } - else { - /* Create unaligned node with orientation transform for each of the - * children. - */ - pack_aligned_inner(e, en, num); - } + bool has_unaligned = false; + /* Check whether we have to create unaligned node or all nodes are aligned + * and we can cut some corner here. + */ + if (params.use_unaligned_nodes) { + for (int i = 0; i < num; i++) { + if (en[i].node->is_unaligned) { + has_unaligned = true; + break; + } + } + } + if (has_unaligned) { + /* There's no unaligned children, pack into AABB node. */ + pack_unaligned_inner(e, en, num); + } + else { + /* Create unaligned node with orientation transform for each of the + * children. + */ + pack_aligned_inner(e, en, num); + } } -void BVH8::pack_aligned_inner(const BVHStackEntry& e, - const BVHStackEntry *en, - int num) +void BVH8::pack_aligned_inner(const BVHStackEntry &e, const BVHStackEntry *en, int num) { - BoundBox bounds[8]; - int child[8]; - for(int i = 0; i < num; ++i) { - bounds[i] = en[i].node->bounds; - child[i] = en[i].encodeIdx(); - } - pack_aligned_node(e.idx, - bounds, - child, - e.node->visibility, - e.node->time_from, - e.node->time_to, - num); + BoundBox bounds[8]; + int child[8]; + for (int i = 0; i < num; ++i) { + bounds[i] = en[i].node->bounds; + child[i] = en[i].encodeIdx(); + } + pack_aligned_node( + e.idx, bounds, child, e.node->visibility, e.node->time_from, e.node->time_to, num); } void BVH8::pack_aligned_node(int idx, @@ -208,66 +196,64 @@ void BVH8::pack_aligned_node(int idx, const float time_to, const int num) { - float8 data[8]; - memset(data, 0, sizeof(data)); + float8 data[8]; + memset(data, 0, sizeof(data)); - data[0].a = __uint_as_float(visibility & ~PATH_RAY_NODE_UNALIGNED); - data[0].b = time_from; - data[0].c = time_to; + data[0].a = __uint_as_float(visibility & ~PATH_RAY_NODE_UNALIGNED); + data[0].b = time_from; + data[0].c = time_to; - for(int i = 0; i < num; i++) { - float3 bb_min = bounds[i].min; - float3 bb_max = bounds[i].max; + for (int i = 0; i < num; i++) { + float3 bb_min = bounds[i].min; + float3 bb_max = bounds[i].max; - data[1][i] = bb_min.x; - data[2][i] = bb_max.x; - data[3][i] = bb_min.y; - data[4][i] = bb_max.y; - data[5][i] = bb_min.z; - data[6][i] = bb_max.z; + data[1][i] = bb_min.x; + data[2][i] = bb_max.x; + data[3][i] = bb_min.y; + data[4][i] = bb_max.y; + data[5][i] = bb_min.z; + data[6][i] = bb_max.z; - data[7][i] = __int_as_float(child[i]); - } + data[7][i] = __int_as_float(child[i]); + } - for(int i = num; i < 8; i++) { - /* We store BB which would never be recorded as intersection - * so kernel might safely assume there are always 4 child nodes. - */ - data[1][i] = FLT_MAX; - data[2][i] = -FLT_MAX; + for (int i = num; i < 8; i++) { + /* We store BB which would never be recorded as intersection + * so kernel might safely assume there are always 4 child nodes. + */ + data[1][i] = FLT_MAX; + data[2][i] = -FLT_MAX; - data[3][i] = FLT_MAX; - data[4][i] = -FLT_MAX; + data[3][i] = FLT_MAX; + data[4][i] = -FLT_MAX; - data[5][i] = FLT_MAX; - data[6][i] = -FLT_MAX; + data[5][i] = FLT_MAX; + data[6][i] = -FLT_MAX; - data[7][i] = __int_as_float(0); - } + data[7][i] = __int_as_float(0); + } - memcpy(&pack.nodes[idx], data, sizeof(float4)*BVH_ONODE_SIZE); + memcpy(&pack.nodes[idx], data, sizeof(float4) * BVH_ONODE_SIZE); } -void BVH8::pack_unaligned_inner(const BVHStackEntry& e, - const BVHStackEntry *en, - int num) +void BVH8::pack_unaligned_inner(const BVHStackEntry &e, const BVHStackEntry *en, int num) { - Transform aligned_space[8]; - BoundBox bounds[8]; - int child[8]; - for(int i = 0; i < num; ++i) { - aligned_space[i] = en[i].node->get_aligned_space(); - bounds[i] = en[i].node->bounds; - child[i] = en[i].encodeIdx(); - } - pack_unaligned_node(e.idx, - aligned_space, - bounds, - child, - e.node->visibility, - e.node->time_from, - e.node->time_to, - num); + Transform aligned_space[8]; + BoundBox bounds[8]; + int child[8]; + for (int i = 0; i < num; ++i) { + aligned_space[i] = en[i].node->get_aligned_space(); + bounds[i] = en[i].node->bounds; + child[i] = en[i].encodeIdx(); + } + pack_unaligned_node(e.idx, + aligned_space, + bounds, + child, + e.node->visibility, + e.node->time_from, + e.node->time_to, + num); } void BVH8::pack_unaligned_node(int idx, @@ -279,283 +265,275 @@ void BVH8::pack_unaligned_node(int idx, const float time_to, const int num) { - float8 data[BVH_UNALIGNED_ONODE_SIZE]; - memset(data, 0, sizeof(data)); + float8 data[BVH_UNALIGNED_ONODE_SIZE]; + memset(data, 0, sizeof(data)); - data[0].a = __uint_as_float(visibility | PATH_RAY_NODE_UNALIGNED); - data[0].b = time_from; - data[0].c = time_to; + data[0].a = __uint_as_float(visibility | PATH_RAY_NODE_UNALIGNED); + data[0].b = time_from; + data[0].c = time_to; - for(int i = 0; i < num; i++) { - Transform space = BVHUnaligned::compute_node_transform( - bounds[i], - aligned_space[i]); + for (int i = 0; i < num; i++) { + Transform space = BVHUnaligned::compute_node_transform(bounds[i], aligned_space[i]); - data[1][i] = space.x.x; - data[2][i] = space.x.y; - data[3][i] = space.x.z; + data[1][i] = space.x.x; + data[2][i] = space.x.y; + data[3][i] = space.x.z; - data[4][i] = space.y.x; - data[5][i] = space.y.y; - data[6][i] = space.y.z; + data[4][i] = space.y.x; + data[5][i] = space.y.y; + data[6][i] = space.y.z; - data[7][i] = space.z.x; - data[8][i] = space.z.y; - data[9][i] = space.z.z; + data[7][i] = space.z.x; + data[8][i] = space.z.y; + data[9][i] = space.z.z; - data[10][i] = space.x.w; - data[11][i] = space.y.w; - data[12][i] = space.z.w; + data[10][i] = space.x.w; + data[11][i] = space.y.w; + data[12][i] = space.z.w; - data[13][i] = __int_as_float(child[i]); - } + data[13][i] = __int_as_float(child[i]); + } - for(int i = num; i < 8; i++) { - /* We store BB which would never be recorded as intersection - * so kernel might safely assume there are always 4 child nodes. - */ + for (int i = num; i < 8; i++) { + /* We store BB which would never be recorded as intersection + * so kernel might safely assume there are always 4 child nodes. + */ - data[1][i] = NAN; - data[2][i] = NAN; - data[3][i] = NAN; + data[1][i] = NAN; + data[2][i] = NAN; + data[3][i] = NAN; - data[4][i] = NAN; - data[5][i] = NAN; - data[6][i] = NAN; + data[4][i] = NAN; + data[5][i] = NAN; + data[6][i] = NAN; - data[7][i] = NAN; - data[8][i] = NAN; - data[9][i] = NAN; + data[7][i] = NAN; + data[8][i] = NAN; + data[9][i] = NAN; - data[10][i] = NAN; - data[11][i] = NAN; - data[12][i] = NAN; + data[10][i] = NAN; + data[11][i] = NAN; + data[12][i] = NAN; - data[13][i] = __int_as_float(0); - } + data[13][i] = __int_as_float(0); + } - memcpy(&pack.nodes[idx], data, sizeof(float4)*BVH_UNALIGNED_ONODE_SIZE); + memcpy(&pack.nodes[idx], data, sizeof(float4) * BVH_UNALIGNED_ONODE_SIZE); } /* Quad SIMD Nodes */ void BVH8::pack_nodes(const BVHNode *root) { - /* Calculate size of the arrays required. */ - const size_t num_nodes = root->getSubtreeSize(BVH_STAT_NODE_COUNT); - const size_t num_leaf_nodes = root->getSubtreeSize(BVH_STAT_LEAF_COUNT); - assert(num_leaf_nodes <= num_nodes); - const size_t num_inner_nodes = num_nodes - num_leaf_nodes; - size_t node_size; - if(params.use_unaligned_nodes) { - const size_t num_unaligned_nodes = - root->getSubtreeSize(BVH_STAT_UNALIGNED_INNER_COUNT); - node_size = (num_unaligned_nodes * BVH_UNALIGNED_ONODE_SIZE) + - (num_inner_nodes - num_unaligned_nodes) * BVH_ONODE_SIZE; - } - else { - node_size = num_inner_nodes * BVH_ONODE_SIZE; - } - /* Resize arrays. */ - pack.nodes.clear(); - pack.leaf_nodes.clear(); - /* For top level BVH, first merge existing BVH's so we know the offsets. */ - if(params.top_level) { - pack_instances(node_size, num_leaf_nodes*BVH_ONODE_LEAF_SIZE); - } - else { - pack.nodes.resize(node_size); - pack.leaf_nodes.resize(num_leaf_nodes*BVH_ONODE_LEAF_SIZE); - } - - int nextNodeIdx = 0, nextLeafNodeIdx = 0; - - vector<BVHStackEntry> stack; - stack.reserve(BVHParams::MAX_DEPTH*2); - if(root->is_leaf()) { - stack.push_back(BVHStackEntry(root, nextLeafNodeIdx++)); - } - else { - stack.push_back(BVHStackEntry(root, nextNodeIdx)); - nextNodeIdx += root->has_unaligned() ? BVH_UNALIGNED_ONODE_SIZE - : BVH_ONODE_SIZE; - } - - while(stack.size()) { - BVHStackEntry e = stack.back(); - stack.pop_back(); - - if(e.node->is_leaf()) { - /* leaf node */ - const LeafNode *leaf = reinterpret_cast<const LeafNode*>(e.node); - pack_leaf(e, leaf); - } - else { - /* Inner node. */ - /* Collect nodes. */ - const BVHNode *children[8]; - int num_children = e.node->num_children(); - /* Push entries on the stack. */ - for(int i = 0; i < num_children; ++i) { - int idx; - children[i] = e.node->get_child(i); - if(children[i]->is_leaf()) { - idx = nextLeafNodeIdx++; - } - else { - idx = nextNodeIdx; - nextNodeIdx += children[i]->has_unaligned() - ? BVH_UNALIGNED_ONODE_SIZE - : BVH_ONODE_SIZE; - } - stack.push_back(BVHStackEntry(children[i], idx)); - } - /* Set node. */ - pack_inner(e, &stack[stack.size() - num_children], num_children); - } - } - - assert(node_size == nextNodeIdx); - /* Root index to start traversal at, to handle case of single leaf node. */ - pack.root_index = (root->is_leaf()) ? -1 : 0; + /* Calculate size of the arrays required. */ + const size_t num_nodes = root->getSubtreeSize(BVH_STAT_NODE_COUNT); + const size_t num_leaf_nodes = root->getSubtreeSize(BVH_STAT_LEAF_COUNT); + assert(num_leaf_nodes <= num_nodes); + const size_t num_inner_nodes = num_nodes - num_leaf_nodes; + size_t node_size; + if (params.use_unaligned_nodes) { + const size_t num_unaligned_nodes = root->getSubtreeSize(BVH_STAT_UNALIGNED_INNER_COUNT); + node_size = (num_unaligned_nodes * BVH_UNALIGNED_ONODE_SIZE) + + (num_inner_nodes - num_unaligned_nodes) * BVH_ONODE_SIZE; + } + else { + node_size = num_inner_nodes * BVH_ONODE_SIZE; + } + /* Resize arrays. */ + pack.nodes.clear(); + pack.leaf_nodes.clear(); + /* For top level BVH, first merge existing BVH's so we know the offsets. */ + if (params.top_level) { + pack_instances(node_size, num_leaf_nodes * BVH_ONODE_LEAF_SIZE); + } + else { + pack.nodes.resize(node_size); + pack.leaf_nodes.resize(num_leaf_nodes * BVH_ONODE_LEAF_SIZE); + } + + int nextNodeIdx = 0, nextLeafNodeIdx = 0; + + vector<BVHStackEntry> stack; + stack.reserve(BVHParams::MAX_DEPTH * 2); + if (root->is_leaf()) { + stack.push_back(BVHStackEntry(root, nextLeafNodeIdx++)); + } + else { + stack.push_back(BVHStackEntry(root, nextNodeIdx)); + nextNodeIdx += root->has_unaligned() ? BVH_UNALIGNED_ONODE_SIZE : BVH_ONODE_SIZE; + } + + while (stack.size()) { + BVHStackEntry e = stack.back(); + stack.pop_back(); + + if (e.node->is_leaf()) { + /* leaf node */ + const LeafNode *leaf = reinterpret_cast<const LeafNode *>(e.node); + pack_leaf(e, leaf); + } + else { + /* Inner node. */ + /* Collect nodes. */ + const BVHNode *children[8]; + int num_children = e.node->num_children(); + /* Push entries on the stack. */ + for (int i = 0; i < num_children; ++i) { + int idx; + children[i] = e.node->get_child(i); + if (children[i]->is_leaf()) { + idx = nextLeafNodeIdx++; + } + else { + idx = nextNodeIdx; + nextNodeIdx += children[i]->has_unaligned() ? BVH_UNALIGNED_ONODE_SIZE : BVH_ONODE_SIZE; + } + stack.push_back(BVHStackEntry(children[i], idx)); + } + /* Set node. */ + pack_inner(e, &stack[stack.size() - num_children], num_children); + } + } + + assert(node_size == nextNodeIdx); + /* Root index to start traversal at, to handle case of single leaf node. */ + pack.root_index = (root->is_leaf()) ? -1 : 0; } void BVH8::refit_nodes() { - assert(!params.top_level); + assert(!params.top_level); - BoundBox bbox = BoundBox::empty; - uint visibility = 0; - refit_node(0, (pack.root_index == -1)? true: false, bbox, visibility); + BoundBox bbox = BoundBox::empty; + uint visibility = 0; + refit_node(0, (pack.root_index == -1) ? true : false, bbox, visibility); } -void BVH8::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility) +void BVH8::refit_node(int idx, bool leaf, BoundBox &bbox, uint &visibility) { - if(leaf) { - int4 *data = &pack.leaf_nodes[idx]; - int4 c = data[0]; - /* Refit leaf node. */ - for(int prim = c.x; prim < c.y; prim++) { - int pidx = pack.prim_index[prim]; - int tob = pack.prim_object[prim]; - Object *ob = objects[tob]; - - if(pidx == -1) { - /* Object instance. */ - bbox.grow(ob->bounds); - } - else { - /* Primitives. */ - const Mesh *mesh = ob->mesh; - - if(pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) { - /* Curves. */ - int str_offset = (params.top_level) ? mesh->curve_offset : 0; - Mesh::Curve curve = mesh->get_curve(pidx - str_offset); - int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]); - - curve.bounds_grow(k, &mesh->curve_keys[0], &mesh->curve_radius[0], bbox); - - visibility |= PATH_RAY_CURVE; - - /* Motion curves. */ - if(mesh->use_motion_blur) { - Attribute *attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); - - if(attr) { - size_t mesh_size = mesh->curve_keys.size(); - size_t steps = mesh->motion_steps - 1; - float3 *key_steps = attr->data_float3(); - - for(size_t i = 0; i < steps; i++) { - curve.bounds_grow(k, key_steps + i*mesh_size, &mesh->curve_radius[0], bbox); - } - } - } - } - else { - /* Triangles. */ - int tri_offset = (params.top_level) ? mesh->tri_offset : 0; - Mesh::Triangle triangle = mesh->get_triangle(pidx - tri_offset); - const float3 *vpos = &mesh->verts[0]; - - triangle.bounds_grow(vpos, bbox); - - /* Motion triangles. */ - if(mesh->use_motion_blur) { - Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); - - if(attr) { - size_t mesh_size = mesh->verts.size(); - size_t steps = mesh->motion_steps - 1; - float3 *vert_steps = attr->data_float3(); - - for(size_t i = 0; i < steps; i++) { - triangle.bounds_grow(vert_steps + i*mesh_size, bbox); - } - } - } - } - } - - visibility |= ob->visibility; - } - - float4 leaf_data[BVH_ONODE_LEAF_SIZE]; - leaf_data[0].x = __int_as_float(c.x); - leaf_data[0].y = __int_as_float(c.y); - leaf_data[0].z = __uint_as_float(visibility); - leaf_data[0].w = __uint_as_float(c.w); - memcpy(&pack.leaf_nodes[idx], leaf_data, sizeof(float4)*BVH_ONODE_LEAF_SIZE); - } - else { - float8 *data = (float8*)&pack.nodes[idx]; - bool is_unaligned = (__float_as_uint(data[0].a) & PATH_RAY_NODE_UNALIGNED) != 0; - /* Refit inner node, set bbox from children. */ - BoundBox child_bbox[8] = { BoundBox::empty, BoundBox::empty, - BoundBox::empty, BoundBox::empty, - BoundBox::empty, BoundBox::empty, - BoundBox::empty, BoundBox::empty }; - int child[8]; - uint child_visibility[8] = { 0 }; - int num_nodes = 0; - - for(int i = 0; i < 8; ++i) { - child[i] = __float_as_int(data[(is_unaligned) ? 13: 7][i]); - - if(child[i] != 0) { - refit_node((child[i] < 0)? -child[i]-1: child[i], (child[i] < 0), - child_bbox[i], child_visibility[i]); - ++num_nodes; - bbox.grow(child_bbox[i]); - visibility |= child_visibility[i]; - } - } - - if(is_unaligned) { - Transform aligned_space[8] = { transform_identity(), transform_identity(), - transform_identity(), transform_identity(), - transform_identity(), transform_identity(), - transform_identity(), transform_identity()}; - pack_unaligned_node(idx, - aligned_space, - child_bbox, - child, - visibility, - 0.0f, - 1.0f, - num_nodes); - } - else { - pack_aligned_node(idx, - child_bbox, - child, - visibility, - 0.0f, - 1.0f, - num_nodes); - } - } + if (leaf) { + int4 *data = &pack.leaf_nodes[idx]; + int4 c = data[0]; + /* Refit leaf node. */ + for (int prim = c.x; prim < c.y; prim++) { + int pidx = pack.prim_index[prim]; + int tob = pack.prim_object[prim]; + Object *ob = objects[tob]; + + if (pidx == -1) { + /* Object instance. */ + bbox.grow(ob->bounds); + } + else { + /* Primitives. */ + const Mesh *mesh = ob->mesh; + + if (pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) { + /* Curves. */ + int str_offset = (params.top_level) ? mesh->curve_offset : 0; + Mesh::Curve curve = mesh->get_curve(pidx - str_offset); + int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]); + + curve.bounds_grow(k, &mesh->curve_keys[0], &mesh->curve_radius[0], bbox); + + visibility |= PATH_RAY_CURVE; + + /* Motion curves. */ + if (mesh->use_motion_blur) { + Attribute *attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + + if (attr) { + size_t mesh_size = mesh->curve_keys.size(); + size_t steps = mesh->motion_steps - 1; + float3 *key_steps = attr->data_float3(); + + for (size_t i = 0; i < steps; i++) { + curve.bounds_grow(k, key_steps + i * mesh_size, &mesh->curve_radius[0], bbox); + } + } + } + } + else { + /* Triangles. */ + int tri_offset = (params.top_level) ? mesh->tri_offset : 0; + Mesh::Triangle triangle = mesh->get_triangle(pidx - tri_offset); + const float3 *vpos = &mesh->verts[0]; + + triangle.bounds_grow(vpos, bbox); + + /* Motion triangles. */ + if (mesh->use_motion_blur) { + Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + + if (attr) { + size_t mesh_size = mesh->verts.size(); + size_t steps = mesh->motion_steps - 1; + float3 *vert_steps = attr->data_float3(); + + for (size_t i = 0; i < steps; i++) { + triangle.bounds_grow(vert_steps + i * mesh_size, bbox); + } + } + } + } + } + + visibility |= ob->visibility; + } + + float4 leaf_data[BVH_ONODE_LEAF_SIZE]; + leaf_data[0].x = __int_as_float(c.x); + leaf_data[0].y = __int_as_float(c.y); + leaf_data[0].z = __uint_as_float(visibility); + leaf_data[0].w = __uint_as_float(c.w); + memcpy(&pack.leaf_nodes[idx], leaf_data, sizeof(float4) * BVH_ONODE_LEAF_SIZE); + } + else { + float8 *data = (float8 *)&pack.nodes[idx]; + bool is_unaligned = (__float_as_uint(data[0].a) & PATH_RAY_NODE_UNALIGNED) != 0; + /* Refit inner node, set bbox from children. */ + BoundBox child_bbox[8] = {BoundBox::empty, + BoundBox::empty, + BoundBox::empty, + BoundBox::empty, + BoundBox::empty, + BoundBox::empty, + BoundBox::empty, + BoundBox::empty}; + int child[8]; + uint child_visibility[8] = {0}; + int num_nodes = 0; + + for (int i = 0; i < 8; ++i) { + child[i] = __float_as_int(data[(is_unaligned) ? 13 : 7][i]); + + if (child[i] != 0) { + refit_node((child[i] < 0) ? -child[i] - 1 : child[i], + (child[i] < 0), + child_bbox[i], + child_visibility[i]); + ++num_nodes; + bbox.grow(child_bbox[i]); + visibility |= child_visibility[i]; + } + } + + if (is_unaligned) { + Transform aligned_space[8] = {transform_identity(), + transform_identity(), + transform_identity(), + transform_identity(), + transform_identity(), + transform_identity(), + transform_identity(), + transform_identity()}; + pack_unaligned_node( + idx, aligned_space, child_bbox, child, visibility, 0.0f, 1.0f, num_nodes); + } + else { + pack_aligned_node(idx, child_bbox, child, visibility, 0.0f, 1.0f, num_nodes); + } + } } CCL_NAMESPACE_END |