diff options
Diffstat (limited to 'intern/cycles/bvh/bvh_unaligned.cpp')
-rw-r--r-- | intern/cycles/bvh/bvh_unaligned.cpp | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/intern/cycles/bvh/bvh_unaligned.cpp b/intern/cycles/bvh/bvh_unaligned.cpp new file mode 100644 index 00000000000..a876c670914 --- /dev/null +++ b/intern/cycles/bvh/bvh_unaligned.cpp @@ -0,0 +1,178 @@ +/* + * Copyright 2011-2016 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include "bvh_unaligned.h" + +#include "mesh.h" +#include "object.h" + +#include "bvh_binning.h" +#include "bvh_params.h" + +#include "util_boundbox.h" +#include "util_debug.h" +#include "util_transform.h" + +CCL_NAMESPACE_BEGIN + + +BVHUnaligned::BVHUnaligned(const vector<Object*>& objects) + : objects_(objects) +{ +} + +Transform BVHUnaligned::compute_aligned_space( + const BVHObjectBinning& range, + const BVHReference *references) const +{ + for(int i = range.start(); i < range.end(); ++i) { + const BVHReference& ref = references[i]; + Transform aligned_space; + /* Use first primitive which defines correct direction to define + * the orientation space. + */ + if(compute_aligned_space(ref, &aligned_space)) { + return aligned_space; + } + } + return transform_identity(); +} + +Transform BVHUnaligned::compute_aligned_space( + const BVHRange& range, + const BVHReference *references) const +{ + for(int i = range.start(); i < range.end(); ++i) { + const BVHReference& ref = references[i]; + Transform aligned_space; + /* Use first primitive which defines correct direction to define + * the orientation space. + */ + if(compute_aligned_space(ref, &aligned_space)) { + return aligned_space; + } + } + return transform_identity(); +} + +bool BVHUnaligned::compute_aligned_space(const BVHReference& ref, + Transform *aligned_space) const +{ + const Object *object = objects_[ref.prim_object()]; + const int packed_type = ref.prim_type(); + const int type = (packed_type & PRIMITIVE_ALL); + if(type & PRIMITIVE_CURVE) { + const int curve_index = ref.prim_index(); + const int segment = PRIMITIVE_UNPACK_SEGMENT(packed_type); + const Mesh *mesh = object->mesh; + const Mesh::Curve& curve = mesh->get_curve(curve_index); + const int key = curve.first_key + segment; + const float3 v1 = mesh->curve_keys[key], + v2 = mesh->curve_keys[key + 1]; + float length; + const float3 axis = normalize_len(v2 - v1, &length); + if(length > 1e-6f) { + *aligned_space = make_transform_frame(axis); + return true; + } + } + *aligned_space = transform_identity(); + return false; +} + +BoundBox BVHUnaligned::compute_aligned_prim_boundbox( + const BVHReference& prim, + const Transform& aligned_space) const +{ + BoundBox bounds = BoundBox::empty; + const Object *object = objects_[prim.prim_object()]; + const int packed_type = prim.prim_type(); + const int type = (packed_type & PRIMITIVE_ALL); + if(type & PRIMITIVE_CURVE) { + const int curve_index = prim.prim_index(); + const int segment = PRIMITIVE_UNPACK_SEGMENT(packed_type); + const Mesh *mesh = object->mesh; + const Mesh::Curve& curve = mesh->get_curve(curve_index); + curve.bounds_grow(segment, + &mesh->curve_keys[0], + &mesh->curve_radius[0], + aligned_space, + bounds); + } + else { + bounds = prim.bounds().transformed(&aligned_space); + } + return bounds; +} + +BoundBox BVHUnaligned::compute_aligned_boundbox( + const BVHObjectBinning& range, + const BVHReference *references, + const Transform& aligned_space, + BoundBox *cent_bounds) const +{ + BoundBox bounds = BoundBox::empty; + if(cent_bounds != NULL) { + *cent_bounds = BoundBox::empty; + } + for(int i = range.start(); i < range.end(); ++i) { + const BVHReference& ref = references[i]; + BoundBox ref_bounds = compute_aligned_prim_boundbox(ref, aligned_space); + bounds.grow(ref_bounds); + if(cent_bounds != NULL) { + cent_bounds->grow(ref_bounds.center2()); + } + } + return bounds; +} + +BoundBox BVHUnaligned::compute_aligned_boundbox( + const BVHRange& range, + const BVHReference *references, + const Transform& aligned_space, + BoundBox *cent_bounds) const +{ + BoundBox bounds = BoundBox::empty; + if(cent_bounds != NULL) { + *cent_bounds = BoundBox::empty; + } + for(int i = range.start(); i < range.end(); ++i) { + const BVHReference& ref = references[i]; + BoundBox ref_bounds = compute_aligned_prim_boundbox(ref, aligned_space); + bounds.grow(ref_bounds); + if(cent_bounds != NULL) { + cent_bounds->grow(ref_bounds.center2()); + } + } + return bounds; +} + +Transform BVHUnaligned::compute_node_transform( + const BoundBox& bounds, + const Transform& aligned_space) +{ + Transform space = aligned_space; + space.x.w -= bounds.min.x; + space.y.w -= bounds.min.y; + space.z.w -= bounds.min.z; + float3 dim = bounds.max - bounds.min; + return transform_scale(1.0f / max(1e-18f, dim.x), + 1.0f / max(1e-18f, dim.y), + 1.0f / max(1e-18f, dim.z)) * space; +} + +CCL_NAMESPACE_END |