void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, int i) { for(uint j = 0; j < mesh->triangles.size(); j++) { Mesh::Triangle t = mesh->triangles[j]; BoundBox bounds = BoundBox::empty; for(int k = 0; k < 3; k++) { float3 co = mesh->verts[t.v[k]]; bounds.grow(co); } if(bounds.valid()) { references.push_back(BVHReference(bounds, j, i, ~0)); root.grow(bounds); center.grow(bounds.center2()); } } for(uint j = 0; j < mesh->curves.size(); j++) { Mesh::Curve curve = mesh->curves[j]; for(int k = 0; k < curve.num_keys - 1; k++) { BoundBox bounds = BoundBox::empty; float3 co[4]; co[0] = mesh->curve_keys[max(curve.first_key + k - 1,curve.first_key)].co; co[1] = mesh->curve_keys[curve.first_key + k].co; co[2] = mesh->curve_keys[curve.first_key + k + 1].co; co[3] = mesh->curve_keys[min(curve.first_key + k + 2, curve.first_key + curve.num_keys - 1)].co; float3 lower; float3 upper; curvebounds(&lower.x, &upper.x, co, 0); curvebounds(&lower.y, &upper.y, co, 1); curvebounds(&lower.z, &upper.z, co, 2); float mr = max(mesh->curve_keys[curve.first_key + k].radius, mesh->curve_keys[curve.first_key + k + 1].radius); bounds.grow(lower, mr); bounds.grow(upper, mr); if(bounds.valid()) { references.push_back(BVHReference(bounds, j, i, k)); root.grow(bounds); center.grow(bounds.center2()); } } } }
void BVHBuild::add_references(BVHRange& root) { /* reserve space for references */ size_t num_alloc_references = 0; foreach(Object *ob, objects) { if(params.top_level) { if(!ob->mesh->is_instanced()) { num_alloc_references += ob->mesh->triangles.size(); num_alloc_references += count_curve_segments(ob->mesh); } else num_alloc_references++; } else { num_alloc_references += ob->mesh->triangles.size(); num_alloc_references += count_curve_segments(ob->mesh); } } references.reserve(num_alloc_references); /* add references from objects */ BoundBox bounds = BoundBox::empty, center = BoundBox::empty; int i = 0; foreach(Object *ob, objects) { if(params.top_level) { if(!ob->mesh->is_instanced()) add_reference_mesh(bounds, center, ob->mesh, i); else add_reference_object(bounds, center, ob, i); } else add_reference_mesh(bounds, center, ob->mesh, i); i++; if(progress.get_cancel()) return; } /* happens mostly on empty meshes */ if(!bounds.valid()) bounds.grow(make_float3(0.0f, 0.0f, 0.0f)); root = BVHRange(bounds, center, 0, references.size()); }
void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, int i) { Attribute *attr_mP = NULL; if(mesh->has_motion_blur()) attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); for(uint j = 0; j < mesh->triangles.size(); j++) { Mesh::Triangle t = mesh->triangles[j]; BoundBox bounds = BoundBox::empty; PrimitiveType type = PRIMITIVE_TRIANGLE; t.bounds_grow(&mesh->verts[0], bounds); /* motion triangles */ if(attr_mP) { size_t mesh_size = mesh->verts.size(); size_t steps = mesh->motion_steps - 1; float3 *vert_steps = attr_mP->data_float3(); for(size_t i = 0; i < steps; i++) t.bounds_grow(vert_steps + i*mesh_size, bounds); type = PRIMITIVE_MOTION_TRIANGLE; } if(bounds.valid()) { references.push_back(BVHReference(bounds, j, i, type)); root.grow(bounds); center.grow(bounds.center2()); } } Attribute *curve_attr_mP = NULL; if(mesh->has_motion_blur()) curve_attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); for(uint j = 0; j < mesh->curves.size(); j++) { Mesh::Curve curve = mesh->curves[j]; PrimitiveType type = PRIMITIVE_CURVE; for(int k = 0; k < curve.num_keys - 1; k++) { BoundBox bounds = BoundBox::empty; curve.bounds_grow(k, &mesh->curve_keys[0], bounds); /* motion curve */ if(curve_attr_mP) { size_t mesh_size = mesh->curve_keys.size(); size_t steps = mesh->motion_steps - 1; float4 *key_steps = curve_attr_mP->data_float4(); for(size_t i = 0; i < steps; i++) curve.bounds_grow(k, key_steps + i*mesh_size, bounds); type = PRIMITIVE_MOTION_CURVE; } if(bounds.valid()) { int packed_type = PRIMITIVE_PACK_SEGMENT(type, k); references.push_back(BVHReference(bounds, j, i, packed_type)); root.grow(bounds); center.grow(bounds.center2()); } } } }