Blender V2.61 - r43446
|
00001 /* 00002 * Adapted from code copyright 2009-2010 NVIDIA Corporation 00003 * Modifications Copyright 2011, Blender Foundation. 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #include "mesh.h" 00019 #include "object.h" 00020 #include "scene.h" 00021 00022 #include "bvh.h" 00023 #include "bvh_build.h" 00024 #include "bvh_node.h" 00025 #include "bvh_params.h" 00026 00027 #include "util_cache.h" 00028 #include "util_debug.h" 00029 #include "util_foreach.h" 00030 #include "util_map.h" 00031 #include "util_progress.h" 00032 #include "util_types.h" 00033 00034 CCL_NAMESPACE_BEGIN 00035 00036 /* Pack Utility */ 00037 00038 struct BVHStackEntry 00039 { 00040 const BVHNode *node; 00041 int idx; 00042 00043 BVHStackEntry(const BVHNode* n = 0, int i = 0) 00044 : node(n), idx(i) 00045 { 00046 } 00047 00048 int encodeIdx() const 00049 { 00050 return (node->is_leaf())? ~idx: idx; 00051 } 00052 }; 00053 00054 /* BVH */ 00055 00056 BVH::BVH(const BVHParams& params_, const vector<Object*>& objects_) 00057 : params(params_), objects(objects_) 00058 { 00059 } 00060 00061 BVH *BVH::create(const BVHParams& params, const vector<Object*>& objects) 00062 { 00063 if(params.use_qbvh) 00064 return new QBVH(params, objects); 00065 else 00066 return new RegularBVH(params, objects); 00067 } 00068 00069 /* Cache */ 00070 00071 bool BVH::cache_read(CacheData& key) 00072 { 00073 key.add(¶ms, sizeof(params)); 00074 00075 foreach(Object *ob, objects) { 00076 key.add(ob->mesh->verts); 00077 key.add(ob->mesh->triangles); 00078 key.add(&ob->bounds, sizeof(ob->bounds)); 00079 key.add(&ob->visibility, sizeof(ob->visibility)); 00080 key.add(&ob->mesh->transform_applied, sizeof(bool)); 00081 } 00082 00083 CacheData value; 00084 00085 if(Cache::global.lookup(key, value)) { 00086 cache_filename = key.get_filename(); 00087 00088 value.read(pack.root_index); 00089 value.read(pack.SAH); 00090 00091 value.read(pack.nodes); 00092 value.read(pack.object_node); 00093 value.read(pack.tri_woop); 00094 value.read(pack.prim_visibility); 00095 value.read(pack.prim_index); 00096 value.read(pack.prim_object); 00097 value.read(pack.is_leaf); 00098 00099 return true; 00100 } 00101 00102 return false; 00103 } 00104 00105 void BVH::cache_write(CacheData& key) 00106 { 00107 CacheData value; 00108 00109 value.add(pack.root_index); 00110 value.add(pack.SAH); 00111 00112 value.add(pack.nodes); 00113 value.add(pack.object_node); 00114 value.add(pack.tri_woop); 00115 value.add(pack.prim_visibility); 00116 value.add(pack.prim_index); 00117 value.add(pack.prim_object); 00118 value.add(pack.is_leaf); 00119 00120 Cache::global.insert(key, value); 00121 00122 cache_filename = key.get_filename(); 00123 } 00124 00125 void BVH::clear_cache_except() 00126 { 00127 set<string> except; 00128 00129 if(!cache_filename.empty()) 00130 except.insert(cache_filename); 00131 00132 foreach(Object *ob, objects) { 00133 Mesh *mesh = ob->mesh; 00134 BVH *bvh = mesh->bvh; 00135 00136 if(bvh && !bvh->cache_filename.empty()) 00137 except.insert(bvh->cache_filename); 00138 } 00139 00140 Cache::global.clear_except("bvh", except); 00141 } 00142 00143 /* Building */ 00144 00145 void BVH::build(Progress& progress) 00146 { 00147 progress.set_substatus("Building BVH"); 00148 00149 /* cache read */ 00150 CacheData key("bvh"); 00151 00152 if(params.use_cache) { 00153 progress.set_substatus("Looking in BVH cache"); 00154 00155 if(cache_read(key)) 00156 return; 00157 } 00158 00159 /* build nodes */ 00160 vector<int> prim_index; 00161 vector<int> prim_object; 00162 00163 BVHBuild bvh_build(objects, prim_index, prim_object, params, progress); 00164 BVHNode *root = bvh_build.run(); 00165 00166 if(progress.get_cancel()) { 00167 if(root) root->deleteSubtree(); 00168 return; 00169 } 00170 00171 /* todo: get rid of this copy */ 00172 pack.prim_index = prim_index; 00173 pack.prim_object = prim_object; 00174 00175 /* compute SAH */ 00176 if(!params.top_level) 00177 pack.SAH = root->computeSubtreeSAHCost(params); 00178 00179 if(progress.get_cancel()) { 00180 root->deleteSubtree(); 00181 return; 00182 } 00183 00184 /* pack triangles */ 00185 progress.set_substatus("Packing BVH triangles"); 00186 pack_triangles(); 00187 00188 if(progress.get_cancel()) { 00189 root->deleteSubtree(); 00190 return; 00191 } 00192 00193 /* pack nodes */ 00194 progress.set_substatus("Packing BVH nodes"); 00195 array<int> tmp_prim_object = pack.prim_object; 00196 pack_nodes(tmp_prim_object, root); 00197 00198 /* free build nodes */ 00199 root->deleteSubtree(); 00200 00201 if(progress.get_cancel()) return; 00202 00203 /* cache write */ 00204 if(params.use_cache) { 00205 progress.set_substatus("Writing BVH cache"); 00206 cache_write(key); 00207 00208 /* clear other bvh files from cache */ 00209 if(params.top_level) 00210 clear_cache_except(); 00211 } 00212 } 00213 00214 /* Refitting */ 00215 00216 void BVH::refit(Progress& progress) 00217 { 00218 progress.set_substatus("Packing BVH triangles"); 00219 pack_triangles(); 00220 00221 if(progress.get_cancel()) return; 00222 00223 progress.set_substatus("Refitting BVH nodes"); 00224 refit_nodes(); 00225 } 00226 00227 /* Triangles */ 00228 00229 void BVH::pack_triangle(int idx, float4 woop[3]) 00230 { 00231 /* create Woop triangle */ 00232 int tob = pack.prim_object[idx]; 00233 const Mesh *mesh = objects[tob]->mesh; 00234 int tidx = pack.prim_index[idx]; 00235 const int *vidx = mesh->triangles[tidx].v; 00236 const float3* vpos = &mesh->verts[0]; 00237 float3 v0 = vpos[vidx[0]]; 00238 float3 v1 = vpos[vidx[1]]; 00239 float3 v2 = vpos[vidx[2]]; 00240 00241 float3 r0 = v0 - v2; 00242 float3 r1 = v1 - v2; 00243 float3 r2 = cross(r0, r1); 00244 00245 if(dot(r0, r0) == 0.0f || dot(r1, r1) == 0.0f || dot(r2, r2) == 0.0f) { 00246 /* degenerate */ 00247 woop[0] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); 00248 woop[1] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); 00249 woop[2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); 00250 } 00251 else { 00252 Transform t = make_transform( 00253 r0.x, r1.x, r2.x, v2.x, 00254 r0.y, r1.y, r2.y, v2.y, 00255 r0.z, r1.z, r2.z, v2.z, 00256 0.0f, 0.0f, 0.0f, 1.0f); 00257 00258 t = transform_inverse(t); 00259 00260 woop[0] = make_float4(t.z.x, t.z.y, t.z.z, -t.z.w); 00261 woop[1] = make_float4(t.x.x, t.x.y, t.x.z, t.x.w); 00262 woop[2] = make_float4(t.y.x, t.y.y, t.y.z, t.y.w); 00263 } 00264 } 00265 00266 void BVH::pack_triangles() 00267 { 00268 int nsize = TRI_NODE_SIZE; 00269 size_t tidx_size = pack.prim_index.size(); 00270 00271 pack.tri_woop.clear(); 00272 pack.tri_woop.resize(tidx_size * nsize); 00273 pack.prim_visibility.clear(); 00274 pack.prim_visibility.resize(tidx_size); 00275 00276 for(unsigned int i = 0; i < tidx_size; i++) { 00277 if(pack.prim_index[i] != -1) { 00278 float4 woop[3]; 00279 00280 pack_triangle(i, woop); 00281 memcpy(&pack.tri_woop[i * nsize], woop, sizeof(float4)*3); 00282 00283 int tob = pack.prim_object[i]; 00284 Object *ob = objects[tob]; 00285 pack.prim_visibility[i] = ob->visibility; 00286 } 00287 } 00288 } 00289 00290 /* Pack Instances */ 00291 00292 void BVH::pack_instances(size_t nodes_size) 00293 { 00294 /* The BVH's for instances are built separately, but for traversal all 00295 BVH's are stored in global arrays. This function merges them into the 00296 top level BVH, adjusting indexes and offsets where appropriate. */ 00297 bool use_qbvh = params.use_qbvh; 00298 size_t nsize = (use_qbvh)? BVH_QNODE_SIZE: BVH_NODE_SIZE; 00299 00300 /* adjust primitive index to point to the triangle in the global array, for 00301 meshes with transform applied and already in the top level BVH */ 00302 for(size_t i = 0; i < pack.prim_index.size(); i++) 00303 if(pack.prim_index[i] != -1) 00304 pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset; 00305 00306 /* track offsets of instanced BVH data in global array */ 00307 size_t tri_offset = pack.prim_index.size(); 00308 size_t nodes_offset = nodes_size; 00309 00310 /* clear array that gives the node indexes for instanced objects */ 00311 pack.object_node.clear(); 00312 00313 /* reserve */ 00314 size_t prim_index_size = pack.prim_index.size(); 00315 size_t tri_woop_size = pack.tri_woop.size(); 00316 00317 size_t pack_prim_index_offset = prim_index_size; 00318 size_t pack_tri_woop_offset = tri_woop_size; 00319 size_t pack_nodes_offset = nodes_size; 00320 size_t object_offset = 0; 00321 00322 map<Mesh*, int> mesh_map; 00323 00324 foreach(Object *ob, objects) { 00325 Mesh *mesh = ob->mesh; 00326 BVH *bvh = mesh->bvh; 00327 00328 if(!mesh->transform_applied) { 00329 if(mesh_map.find(mesh) == mesh_map.end()) { 00330 prim_index_size += bvh->pack.prim_index.size(); 00331 tri_woop_size += bvh->pack.tri_woop.size(); 00332 nodes_size += bvh->pack.nodes.size()*nsize; 00333 00334 mesh_map[mesh] = 1; 00335 } 00336 } 00337 } 00338 00339 mesh_map.clear(); 00340 00341 pack.prim_index.resize(prim_index_size); 00342 pack.prim_object.resize(prim_index_size); 00343 pack.prim_visibility.resize(prim_index_size); 00344 pack.tri_woop.resize(tri_woop_size); 00345 pack.nodes.resize(nodes_size); 00346 pack.object_node.resize(objects.size()); 00347 00348 int *pack_prim_index = (pack.prim_index.size())? &pack.prim_index[0]: NULL; 00349 int *pack_prim_object = (pack.prim_object.size())? &pack.prim_object[0]: NULL; 00350 uint *pack_prim_visibility = (pack.prim_visibility.size())? &pack.prim_visibility[0]: NULL; 00351 float4 *pack_tri_woop = (pack.tri_woop.size())? &pack.tri_woop[0]: NULL; 00352 int4 *pack_nodes = (pack.nodes.size())? &pack.nodes[0]: NULL; 00353 00354 /* merge */ 00355 foreach(Object *ob, objects) { 00356 Mesh *mesh = ob->mesh; 00357 00358 /* if mesh transform is applied, that means it's already in the top 00359 level BVH, and we don't need to merge it in */ 00360 if(mesh->transform_applied) { 00361 pack.object_node[object_offset++] = 0; 00362 continue; 00363 } 00364 00365 /* if mesh already added once, don't add it again, but used set 00366 node offset for this object */ 00367 map<Mesh*, int>::iterator it = mesh_map.find(mesh); 00368 00369 if(mesh_map.find(mesh) != mesh_map.end()) { 00370 int noffset = it->second; 00371 pack.object_node[object_offset++] = noffset; 00372 continue; 00373 } 00374 00375 BVH *bvh = mesh->bvh; 00376 00377 int noffset = nodes_offset/nsize; 00378 int mesh_tri_offset = mesh->tri_offset; 00379 00380 /* fill in node indexes for instances */ 00381 if(bvh->pack.is_leaf[0]) 00382 pack.object_node[object_offset++] = -noffset-1; 00383 else 00384 pack.object_node[object_offset++] = noffset; 00385 00386 mesh_map[mesh] = pack.object_node[object_offset-1]; 00387 00388 /* merge primitive and object indexes */ 00389 if(bvh->pack.prim_index.size()) { 00390 size_t bvh_prim_index_size = bvh->pack.prim_index.size(); 00391 int *bvh_prim_index = &bvh->pack.prim_index[0]; 00392 uint *bvh_prim_visibility = &bvh->pack.prim_visibility[0]; 00393 00394 for(size_t i = 0; i < bvh_prim_index_size; i++) { 00395 pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_tri_offset; 00396 pack_prim_visibility[pack_prim_index_offset] = bvh_prim_visibility[i]; 00397 pack_prim_object[pack_prim_index_offset] = 0; // unused for instances 00398 pack_prim_index_offset++; 00399 } 00400 } 00401 00402 /* merge triangle intersection data */ 00403 if(bvh->pack.tri_woop.size()) { 00404 memcpy(pack_tri_woop+pack_tri_woop_offset, &bvh->pack.tri_woop[0], 00405 bvh->pack.tri_woop.size()*sizeof(float4)); 00406 pack_tri_woop_offset += bvh->pack.tri_woop.size(); 00407 } 00408 00409 /* merge nodes */ 00410 if( bvh->pack.nodes.size()) { 00411 size_t nsize_bbox = (use_qbvh)? nsize-2: nsize-1; 00412 int4 *bvh_nodes = &bvh->pack.nodes[0]; 00413 size_t bvh_nodes_size = bvh->pack.nodes.size(); 00414 int *bvh_is_leaf = &bvh->pack.is_leaf[0]; 00415 00416 for(size_t i = 0, j = 0; i < bvh_nodes_size; i+=nsize, j++) { 00417 memcpy(pack_nodes + pack_nodes_offset, bvh_nodes + i, nsize_bbox*sizeof(int4)); 00418 00419 /* modify offsets into arrays */ 00420 int4 data = bvh_nodes[i + nsize_bbox]; 00421 00422 if(bvh_is_leaf[j]) { 00423 data.x += tri_offset; 00424 data.y += tri_offset; 00425 } 00426 else { 00427 data.x += (data.x < 0)? -noffset: noffset; 00428 data.y += (data.y < 0)? -noffset: noffset; 00429 00430 if(use_qbvh) { 00431 data.z += (data.z < 0)? -noffset: noffset; 00432 data.w += (data.w < 0)? -noffset: noffset; 00433 } 00434 } 00435 00436 pack_nodes[pack_nodes_offset + nsize_bbox] = data; 00437 00438 if(use_qbvh) 00439 pack_nodes[pack_nodes_offset + nsize_bbox+1] = bvh_nodes[i + nsize_bbox+1]; 00440 00441 pack_nodes_offset += nsize; 00442 } 00443 } 00444 00445 nodes_offset += bvh->pack.nodes.size(); 00446 tri_offset += bvh->pack.prim_index.size(); 00447 } 00448 } 00449 00450 /* Regular BVH */ 00451 00452 RegularBVH::RegularBVH(const BVHParams& params_, const vector<Object*>& objects_) 00453 : BVH(params_, objects_) 00454 { 00455 } 00456 00457 void RegularBVH::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf) 00458 { 00459 if(leaf->num_triangles() == 1 && pack.prim_index[leaf->m_lo] == -1) 00460 /* object */ 00461 pack_node(e.idx, leaf->m_bounds, leaf->m_bounds, ~(leaf->m_lo), 0, leaf->m_visibility, leaf->m_visibility); 00462 else 00463 /* triangle */ 00464 pack_node(e.idx, leaf->m_bounds, leaf->m_bounds, leaf->m_lo, leaf->m_hi, leaf->m_visibility, leaf->m_visibility); 00465 } 00466 00467 void RegularBVH::pack_inner(const BVHStackEntry& e, const BVHStackEntry& e0, const BVHStackEntry& e1) 00468 { 00469 pack_node(e.idx, e0.node->m_bounds, e1.node->m_bounds, e0.encodeIdx(), e1.encodeIdx(), e0.node->m_visibility, e1.node->m_visibility); 00470 } 00471 00472 void RegularBVH::pack_node(int idx, const BoundBox& b0, const BoundBox& b1, int c0, int c1, uint visibility0, uint visibility1) 00473 { 00474 int4 data[BVH_NODE_SIZE] = 00475 { 00476 make_int4(__float_as_int(b0.min.x), __float_as_int(b0.max.x), __float_as_int(b0.min.y), __float_as_int(b0.max.y)), 00477 make_int4(__float_as_int(b1.min.x), __float_as_int(b1.max.x), __float_as_int(b1.min.y), __float_as_int(b1.max.y)), 00478 make_int4(__float_as_int(b0.min.z), __float_as_int(b0.max.z), __float_as_int(b1.min.z), __float_as_int(b1.max.z)), 00479 make_int4(c0, c1, visibility0, visibility1) 00480 }; 00481 00482 memcpy(&pack.nodes[idx * BVH_NODE_SIZE], data, sizeof(int4)*BVH_NODE_SIZE); 00483 } 00484 00485 void RegularBVH::pack_nodes(const array<int>& prims, const BVHNode *root) 00486 { 00487 size_t node_size = root->getSubtreeSize(BVH_STAT_NODE_COUNT); 00488 00489 /* resize arrays */ 00490 pack.nodes.clear(); 00491 pack.is_leaf.clear(); 00492 pack.is_leaf.resize(node_size); 00493 00494 /* for top level BVH, first merge existing BVH's so we know the offsets */ 00495 if(params.top_level) 00496 pack_instances(node_size*BVH_NODE_SIZE); 00497 else 00498 pack.nodes.resize(node_size*BVH_NODE_SIZE); 00499 00500 int nextNodeIdx = 0; 00501 00502 vector<BVHStackEntry> stack; 00503 stack.push_back(BVHStackEntry(root, nextNodeIdx++)); 00504 00505 while(stack.size()) { 00506 BVHStackEntry e = stack.back(); 00507 stack.pop_back(); 00508 00509 pack.is_leaf[e.idx] = e.node->is_leaf(); 00510 00511 if(e.node->is_leaf()) { 00512 /* leaf node */ 00513 const LeafNode* leaf = reinterpret_cast<const LeafNode*>(e.node); 00514 pack_leaf(e, leaf); 00515 } 00516 else { 00517 /* innner node */ 00518 stack.push_back(BVHStackEntry(e.node->get_child(0), nextNodeIdx++)); 00519 stack.push_back(BVHStackEntry(e.node->get_child(1), nextNodeIdx++)); 00520 00521 pack_inner(e, stack[stack.size()-2], stack[stack.size()-1]); 00522 } 00523 } 00524 00525 /* root index to start traversal at, to handle case of single leaf node */ 00526 pack.root_index = (pack.is_leaf[0])? -1: 0; 00527 } 00528 00529 void RegularBVH::refit_nodes() 00530 { 00531 assert(!params.top_level); 00532 00533 BoundBox bbox; 00534 uint visibility = 0; 00535 refit_node(0, (pack.is_leaf[0])? true: false, bbox, visibility); 00536 } 00537 00538 void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility) 00539 { 00540 int4 *data = &pack.nodes[idx*4]; 00541 00542 int c0 = data[3].x; 00543 int c1 = data[3].y; 00544 00545 if(leaf) { 00546 /* refit leaf node */ 00547 for(int tri = c0; tri < c1; tri++) { 00548 int tidx = pack.prim_index[tri]; 00549 int tob = pack.prim_object[tri]; 00550 Object *ob = objects[tob]; 00551 00552 if(tidx == -1) { 00553 /* object instance */ 00554 bbox.grow(ob->bounds); 00555 } 00556 else { 00557 /* triangles */ 00558 const Mesh *mesh = ob->mesh; 00559 int tri_offset = (params.top_level)? mesh->tri_offset: 0; 00560 const int *vidx = mesh->triangles[tidx - tri_offset].v; 00561 const float3 *vpos = &mesh->verts[0]; 00562 00563 bbox.grow(vpos[vidx[0]]); 00564 bbox.grow(vpos[vidx[1]]); 00565 bbox.grow(vpos[vidx[2]]); 00566 } 00567 00568 visibility |= ob->visibility; 00569 } 00570 00571 pack_node(idx, bbox, bbox, c0, c1, visibility, visibility); 00572 } 00573 else { 00574 /* refit inner node, set bbox from children */ 00575 BoundBox bbox0, bbox1; 00576 uint visibility0 = 0, visibility1 = 0; 00577 00578 refit_node((c0 < 0)? -c0-1: c0, (c0 < 0), bbox0, visibility0); 00579 refit_node((c1 < 0)? -c1-1: c1, (c1 < 0), bbox1, visibility1); 00580 00581 pack_node(idx, bbox0, bbox1, c0, c1, visibility0, visibility1); 00582 00583 bbox.grow(bbox0); 00584 bbox.grow(bbox1); 00585 visibility = visibility0|visibility1; 00586 } 00587 } 00588 00589 /* QBVH */ 00590 00591 QBVH::QBVH(const BVHParams& params_, const vector<Object*>& objects_) 00592 : BVH(params_, objects_) 00593 { 00594 params.use_qbvh = true; 00595 00596 /* todo: use visibility */ 00597 } 00598 00599 void QBVH::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf) 00600 { 00601 float4 data[BVH_QNODE_SIZE]; 00602 00603 memset(data, 0, sizeof(data)); 00604 00605 if(leaf->num_triangles() == 1 && pack.prim_index[leaf->m_lo] == -1) { 00606 /* object */ 00607 data[6].x = __int_as_float(~(leaf->m_lo)); 00608 data[6].y = __int_as_float(0); 00609 } 00610 else { 00611 /* triangle */ 00612 data[6].x = __int_as_float(leaf->m_lo); 00613 data[6].y = __int_as_float(leaf->m_hi); 00614 } 00615 00616 memcpy(&pack.nodes[e.idx * BVH_QNODE_SIZE], data, sizeof(float4)*BVH_QNODE_SIZE); 00617 } 00618 00619 void QBVH::pack_inner(const BVHStackEntry& e, const BVHStackEntry *en, int num) 00620 { 00621 float4 data[BVH_QNODE_SIZE]; 00622 00623 for(int i = 0; i < num; i++) { 00624 float3 bb_min = en[i].node->m_bounds.min; 00625 float3 bb_max = en[i].node->m_bounds.max; 00626 00627 data[0][i] = bb_min.x; 00628 data[1][i] = bb_max.x; 00629 data[2][i] = bb_min.y; 00630 data[3][i] = bb_max.y; 00631 data[4][i] = bb_min.z; 00632 data[5][i] = bb_max.z; 00633 00634 data[6][i] = __int_as_float(en[i].encodeIdx()); 00635 data[7][i] = 0.0f; 00636 } 00637 00638 for(int i = num; i < 4; i++) { 00639 data[0][i] = 0.0f; 00640 data[1][i] = 0.0f; 00641 data[2][i] = 0.0f; 00642 00643 data[3][i] = 0.0f; 00644 data[4][i] = 0.0f; 00645 data[5][i] = 0.0f; 00646 00647 data[6][i] = __int_as_float(0); 00648 data[7][i] = 0.0f; 00649 } 00650 00651 memcpy(&pack.nodes[e.idx * BVH_QNODE_SIZE], data, sizeof(float4)*BVH_QNODE_SIZE); 00652 } 00653 00654 /* Quad SIMD Nodes */ 00655 00656 void QBVH::pack_nodes(const array<int>& prims, const BVHNode *root) 00657 { 00658 size_t node_size = root->getSubtreeSize(BVH_STAT_NODE_COUNT); 00659 00660 /* resize arrays */ 00661 pack.nodes.clear(); 00662 pack.is_leaf.clear(); 00663 pack.is_leaf.resize(node_size); 00664 00665 /* for top level BVH, first merge existing BVH's so we know the offsets */ 00666 if(params.top_level) 00667 pack_instances(node_size*BVH_QNODE_SIZE); 00668 else 00669 pack.nodes.resize(node_size*BVH_QNODE_SIZE); 00670 00671 int nextNodeIdx = 0; 00672 00673 vector<BVHStackEntry> stack; 00674 stack.push_back(BVHStackEntry(root, nextNodeIdx++)); 00675 00676 while(stack.size()) { 00677 BVHStackEntry e = stack.back(); 00678 stack.pop_back(); 00679 00680 pack.is_leaf[e.idx] = e.node->is_leaf(); 00681 00682 if(e.node->is_leaf()) { 00683 /* leaf node */ 00684 const LeafNode* leaf = reinterpret_cast<const LeafNode*>(e.node); 00685 pack_leaf(e, leaf); 00686 } 00687 else { 00688 /* inner node */ 00689 const BVHNode *node = e.node; 00690 const BVHNode *node0 = node->get_child(0); 00691 const BVHNode *node1 = node->get_child(1); 00692 00693 /* collect nodes */ 00694 const BVHNode *nodes[4]; 00695 int numnodes = 0; 00696 00697 if(node0->is_leaf()) { 00698 nodes[numnodes++] = node0; 00699 } 00700 else { 00701 nodes[numnodes++] = node0->get_child(0); 00702 nodes[numnodes++] = node0->get_child(1); 00703 } 00704 00705 if(node1->is_leaf()) { 00706 nodes[numnodes++] = node1; 00707 } 00708 else { 00709 nodes[numnodes++] = node1->get_child(0); 00710 nodes[numnodes++] = node1->get_child(1); 00711 } 00712 00713 /* push entries on the stack */ 00714 for(int i = 0; i < numnodes; i++) 00715 stack.push_back(BVHStackEntry(nodes[i], nextNodeIdx++)); 00716 00717 /* set node */ 00718 pack_inner(e, &stack[stack.size()-numnodes], numnodes); 00719 } 00720 } 00721 00722 /* root index to start traversal at, to handle case of single leaf node */ 00723 pack.root_index = (pack.is_leaf[0])? -1: 0; 00724 } 00725 00726 void QBVH::refit_nodes() 00727 { 00728 assert(0); /* todo */ 00729 } 00730 00731 CCL_NAMESPACE_END 00732