diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:17:24 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:21:24 +0300 |
commit | e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch) | |
tree | 8cf3453d12edb177a218ef8009357518ec6cab6a /intern/cycles/bvh/bvh.cpp | |
parent | b3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff) |
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211.
For details on usage and instructions for migrating branches
without conflicts, see:
https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'intern/cycles/bvh/bvh.cpp')
-rw-r--r-- | intern/cycles/bvh/bvh.cpp | 946 |
1 files changed, 471 insertions, 475 deletions
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp index af012bbf3ac..53c66777928 100644 --- a/intern/cycles/bvh/bvh.cpp +++ b/intern/cycles/bvh/bvh.cpp @@ -27,7 +27,7 @@ #include "bvh/bvh_node.h" #ifdef WITH_EMBREE -#include "bvh/bvh_embree.h" +# include "bvh/bvh_embree.h" #endif #include "util/util_foreach.h" @@ -40,533 +40,529 @@ CCL_NAMESPACE_BEGIN const char *bvh_layout_name(BVHLayout layout) { - switch(layout) { - case BVH_LAYOUT_BVH2: return "BVH2"; - case BVH_LAYOUT_BVH4: return "BVH4"; - case BVH_LAYOUT_BVH8: return "BVH8"; - case BVH_LAYOUT_NONE: return "NONE"; - case BVH_LAYOUT_EMBREE: return "EMBREE"; - case BVH_LAYOUT_ALL: return "ALL"; - } - LOG(DFATAL) << "Unsupported BVH layout was passed."; - return ""; + switch (layout) { + case BVH_LAYOUT_BVH2: + return "BVH2"; + case BVH_LAYOUT_BVH4: + return "BVH4"; + case BVH_LAYOUT_BVH8: + return "BVH8"; + case BVH_LAYOUT_NONE: + return "NONE"; + case BVH_LAYOUT_EMBREE: + return "EMBREE"; + case BVH_LAYOUT_ALL: + return "ALL"; + } + LOG(DFATAL) << "Unsupported BVH layout was passed."; + return ""; } -BVHLayout BVHParams::best_bvh_layout(BVHLayout requested_layout, - BVHLayoutMask supported_layouts) +BVHLayout BVHParams::best_bvh_layout(BVHLayout requested_layout, BVHLayoutMask supported_layouts) { - const BVHLayoutMask requested_layout_mask = (BVHLayoutMask)requested_layout; - /* Check whether requested layout is supported, if so -- no need to do - * any extra computation. - */ - if(supported_layouts & requested_layout_mask) { - return requested_layout; - } - /* Some bit magic to get widest supported BVH layout. */ - /* This is a mask of supported BVH layouts which are narrower than the - * requested one. - */ - const BVHLayoutMask allowed_layouts_mask = - (supported_layouts & (requested_layout_mask - 1)); - /* We get widest from allowed ones and convert mask to actual layout. */ - const BVHLayoutMask widest_allowed_layout_mask = __bsr(allowed_layouts_mask); - return (BVHLayout)(1 << widest_allowed_layout_mask); + const BVHLayoutMask requested_layout_mask = (BVHLayoutMask)requested_layout; + /* Check whether requested layout is supported, if so -- no need to do + * any extra computation. + */ + if (supported_layouts & requested_layout_mask) { + return requested_layout; + } + /* Some bit magic to get widest supported BVH layout. */ + /* This is a mask of supported BVH layouts which are narrower than the + * requested one. + */ + const BVHLayoutMask allowed_layouts_mask = (supported_layouts & (requested_layout_mask - 1)); + /* We get widest from allowed ones and convert mask to actual layout. */ + const BVHLayoutMask widest_allowed_layout_mask = __bsr(allowed_layouts_mask); + return (BVHLayout)(1 << widest_allowed_layout_mask); } /* Pack Utility */ -BVHStackEntry::BVHStackEntry(const BVHNode *n, int i) - : node(n), idx(i) +BVHStackEntry::BVHStackEntry(const BVHNode *n, int i) : node(n), idx(i) { } int BVHStackEntry::encodeIdx() const { - return (node->is_leaf())? ~idx: idx; + return (node->is_leaf()) ? ~idx : idx; } /* BVH */ -BVH::BVH(const BVHParams& params_, const vector<Object*>& objects_) -: params(params_), objects(objects_) +BVH::BVH(const BVHParams ¶ms_, const vector<Object *> &objects_) + : params(params_), objects(objects_) { } -BVH *BVH::create(const BVHParams& params, const vector<Object*>& objects) +BVH *BVH::create(const BVHParams ¶ms, const vector<Object *> &objects) { - switch(params.bvh_layout) { - case BVH_LAYOUT_BVH2: - return new BVH2(params, objects); - case BVH_LAYOUT_BVH4: - return new BVH4(params, objects); - case BVH_LAYOUT_BVH8: - return new BVH8(params, objects); - case BVH_LAYOUT_EMBREE: + switch (params.bvh_layout) { + case BVH_LAYOUT_BVH2: + return new BVH2(params, objects); + case BVH_LAYOUT_BVH4: + return new BVH4(params, objects); + case BVH_LAYOUT_BVH8: + return new BVH8(params, objects); + case BVH_LAYOUT_EMBREE: #ifdef WITH_EMBREE - return new BVHEmbree(params, objects); + return new BVHEmbree(params, objects); #endif - case BVH_LAYOUT_NONE: - case BVH_LAYOUT_ALL: - break; - } - LOG(DFATAL) << "Requested unsupported BVH layout."; - return NULL; + case BVH_LAYOUT_NONE: + case BVH_LAYOUT_ALL: + break; + } + LOG(DFATAL) << "Requested unsupported BVH layout."; + return NULL; } /* Building */ -void BVH::build(Progress& progress, Stats*) +void BVH::build(Progress &progress, Stats *) { - progress.set_substatus("Building BVH"); - - /* build nodes */ - BVHBuild bvh_build(objects, - pack.prim_type, - pack.prim_index, - pack.prim_object, - pack.prim_time, - params, - progress); - BVHNode *bvh2_root = bvh_build.run(); - - if(progress.get_cancel()) { - if(bvh2_root != NULL) { - bvh2_root->deleteSubtree(); - } - return; - } - - /* BVH builder returns tree in a binary mode (with two children per inner - * node. Need to adopt that for a wider BVH implementations. */ - BVHNode *root = widen_children_nodes(bvh2_root); - if(root != bvh2_root) { - bvh2_root->deleteSubtree(); - } - - if(progress.get_cancel()) { - if(root != NULL) { - root->deleteSubtree(); - } - return; - } - - /* pack triangles */ - progress.set_substatus("Packing BVH triangles and strands"); - pack_primitives(); - - if(progress.get_cancel()) { - root->deleteSubtree(); - return; - } - - /* pack nodes */ - progress.set_substatus("Packing BVH nodes"); - pack_nodes(root); - - /* free build nodes */ - root->deleteSubtree(); + progress.set_substatus("Building BVH"); + + /* build nodes */ + BVHBuild bvh_build(objects, + pack.prim_type, + pack.prim_index, + pack.prim_object, + pack.prim_time, + params, + progress); + BVHNode *bvh2_root = bvh_build.run(); + + if (progress.get_cancel()) { + if (bvh2_root != NULL) { + bvh2_root->deleteSubtree(); + } + return; + } + + /* BVH builder returns tree in a binary mode (with two children per inner + * node. Need to adopt that for a wider BVH implementations. */ + BVHNode *root = widen_children_nodes(bvh2_root); + if (root != bvh2_root) { + bvh2_root->deleteSubtree(); + } + + if (progress.get_cancel()) { + if (root != NULL) { + root->deleteSubtree(); + } + return; + } + + /* pack triangles */ + progress.set_substatus("Packing BVH triangles and strands"); + pack_primitives(); + + if (progress.get_cancel()) { + root->deleteSubtree(); + return; + } + + /* pack nodes */ + progress.set_substatus("Packing BVH nodes"); + pack_nodes(root); + + /* free build nodes */ + root->deleteSubtree(); } /* Refitting */ -void BVH::refit(Progress& progress) +void BVH::refit(Progress &progress) { - progress.set_substatus("Packing BVH primitives"); - pack_primitives(); + progress.set_substatus("Packing BVH primitives"); + pack_primitives(); - if(progress.get_cancel()) return; + if (progress.get_cancel()) + return; - progress.set_substatus("Refitting BVH nodes"); - refit_nodes(); + progress.set_substatus("Refitting BVH nodes"); + refit_nodes(); } -void BVH::refit_primitives(int start, int end, BoundBox& bbox, uint& visibility) +void BVH::refit_primitives(int start, int end, BoundBox &bbox, uint &visibility) { - /* Refit range of primitives. */ - for(int prim = start; prim < end; 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_for_tracing(); - - } + /* Refit range of primitives. */ + for (int prim = start; prim < end; 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_for_tracing(); + } } /* Triangles */ void BVH::pack_triangle(int idx, float4 tri_verts[3]) { - int tob = pack.prim_object[idx]; - assert(tob >= 0 && tob < objects.size()); - const Mesh *mesh = objects[tob]->mesh; - - int tidx = pack.prim_index[idx]; - Mesh::Triangle t = mesh->get_triangle(tidx); - const float3 *vpos = &mesh->verts[0]; - float3 v0 = vpos[t.v[0]]; - float3 v1 = vpos[t.v[1]]; - float3 v2 = vpos[t.v[2]]; - - tri_verts[0] = float3_to_float4(v0); - tri_verts[1] = float3_to_float4(v1); - tri_verts[2] = float3_to_float4(v2); + int tob = pack.prim_object[idx]; + assert(tob >= 0 && tob < objects.size()); + const Mesh *mesh = objects[tob]->mesh; + + int tidx = pack.prim_index[idx]; + Mesh::Triangle t = mesh->get_triangle(tidx); + const float3 *vpos = &mesh->verts[0]; + float3 v0 = vpos[t.v[0]]; + float3 v1 = vpos[t.v[1]]; + float3 v2 = vpos[t.v[2]]; + + tri_verts[0] = float3_to_float4(v0); + tri_verts[1] = float3_to_float4(v1); + tri_verts[2] = float3_to_float4(v2); } void BVH::pack_primitives() { - const size_t tidx_size = pack.prim_index.size(); - size_t num_prim_triangles = 0; - /* Count number of triangles primitives in BVH. */ - for(unsigned int i = 0; i < tidx_size; i++) { - if((pack.prim_index[i] != -1)) { - if((pack.prim_type[i] & PRIMITIVE_ALL_TRIANGLE) != 0) { - ++num_prim_triangles; - } - } - } - /* Reserve size for arrays. */ - pack.prim_tri_index.clear(); - pack.prim_tri_index.resize(tidx_size); - pack.prim_tri_verts.clear(); - pack.prim_tri_verts.resize(num_prim_triangles * 3); - pack.prim_visibility.clear(); - pack.prim_visibility.resize(tidx_size); - /* Fill in all the arrays. */ - size_t prim_triangle_index = 0; - for(unsigned int i = 0; i < tidx_size; i++) { - if(pack.prim_index[i] != -1) { - int tob = pack.prim_object[i]; - Object *ob = objects[tob]; - if((pack.prim_type[i] & PRIMITIVE_ALL_TRIANGLE) != 0) { - pack_triangle(i, (float4*)&pack.prim_tri_verts[3 * prim_triangle_index]); - pack.prim_tri_index[i] = 3 * prim_triangle_index; - ++prim_triangle_index; - } - else { - pack.prim_tri_index[i] = -1; - } - pack.prim_visibility[i] = ob->visibility_for_tracing(); - if(pack.prim_type[i] & PRIMITIVE_ALL_CURVE) { - pack.prim_visibility[i] |= PATH_RAY_CURVE; - } - } - else { - pack.prim_tri_index[i] = -1; - pack.prim_visibility[i] = 0; - } - } + const size_t tidx_size = pack.prim_index.size(); + size_t num_prim_triangles = 0; + /* Count number of triangles primitives in BVH. */ + for (unsigned int i = 0; i < tidx_size; i++) { + if ((pack.prim_index[i] != -1)) { + if ((pack.prim_type[i] & PRIMITIVE_ALL_TRIANGLE) != 0) { + ++num_prim_triangles; + } + } + } + /* Reserve size for arrays. */ + pack.prim_tri_index.clear(); + pack.prim_tri_index.resize(tidx_size); + pack.prim_tri_verts.clear(); + pack.prim_tri_verts.resize(num_prim_triangles * 3); + pack.prim_visibility.clear(); + pack.prim_visibility.resize(tidx_size); + /* Fill in all the arrays. */ + size_t prim_triangle_index = 0; + for (unsigned int i = 0; i < tidx_size; i++) { + if (pack.prim_index[i] != -1) { + int tob = pack.prim_object[i]; + Object *ob = objects[tob]; + if ((pack.prim_type[i] & PRIMITIVE_ALL_TRIANGLE) != 0) { + pack_triangle(i, (float4 *)&pack.prim_tri_verts[3 * prim_triangle_index]); + pack.prim_tri_index[i] = 3 * prim_triangle_index; + ++prim_triangle_index; + } + else { + pack.prim_tri_index[i] = -1; + } + pack.prim_visibility[i] = ob->visibility_for_tracing(); + if (pack.prim_type[i] & PRIMITIVE_ALL_CURVE) { + pack.prim_visibility[i] |= PATH_RAY_CURVE; + } + } + else { + pack.prim_tri_index[i] = -1; + pack.prim_visibility[i] = 0; + } + } } /* Pack Instances */ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size) { - /* The BVH's for instances are built separately, but for traversal all - * BVH's are stored in global arrays. This function merges them into the - * top level BVH, adjusting indexes and offsets where appropriate. - */ - const bool use_qbvh = (params.bvh_layout == BVH_LAYOUT_BVH4); - const bool use_obvh = (params.bvh_layout == BVH_LAYOUT_BVH8); - - /* Adjust primitive index to point to the triangle in the global array, for - * meshes with transform applied and already in the top level BVH. - */ - for(size_t i = 0; i < pack.prim_index.size(); i++) - if(pack.prim_index[i] != -1) { - if(pack.prim_type[i] & PRIMITIVE_ALL_CURVE) - pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->curve_offset; - else - pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset; - } - - /* track offsets of instanced BVH data in global array */ - size_t prim_offset = pack.prim_index.size(); - size_t nodes_offset = nodes_size; - size_t nodes_leaf_offset = leaf_nodes_size; - - /* clear array that gives the node indexes for instanced objects */ - pack.object_node.clear(); - - /* reserve */ - size_t prim_index_size = pack.prim_index.size(); - size_t prim_tri_verts_size = pack.prim_tri_verts.size(); - - size_t pack_prim_index_offset = prim_index_size; - size_t pack_prim_tri_verts_offset = prim_tri_verts_size; - size_t pack_nodes_offset = nodes_size; - size_t pack_leaf_nodes_offset = leaf_nodes_size; - size_t object_offset = 0; - - map<Mesh*, int> mesh_map; - - foreach(Object *ob, objects) { - Mesh *mesh = ob->mesh; - BVH *bvh = mesh->bvh; - - if(mesh->need_build_bvh()) { - if(mesh_map.find(mesh) == mesh_map.end()) { - prim_index_size += bvh->pack.prim_index.size(); - prim_tri_verts_size += bvh->pack.prim_tri_verts.size(); - nodes_size += bvh->pack.nodes.size(); - leaf_nodes_size += bvh->pack.leaf_nodes.size(); - - mesh_map[mesh] = 1; - } - } - } - - mesh_map.clear(); - - pack.prim_index.resize(prim_index_size); - pack.prim_type.resize(prim_index_size); - pack.prim_object.resize(prim_index_size); - pack.prim_visibility.resize(prim_index_size); - pack.prim_tri_verts.resize(prim_tri_verts_size); - pack.prim_tri_index.resize(prim_index_size); - pack.nodes.resize(nodes_size); - pack.leaf_nodes.resize(leaf_nodes_size); - pack.object_node.resize(objects.size()); - - if(params.num_motion_curve_steps > 0 || params.num_motion_triangle_steps > 0) { - pack.prim_time.resize(prim_index_size); - } - - int *pack_prim_index = (pack.prim_index.size())? &pack.prim_index[0]: NULL; - int *pack_prim_type = (pack.prim_type.size())? &pack.prim_type[0]: NULL; - int *pack_prim_object = (pack.prim_object.size())? &pack.prim_object[0]: NULL; - uint *pack_prim_visibility = (pack.prim_visibility.size())? &pack.prim_visibility[0]: NULL; - float4 *pack_prim_tri_verts = (pack.prim_tri_verts.size())? &pack.prim_tri_verts[0]: NULL; - uint *pack_prim_tri_index = (pack.prim_tri_index.size())? &pack.prim_tri_index[0]: NULL; - int4 *pack_nodes = (pack.nodes.size())? &pack.nodes[0]: NULL; - int4 *pack_leaf_nodes = (pack.leaf_nodes.size())? &pack.leaf_nodes[0]: NULL; - float2 *pack_prim_time = (pack.prim_time.size())? &pack.prim_time[0]: NULL; - - /* merge */ - foreach(Object *ob, objects) { - Mesh *mesh = ob->mesh; - - /* We assume that if mesh doesn't need own BVH it was already included - * into a top-level BVH and no packing here is needed. - */ - if(!mesh->need_build_bvh()) { - pack.object_node[object_offset++] = 0; - continue; - } - - /* if mesh already added once, don't add it again, but used set - * node offset for this object */ - map<Mesh*, int>::iterator it = mesh_map.find(mesh); - - if(mesh_map.find(mesh) != mesh_map.end()) { - int noffset = it->second; - pack.object_node[object_offset++] = noffset; - continue; - } - - BVH *bvh = mesh->bvh; - - int noffset = nodes_offset; - int noffset_leaf = nodes_leaf_offset; - int mesh_tri_offset = mesh->tri_offset; - int mesh_curve_offset = mesh->curve_offset; - - /* fill in node indexes for instances */ - if(bvh->pack.root_index == -1) - pack.object_node[object_offset++] = -noffset_leaf-1; - else - pack.object_node[object_offset++] = noffset; - - mesh_map[mesh] = pack.object_node[object_offset-1]; - - /* merge primitive, object and triangle indexes */ - if(bvh->pack.prim_index.size()) { - size_t bvh_prim_index_size = bvh->pack.prim_index.size(); - int *bvh_prim_index = &bvh->pack.prim_index[0]; - int *bvh_prim_type = &bvh->pack.prim_type[0]; - uint *bvh_prim_visibility = &bvh->pack.prim_visibility[0]; - uint *bvh_prim_tri_index = &bvh->pack.prim_tri_index[0]; - float2 *bvh_prim_time = bvh->pack.prim_time.size()? &bvh->pack.prim_time[0]: NULL; - - for(size_t i = 0; i < bvh_prim_index_size; i++) { - if(bvh->pack.prim_type[i] & PRIMITIVE_ALL_CURVE) { - pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_curve_offset; - pack_prim_tri_index[pack_prim_index_offset] = -1; - } - else { - pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_tri_offset; - pack_prim_tri_index[pack_prim_index_offset] = - bvh_prim_tri_index[i] + pack_prim_tri_verts_offset; - } - - pack_prim_type[pack_prim_index_offset] = bvh_prim_type[i]; - pack_prim_visibility[pack_prim_index_offset] = bvh_prim_visibility[i]; - pack_prim_object[pack_prim_index_offset] = 0; // unused for instances - if(bvh_prim_time != NULL) { - pack_prim_time[pack_prim_index_offset] = bvh_prim_time[i]; - } - pack_prim_index_offset++; - } - } - - /* Merge triangle vertices data. */ - if(bvh->pack.prim_tri_verts.size()) { - const size_t prim_tri_size = bvh->pack.prim_tri_verts.size(); - memcpy(pack_prim_tri_verts + pack_prim_tri_verts_offset, - &bvh->pack.prim_tri_verts[0], - prim_tri_size*sizeof(float4)); - pack_prim_tri_verts_offset += prim_tri_size; - } - - /* merge nodes */ - if(bvh->pack.leaf_nodes.size()) { - int4 *leaf_nodes_offset = &bvh->pack.leaf_nodes[0]; - size_t leaf_nodes_offset_size = bvh->pack.leaf_nodes.size(); - for(size_t i = 0, j = 0; - i < leaf_nodes_offset_size; - i += BVH_NODE_LEAF_SIZE, j++) - { - int4 data = leaf_nodes_offset[i]; - data.x += prim_offset; - data.y += prim_offset; - pack_leaf_nodes[pack_leaf_nodes_offset] = data; - for(int j = 1; j < BVH_NODE_LEAF_SIZE; ++j) { - pack_leaf_nodes[pack_leaf_nodes_offset + j] = leaf_nodes_offset[i + j]; - } - pack_leaf_nodes_offset += BVH_NODE_LEAF_SIZE; - } - } - - if(bvh->pack.nodes.size()) { - int4 *bvh_nodes = &bvh->pack.nodes[0]; - size_t bvh_nodes_size = bvh->pack.nodes.size(); - - for(size_t i = 0, j = 0; i < bvh_nodes_size; j++) { - size_t nsize, nsize_bbox; - if(bvh_nodes[i].x & PATH_RAY_NODE_UNALIGNED) { - if(use_obvh) { - nsize = BVH_UNALIGNED_ONODE_SIZE; - nsize_bbox = BVH_UNALIGNED_ONODE_SIZE-1; - } - else { - nsize = use_qbvh - ? BVH_UNALIGNED_QNODE_SIZE - : BVH_UNALIGNED_NODE_SIZE; - nsize_bbox = (use_qbvh) ? BVH_UNALIGNED_QNODE_SIZE-1 : 0; - } - } - else { - if(use_obvh) { - nsize = BVH_ONODE_SIZE; - nsize_bbox = BVH_ONODE_SIZE-1; - } - else { - nsize = (use_qbvh)? BVH_QNODE_SIZE: BVH_NODE_SIZE; - nsize_bbox = (use_qbvh)? BVH_QNODE_SIZE-1 : 0; - } - } - - memcpy(pack_nodes + pack_nodes_offset, - bvh_nodes + i, - nsize_bbox*sizeof(int4)); - - /* Modify offsets into arrays */ - int4 data = bvh_nodes[i + nsize_bbox]; - int4 data1 = bvh_nodes[i + nsize_bbox-1]; - if(use_obvh) { - data.z += (data.z < 0) ? -noffset_leaf : noffset; - data.w += (data.w < 0) ? -noffset_leaf : noffset; - data.x += (data.x < 0) ? -noffset_leaf : noffset; - data.y += (data.y < 0) ? -noffset_leaf : noffset; - data1.z += (data1.z < 0) ? -noffset_leaf : noffset; - data1.w += (data1.w < 0) ? -noffset_leaf : noffset; - data1.x += (data1.x < 0) ? -noffset_leaf : noffset; - data1.y += (data1.y < 0) ? -noffset_leaf : noffset; - } - else { - data.z += (data.z < 0) ? -noffset_leaf : noffset; - data.w += (data.w < 0) ? -noffset_leaf : noffset; - if(use_qbvh) { - data.x += (data.x < 0)? -noffset_leaf: noffset; - data.y += (data.y < 0)? -noffset_leaf: noffset; - } - } - pack_nodes[pack_nodes_offset + nsize_bbox] = data; - if(use_obvh) { - pack_nodes[pack_nodes_offset + nsize_bbox - 1] = data1; - } - - /* Usually this copies nothing, but we better - * be prepared for possible node size extension. - */ - memcpy(&pack_nodes[pack_nodes_offset + nsize_bbox+1], - &bvh_nodes[i + nsize_bbox+1], - sizeof(int4) * (nsize - (nsize_bbox+1))); - - pack_nodes_offset += nsize; - i += nsize; - } - } - - nodes_offset += bvh->pack.nodes.size(); - nodes_leaf_offset += bvh->pack.leaf_nodes.size(); - prim_offset += bvh->pack.prim_index.size(); - } + /* The BVH's for instances are built separately, but for traversal all + * BVH's are stored in global arrays. This function merges them into the + * top level BVH, adjusting indexes and offsets where appropriate. + */ + const bool use_qbvh = (params.bvh_layout == BVH_LAYOUT_BVH4); + const bool use_obvh = (params.bvh_layout == BVH_LAYOUT_BVH8); + + /* Adjust primitive index to point to the triangle in the global array, for + * meshes with transform applied and already in the top level BVH. + */ + for (size_t i = 0; i < pack.prim_index.size(); i++) + if (pack.prim_index[i] != -1) { + if (pack.prim_type[i] & PRIMITIVE_ALL_CURVE) + pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->curve_offset; + else + pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset; + } + + /* track offsets of instanced BVH data in global array */ + size_t prim_offset = pack.prim_index.size(); + size_t nodes_offset = nodes_size; + size_t nodes_leaf_offset = leaf_nodes_size; + + /* clear array that gives the node indexes for instanced objects */ + pack.object_node.clear(); + + /* reserve */ + size_t prim_index_size = pack.prim_index.size(); + size_t prim_tri_verts_size = pack.prim_tri_verts.size(); + + size_t pack_prim_index_offset = prim_index_size; + size_t pack_prim_tri_verts_offset = prim_tri_verts_size; + size_t pack_nodes_offset = nodes_size; + size_t pack_leaf_nodes_offset = leaf_nodes_size; + size_t object_offset = 0; + + map<Mesh *, int> mesh_map; + + foreach (Object *ob, objects) { + Mesh *mesh = ob->mesh; + BVH *bvh = mesh->bvh; + + if (mesh->need_build_bvh()) { + if (mesh_map.find(mesh) == mesh_map.end()) { + prim_index_size += bvh->pack.prim_index.size(); + prim_tri_verts_size += bvh->pack.prim_tri_verts.size(); + nodes_size += bvh->pack.nodes.size(); + leaf_nodes_size += bvh->pack.leaf_nodes.size(); + + mesh_map[mesh] = 1; + } + } + } + + mesh_map.clear(); + + pack.prim_index.resize(prim_index_size); + pack.prim_type.resize(prim_index_size); + pack.prim_object.resize(prim_index_size); + pack.prim_visibility.resize(prim_index_size); + pack.prim_tri_verts.resize(prim_tri_verts_size); + pack.prim_tri_index.resize(prim_index_size); + pack.nodes.resize(nodes_size); + pack.leaf_nodes.resize(leaf_nodes_size); + pack.object_node.resize(objects.size()); + + if (params.num_motion_curve_steps > 0 || params.num_motion_triangle_steps > 0) { + pack.prim_time.resize(prim_index_size); + } + + int *pack_prim_index = (pack.prim_index.size()) ? &pack.prim_index[0] : NULL; + int *pack_prim_type = (pack.prim_type.size()) ? &pack.prim_type[0] : NULL; + int *pack_prim_object = (pack.prim_object.size()) ? &pack.prim_object[0] : NULL; + uint *pack_prim_visibility = (pack.prim_visibility.size()) ? &pack.prim_visibility[0] : NULL; + float4 *pack_prim_tri_verts = (pack.prim_tri_verts.size()) ? &pack.prim_tri_verts[0] : NULL; + uint *pack_prim_tri_index = (pack.prim_tri_index.size()) ? &pack.prim_tri_index[0] : NULL; + int4 *pack_nodes = (pack.nodes.size()) ? &pack.nodes[0] : NULL; + int4 *pack_leaf_nodes = (pack.leaf_nodes.size()) ? &pack.leaf_nodes[0] : NULL; + float2 *pack_prim_time = (pack.prim_time.size()) ? &pack.prim_time[0] : NULL; + + /* merge */ + foreach (Object *ob, objects) { + Mesh *mesh = ob->mesh; + + /* We assume that if mesh doesn't need own BVH it was already included + * into a top-level BVH and no packing here is needed. + */ + if (!mesh->need_build_bvh()) { + pack.object_node[object_offset++] = 0; + continue; + } + + /* if mesh already added once, don't add it again, but used set + * node offset for this object */ + map<Mesh *, int>::iterator it = mesh_map.find(mesh); + + if (mesh_map.find(mesh) != mesh_map.end()) { + int noffset = it->second; + pack.object_node[object_offset++] = noffset; + continue; + } + + BVH *bvh = mesh->bvh; + + int noffset = nodes_offset; + int noffset_leaf = nodes_leaf_offset; + int mesh_tri_offset = mesh->tri_offset; + int mesh_curve_offset = mesh->curve_offset; + + /* fill in node indexes for instances */ + if (bvh->pack.root_index == -1) + pack.object_node[object_offset++] = -noffset_leaf - 1; + else + pack.object_node[object_offset++] = noffset; + + mesh_map[mesh] = pack.object_node[object_offset - 1]; + + /* merge primitive, object and triangle indexes */ + if (bvh->pack.prim_index.size()) { + size_t bvh_prim_index_size = bvh->pack.prim_index.size(); + int *bvh_prim_index = &bvh->pack.prim_index[0]; + int *bvh_prim_type = &bvh->pack.prim_type[0]; + uint *bvh_prim_visibility = &bvh->pack.prim_visibility[0]; + uint *bvh_prim_tri_index = &bvh->pack.prim_tri_index[0]; + float2 *bvh_prim_time = bvh->pack.prim_time.size() ? &bvh->pack.prim_time[0] : NULL; + + for (size_t i = 0; i < bvh_prim_index_size; i++) { + if (bvh->pack.prim_type[i] & PRIMITIVE_ALL_CURVE) { + pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_curve_offset; + pack_prim_tri_index[pack_prim_index_offset] = -1; + } + else { + pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_tri_offset; + pack_prim_tri_index[pack_prim_index_offset] = bvh_prim_tri_index[i] + + pack_prim_tri_verts_offset; + } + + pack_prim_type[pack_prim_index_offset] = bvh_prim_type[i]; + pack_prim_visibility[pack_prim_index_offset] = bvh_prim_visibility[i]; + pack_prim_object[pack_prim_index_offset] = 0; // unused for instances + if (bvh_prim_time != NULL) { + pack_prim_time[pack_prim_index_offset] = bvh_prim_time[i]; + } + pack_prim_index_offset++; + } + } + + /* Merge triangle vertices data. */ + if (bvh->pack.prim_tri_verts.size()) { + const size_t prim_tri_size = bvh->pack.prim_tri_verts.size(); + memcpy(pack_prim_tri_verts + pack_prim_tri_verts_offset, + &bvh->pack.prim_tri_verts[0], + prim_tri_size * sizeof(float4)); + pack_prim_tri_verts_offset += prim_tri_size; + } + + /* merge nodes */ + if (bvh->pack.leaf_nodes.size()) { + int4 *leaf_nodes_offset = &bvh->pack.leaf_nodes[0]; + size_t leaf_nodes_offset_size = bvh->pack.leaf_nodes.size(); + for (size_t i = 0, j = 0; i < leaf_nodes_offset_size; i += BVH_NODE_LEAF_SIZE, j++) { + int4 data = leaf_nodes_offset[i]; + data.x += prim_offset; + data.y += prim_offset; + pack_leaf_nodes[pack_leaf_nodes_offset] = data; + for (int j = 1; j < BVH_NODE_LEAF_SIZE; ++j) { + pack_leaf_nodes[pack_leaf_nodes_offset + j] = leaf_nodes_offset[i + j]; + } + pack_leaf_nodes_offset += BVH_NODE_LEAF_SIZE; + } + } + + if (bvh->pack.nodes.size()) { + int4 *bvh_nodes = &bvh->pack.nodes[0]; + size_t bvh_nodes_size = bvh->pack.nodes.size(); + + for (size_t i = 0, j = 0; i < bvh_nodes_size; j++) { + size_t nsize, nsize_bbox; + if (bvh_nodes[i].x & PATH_RAY_NODE_UNALIGNED) { + if (use_obvh) { + nsize = BVH_UNALIGNED_ONODE_SIZE; + nsize_bbox = BVH_UNALIGNED_ONODE_SIZE - 1; + } + else { + nsize = use_qbvh ? BVH_UNALIGNED_QNODE_SIZE : BVH_UNALIGNED_NODE_SIZE; + nsize_bbox = (use_qbvh) ? BVH_UNALIGNED_QNODE_SIZE - 1 : 0; + } + } + else { + if (use_obvh) { + nsize = BVH_ONODE_SIZE; + nsize_bbox = BVH_ONODE_SIZE - 1; + } + else { + nsize = (use_qbvh) ? BVH_QNODE_SIZE : BVH_NODE_SIZE; + nsize_bbox = (use_qbvh) ? BVH_QNODE_SIZE - 1 : 0; + } + } + + memcpy(pack_nodes + pack_nodes_offset, bvh_nodes + i, nsize_bbox * sizeof(int4)); + + /* Modify offsets into arrays */ + int4 data = bvh_nodes[i + nsize_bbox]; + int4 data1 = bvh_nodes[i + nsize_bbox - 1]; + if (use_obvh) { + data.z += (data.z < 0) ? -noffset_leaf : noffset; + data.w += (data.w < 0) ? -noffset_leaf : noffset; + data.x += (data.x < 0) ? -noffset_leaf : noffset; + data.y += (data.y < 0) ? -noffset_leaf : noffset; + data1.z += (data1.z < 0) ? -noffset_leaf : noffset; + data1.w += (data1.w < 0) ? -noffset_leaf : noffset; + data1.x += (data1.x < 0) ? -noffset_leaf : noffset; + data1.y += (data1.y < 0) ? -noffset_leaf : noffset; + } + else { + data.z += (data.z < 0) ? -noffset_leaf : noffset; + data.w += (data.w < 0) ? -noffset_leaf : noffset; + if (use_qbvh) { + data.x += (data.x < 0) ? -noffset_leaf : noffset; + data.y += (data.y < 0) ? -noffset_leaf : noffset; + } + } + pack_nodes[pack_nodes_offset + nsize_bbox] = data; + if (use_obvh) { + pack_nodes[pack_nodes_offset + nsize_bbox - 1] = data1; + } + + /* Usually this copies nothing, but we better + * be prepared for possible node size extension. + */ + memcpy(&pack_nodes[pack_nodes_offset + nsize_bbox + 1], + &bvh_nodes[i + nsize_bbox + 1], + sizeof(int4) * (nsize - (nsize_bbox + 1))); + + pack_nodes_offset += nsize; + i += nsize; + } + } + + nodes_offset += bvh->pack.nodes.size(); + nodes_leaf_offset += bvh->pack.leaf_nodes.size(); + prim_offset += bvh->pack.prim_index.size(); + } } CCL_NAMESPACE_END |