From ac25e8919308aa0101870491ec0eb99687d9ca9a Mon Sep 17 00:00:00 2001 From: Fabio Pellacini <fabio.pellacini@gmail.com> Date: Sun, 7 Aug 2022 06:19:20 +0200 Subject: [PATCH 1/9] renaming embree --- libs/yocto/yocto_bvh.cpp | 70 ++++++++++++++++----------------- libs/yocto/yocto_bvh.h | 80 +++++++++++++++++++++++++++++++------- libs/yocto/yocto_trace.cpp | 13 +++---- libs/yocto/yocto_trace.h | 4 +- 4 files changed, 109 insertions(+), 58 deletions(-) diff --git a/libs/yocto/yocto_bvh.cpp b/libs/yocto/yocto_bvh.cpp index 2fc5ddb17..03cb9cbad 100644 --- a/libs/yocto/yocto_bvh.cpp +++ b/libs/yocto/yocto_bvh.cpp @@ -878,18 +878,17 @@ static RTCDevice embree_device() { } // Clear Embree bvh -void clear_embree_bvh(void* embree_bvh) { - if (embree_bvh) rtcReleaseScene((RTCScene)embree_bvh); +void clear_ebvh(void* ebvh) { + if (ebvh) rtcReleaseScene((RTCScene)ebvh); } // Build the bvh acceleration structure. -shape_embree_bvh make_shape_embree_bvh( - const shape_data& shape, bool highquality) { - auto bvh = shape_embree_bvh{}; - auto edevice = embree_device(); - bvh.embree_bvh = unique_ptr<void, void (*)(void*)>{ - rtcNewScene(edevice), &clear_embree_bvh}; - auto escene = (RTCScene)bvh.embree_bvh.get(); +shape_ebvh make_shape_ebvh(const shape_data& shape, bool highquality) { + auto bvh = shape_ebvh{}; + auto edevice = embree_device(); + bvh.bvh = unique_ptr<void, void (*)(void*)>{ + rtcNewScene(edevice), &clear_ebvh}; + auto escene = (RTCScene)bvh.bvh.get(); if (highquality) { rtcSetSceneBuildQuality(escene, RTC_BUILD_QUALITY_HIGH); } else { @@ -967,28 +966,28 @@ shape_embree_bvh make_shape_embree_bvh( return bvh; } -scene_embree_bvh make_scene_embree_bvh( +scene_ebvh make_scene_ebvh( const scene_data& scene, bool highquality, bool noparallel) { // scene bvh - auto bvh = scene_embree_bvh{}; + auto bvh = scene_ebvh{}; // shape bvhs bvh.shapes.resize(scene.shapes.size()); if (noparallel) { for (auto idx : range(scene.shapes.size())) { - bvh.shapes[idx] = make_shape_embree_bvh(scene.shapes[idx], highquality); + bvh.shapes[idx] = make_shape_ebvh(scene.shapes[idx], highquality); } } else { parallel_for(scene.shapes.size(), [&](size_t idx) { - bvh.shapes[idx] = make_shape_embree_bvh(scene.shapes[idx], highquality); + bvh.shapes[idx] = make_shape_ebvh(scene.shapes[idx], highquality); }); } // scene bvh - auto edevice = embree_device(); - bvh.embree_bvh = unique_ptr<void, void (*)(void*)>{ - rtcNewScene(edevice), &clear_embree_bvh}; - auto escene = (RTCScene)bvh.embree_bvh.get(); + auto edevice = embree_device(); + bvh.bvh = unique_ptr<void, void (*)(void*)>{ + rtcNewScene(edevice), &clear_ebvh}; + auto escene = (RTCScene)bvh.bvh.get(); if (highquality) { rtcSetSceneBuildQuality(escene, RTC_BUILD_QUALITY_HIGH); } else { @@ -999,7 +998,7 @@ scene_embree_bvh make_scene_embree_bvh( auto& instance = scene.instances[instance_id]; auto& sbvh = bvh.shapes[instance.shape]; auto egeometry = rtcNewGeometry(edevice, RTC_GEOMETRY_TYPE_INSTANCE); - rtcSetGeometryInstancedScene(egeometry, (RTCScene)sbvh.embree_bvh.get()); + rtcSetGeometryInstancedScene(egeometry, (RTCScene)sbvh.bvh.get()); rtcSetGeometryTransform( egeometry, 0, RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR, &instance.frame); rtcCommitGeometry(egeometry); @@ -1011,18 +1010,18 @@ scene_embree_bvh make_scene_embree_bvh( } // Refit bvh data -void update_shape_embree_bvh(shape_embree_bvh& bvh, const shape_data& shape) { +void update_shape_ebvh(shape_ebvh& bvh, const shape_data& shape) { throw embree_error{"feature not supported"}; } -void update_scene_embree_bvh(scene_embree_bvh& bvh, const scene_data& scene, +void update_scene_ebvh(scene_ebvh& bvh, const scene_data& scene, const vector<int>& updated_instances, const vector<int>& updated_shapes) { // scene bvh - auto escene = (RTCScene)bvh.embree_bvh.get(); + auto escene = (RTCScene)bvh.bvh.get(); for (auto instance_id : updated_instances) { auto& instance = scene.instances[instance_id]; auto& sbvh = bvh.shapes[instance.shape]; auto embree_geom = rtcGetGeometry(escene, instance_id); - rtcSetGeometryInstancedScene(embree_geom, (RTCScene)sbvh.embree_bvh.get()); + rtcSetGeometryInstancedScene(embree_geom, (RTCScene)sbvh.bvh.get()); rtcSetGeometryTransform( embree_geom, 0, RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR, &instance.frame); rtcCommitGeometry(embree_geom); @@ -1033,7 +1032,7 @@ void update_scene_embree_bvh(scene_embree_bvh& bvh, const scene_data& scene, // Intersect ray with a bvh returning either the first or any intersection // depending on `find_any`. Returns the ray distance , the instance id, // the shape element index and the element barycentric coordinates. -shape_intersection intersect_shape_embree_bvh(const shape_embree_bvh& bvh, +shape_intersection intersect_shape_ebvh(const shape_ebvh& bvh, const shape_data& shape, const ray3f& ray, bool find_any) { RTCRayHit embree_ray; embree_ray.ray.org_x = ray.o.x; @@ -1051,7 +1050,7 @@ shape_intersection intersect_shape_embree_bvh(const shape_embree_bvh& bvh, embree_ray.hit.instID[0] = RTC_INVALID_GEOMETRY_ID; RTCIntersectContext embree_ctx; rtcInitIntersectContext(&embree_ctx); - rtcIntersect1((RTCScene)bvh.embree_bvh.get(), &embree_ctx, &embree_ray); + rtcIntersect1((RTCScene)bvh.bvh.get(), &embree_ctx, &embree_ray); if (embree_ray.hit.geomID == RTC_INVALID_GEOMETRY_ID) return {}; auto element = (int)embree_ray.hit.primID; auto uv = vec2f{embree_ray.hit.u, embree_ray.hit.v}; @@ -1059,7 +1058,7 @@ shape_intersection intersect_shape_embree_bvh(const shape_embree_bvh& bvh, return {element, uv, distance, true}; } -scene_intersection intersect_scene_embree_bvh(const scene_embree_bvh& bvh, +scene_intersection intersect_scene_ebvh(const scene_ebvh& bvh, const scene_data& scene, const ray3f& ray, bool find_any) { RTCRayHit embree_ray; embree_ray.ray.org_x = ray.o.x; @@ -1077,7 +1076,7 @@ scene_intersection intersect_scene_embree_bvh(const scene_embree_bvh& bvh, embree_ray.hit.instID[0] = RTC_INVALID_GEOMETRY_ID; RTCIntersectContext embree_ctx; rtcInitIntersectContext(&embree_ctx); - rtcIntersect1((RTCScene)bvh.embree_bvh.get(), &embree_ctx, &embree_ray); + rtcIntersect1((RTCScene)bvh.bvh.get(), &embree_ctx, &embree_ray); if (embree_ray.hit.geomID == RTC_INVALID_GEOMETRY_ID) return {}; auto instance = (int)embree_ray.hit.instID[0]; auto element = (int)embree_ray.hit.primID; @@ -1086,11 +1085,11 @@ scene_intersection intersect_scene_embree_bvh(const scene_embree_bvh& bvh, return {instance, element, uv, distance, true}; } -scene_intersection intersect_instance_embree_bvh(const scene_embree_bvh& bvh, +scene_intersection intersect_instance_ebvh(const scene_ebvh& bvh, const scene_data& scene, int instance_, const ray3f& ray, bool find_any) { auto& instance = scene.instances[instance_]; auto inv_ray = transform_ray(inverse(instance.frame, true), ray); - auto intersection = intersect_shape_embree_bvh(bvh.shapes[instance.shape], + auto intersection = intersect_shape_ebvh(bvh.shapes[instance.shape], scene.shapes[instance.shape], inv_ray, find_any); if (!intersection.hit) return {}; return {instance_, intersection.element, intersection.uv, @@ -1103,34 +1102,33 @@ scene_intersection intersect_instance_embree_bvh(const scene_embree_bvh& bvh, bool embree_supported() { return false; } // Not implemented -shape_embree_bvh make_shape_embree_bvh( - const shape_data& shape, bool highquality) { +shape_ebvh make_shape_ebvh(const shape_data& shape, bool highquality) { throw embree_error{"Embree not available"}; } -scene_embree_bvh make_scene_embree_bvh( +scene_ebvh make_scene_ebvh( const scene_data& scene, bool highquality, bool noparallel) { throw embree_error{"Embree not available"}; } // Not implemented -void update_shape_embree_bvh(shape_embree_bvh& bvh, const shape_data& shape) { +void update_shape_ebvh(shape_ebvh& bvh, const shape_data& shape) { throw embree_error{"Embree not available"}; } -void update_scene_embree_bvh(scene_embree_bvh& bvh, const scene_data& scene, +void update_scene_ebvh(scene_ebvh& bvh, const scene_data& scene, const vector<int>& updated_instances, const vector<int>& updated_shapes) { throw embree_error{"Embree not available"}; } // Not implemented -shape_intersection intersect_shape_embree_bvh(const shape_embree_bvh& bvh, +shape_intersection intersect_shape_ebvh(const shape_ebvh& bvh, const shape_data& shape, const ray3f& ray, bool find_any) { throw embree_error{"Embree not available"}; } -scene_intersection intersect_scene_embree_bvh(const scene_embree_bvh& bvh, +scene_intersection intersect_scene_ebvh(const scene_ebvh& bvh, const scene_data& scene, const ray3f& ray, bool find_any) { throw embree_error{"Embree not available"}; } -scene_intersection intersect_instance_embree_bvh(const scene_embree_bvh& bvh, +scene_intersection intersect_instance_ebvh(const scene_ebvh& bvh, const scene_data& scene, int instance, const ray3f& ray, bool find_any) { throw embree_error{"Embree not available"}; } diff --git a/libs/yocto/yocto_bvh.h b/libs/yocto/yocto_bvh.h index 52898f2d2..b3aa01143 100644 --- a/libs/yocto/yocto_bvh.h +++ b/libs/yocto/yocto_bvh.h @@ -150,39 +150,41 @@ scene_intersection overlap_scene_bvh(const scene_bvh& bvh, // ----------------------------------------------------------------------------- namespace yocto { +// Intel Embree tree +using ebvh_tree = unique_ptr<void, void (*)(void*)>; + // Wrapper for Intel Embree. -struct shape_embree_bvh { - unique_ptr<void, void (*)(void*)> embree_bvh = {nullptr, nullptr}; // embree +struct shape_ebvh { + unique_ptr<void, void (*)(void*)> bvh = {nullptr, nullptr}; // embree }; // Wrapper for Intel Embree. -struct scene_embree_bvh { - vector<shape_embree_bvh> shapes = {}; // shapes - unique_ptr<void, void (*)(void*)> embree_bvh = {nullptr, nullptr}; // embree +struct scene_ebvh { + vector<shape_ebvh> shapes = {}; // shapes + unique_ptr<void, void (*)(void*)> bvh = {nullptr, nullptr}; // embree }; // Check if embree is supported bool embree_supported(); // Build the bvh acceleration structure. -shape_embree_bvh make_shape_embree_bvh( - const shape_data& shape, bool highquality = false); -scene_embree_bvh make_scene_embree_bvh( +shape_ebvh make_shape_ebvh(const shape_data& shape, bool highquality = false); +scene_ebvh make_scene_ebvh( const scene_data& scene, bool highquality = false, bool noparallel = false); // Refit bvh data -void update_shape_embree_bvh(shape_embree_bvh& bvh, const shape_data& shape); -void update_scene_embree_bvh(scene_embree_bvh& bvh, const scene_data& scene, +void update_shape_ebvh(shape_ebvh& bvh, const shape_data& shape); +void update_scene_ebvh(scene_ebvh& bvh, const scene_data& scene, const vector<int>& updated_instances, const vector<int>& updated_shapes); // Intersect ray with a bvh returning either the first or any intersection // depending on `find_any`. Returns the ray distance , the instance id, // the shape element index and the element barycentric coordinates. -shape_intersection intersect_shape_embree_bvh(const shape_embree_bvh& bvh, +shape_intersection intersect_shape_ebvh(const shape_ebvh& bvh, const shape_data& shape, const ray3f& ray, bool find_any = false); -scene_intersection intersect_scene_embree_bvh(const scene_embree_bvh& bvh, +scene_intersection intersect_scene_ebvh(const scene_ebvh& bvh, const scene_data& scene, const ray3f& ray, bool find_any = false); -scene_intersection intersect_instance_embree_bvh(const scene_embree_bvh& bvh, +scene_intersection intersect_instance_ebvh(const scene_ebvh& bvh, const scene_data& scene, int instance, const ray3f& ray, bool find_any = false); @@ -272,4 +274,56 @@ using bvh_scene [[deprecated]] = scene_bvh; } // namespace yocto +// ----------------------------------------------------------------------------- +// EMBREE BACKWARD COMPATIBILITY +// ----------------------------------------------------------------------------- +namespace yocto { + +// backward compatibility +using shape_embree_bvh = shape_ebvh; +using scene_embree_bvh = scene_ebvh; + +// Build the bvh acceleration structure. +[[deprecated]] inline shape_embree_bvh make_shape_embree_bvh( + const shape_data& shape, bool highquality = false) { + return make_shape_ebvh(shape, highquality); +} +[[deprecated]] inline scene_embree_bvh make_scene_embree_bvh( + const scene_data& scene, bool highquality = false, + bool noparallel = false) { + return make_scene_ebvh(scene, highquality, noparallel); +} + +// Refit bvh data +[[deprecated]] inline void update_shape_embree_bvh( + shape_embree_bvh& bvh, const shape_data& shape) { + return update_shape_ebvh(bvh, shape); +} +[[deprecated]] inline void update_scene_embree_bvh(scene_ebvh& bvh, + const scene_data& scene, const vector<int>& updated_instances, + const vector<int>& updated_shapes) { + return update_scene_ebvh(bvh, scene, updated_instances, updated_shapes); +} + +// Intersect ray with a bvh returning either the first or any intersection +// depending on `find_any`. Returns the ray distance , the instance id, +// the shape element index and the element barycentric coordinates. +[[deprecated]] inline shape_intersection intersect_shape_embree_bvh( + const shape_ebvh& bvh, const shape_data& shape, const ray3f& ray, + bool find_any = false) { + return intersect_shape_ebvh(bvh, shape, ray, find_any); +} +[[deprecated]] inline scene_intersection intersect_scene_embree_bvh( + const scene_ebvh& bvh, const scene_data& scene, const ray3f& ray, + bool find_any = false) { + return intersect_scene_ebvh(bvh, scene, ray, find_any); +} +[[deprecated]] inline scene_intersection intersect_instance_embree_bvh( + const scene_ebvh& bvh, const scene_data& scene, int instance, + const ray3f& ray, bool find_any = false) { + return intersect_instance_ebvh(bvh, scene, instance, ray, find_any); +} + +} // namespace yocto + #endif diff --git a/libs/yocto/yocto_trace.cpp b/libs/yocto/yocto_trace.cpp index dfc72c9f5..fb0b8501f 100644 --- a/libs/yocto/yocto_trace.cpp +++ b/libs/yocto/yocto_trace.cpp @@ -87,8 +87,8 @@ namespace yocto { // Build the Bvh acceleration structure. trace_bvh make_trace_bvh(const scene_data& scene, const trace_params& params) { if (params.embreebvh && embree_supported()) { - return {{}, - make_scene_embree_bvh(scene, params.highqualitybvh, params.noparallel)}; + return { + {}, make_scene_ebvh(scene, params.highqualitybvh, params.noparallel)}; } else { return { make_scene_bvh(scene, params.highqualitybvh, params.noparallel), {}}; @@ -98,8 +98,8 @@ trace_bvh make_trace_bvh(const scene_data& scene, const trace_params& params) { // Ray-intersection shortcuts static scene_intersection intersect_scene(const trace_bvh& bvh, const scene_data& scene, const ray3f& ray, bool find_any = false) { - if (bvh.embree.embree_bvh) { - return intersect_scene_embree_bvh(bvh.embree, scene, ray, find_any); + if (bvh.ebvh.bvh) { + return intersect_scene_ebvh(bvh.ebvh, scene, ray, find_any); } else { return intersect_scene_bvh(bvh.bvh, scene, ray, find_any); } @@ -107,9 +107,8 @@ static scene_intersection intersect_scene(const trace_bvh& bvh, static scene_intersection intersect_instance(const trace_bvh& bvh, const scene_data& scene, int instance, const ray3f& ray, bool find_any = false) { - if (bvh.embree.embree_bvh) { - return intersect_instance_embree_bvh( - bvh.embree, scene, instance, ray, find_any); + if (bvh.ebvh.bvh) { + return intersect_instance_ebvh(bvh.ebvh, scene, instance, ray, find_any); } else { return intersect_instance_bvh(bvh.bvh, scene, instance, ray, find_any); } diff --git a/libs/yocto/yocto_trace.h b/libs/yocto/yocto_trace.h index 283b1e284..10529c660 100644 --- a/libs/yocto/yocto_trace.h +++ b/libs/yocto/yocto_trace.h @@ -135,8 +135,8 @@ struct trace_lights { // Trace Bvh, a wrapper of a Yocto/Bvh and an Embree one struct trace_bvh { - scene_bvh bvh = {}; - scene_embree_bvh embree = {}; + scene_bvh bvh = {}; + scene_ebvh ebvh = {}; }; // Check is a sampler requires lights From 9645a283f443c50aecac0b4c6f03bf1d8344d457 Mon Sep 17 00:00:00 2001 From: Fabio Pellacini <fabio.pellacini@gmail.com> Date: Sun, 7 Aug 2022 09:44:52 +0200 Subject: [PATCH 2/9] updated --- libs/yocto/yocto_bvh.h | 12 ------------ libs/yocto/yocto_shape.h | 27 ++++++++++++++------------- 2 files changed, 14 insertions(+), 25 deletions(-) diff --git a/libs/yocto/yocto_bvh.h b/libs/yocto/yocto_bvh.h index b3aa01143..c1a4b41c7 100644 --- a/libs/yocto/yocto_bvh.h +++ b/libs/yocto/yocto_bvh.h @@ -66,18 +66,6 @@ using std::vector; // ----------------------------------------------------------------------------- namespace yocto { -// BVH tree node containing its bounds, indices to the BVH arrays of either -// primitives or internal nodes, the node element type, -// and the split axis. Leaf and internal nodes are identical, except that -// indices refer to primitives for leaf nodes or other nodes for internal nodes. -struct bvh_node { - bbox3f bbox = invalidb3f; - int32_t start = 0; - int16_t num = 0; - int8_t axis = 0; - bool internal = false; -}; - // BVH tree stored as a node array with the tree structure is encoded using // array indices. BVH nodes indices refer to either the node array, // for internal nodes, or the primitive arrays, for leaf nodes. diff --git a/libs/yocto/yocto_shape.h b/libs/yocto/yocto_shape.h index 55ef357f4..cd16db616 100644 --- a/libs/yocto/yocto_shape.h +++ b/libs/yocto/yocto_shape.h @@ -467,24 +467,25 @@ vector<vector<int>> vertex_to_faces_adjacencies( // ----------------------------------------------------------------------------- namespace yocto { -// BVH tree stored as a node array with the tree structure is encoded using -// array indices. BVH nodes indices refer to either the node array, -// for internal nodes, or the primitive arrays, for leaf nodes. -// Application data is not stored explicitly. // BVH tree node containing its bounds, indices to the BVH arrays of either // primitives or internal nodes, the node element type, // and the split axis. Leaf and internal nodes are identical, except that // indices refer to primitives for leaf nodes or other nodes for internal nodes. +struct bvh_node { + bbox3f bbox = invalidb3f; + int32_t start = 0; + int16_t num = 0; + int8_t axis = 0; + bool internal = false; +}; + +// BVH tree stored as a node array with the tree structure is encoded using +// array indices. BVH nodes indices refer to either the node array, +// for internal nodes, or the primitive arrays, for leaf nodes. +// Application data is not stored explicitly. struct bvh_tree { - struct node { - bbox3f bbox = invalidb3f; - int32_t start = 0; - int16_t num = 0; - int8_t axis = 0; - bool internal = false; - }; - vector<node> nodes = {}; - vector<int> primitives = {}; + vector<bvh_node> nodes = {}; + vector<int> primitives = {}; }; // Results of intersect_xxx and overlap_xxx functions that include hit flag, From e69dde3f744c7fb7fe806b0cc3688ea37a559000 Mon Sep 17 00:00:00 2001 From: Fabio Pellacini <fabio.pellacini@gmail.com> Date: Sun, 7 Aug 2022 10:17:05 +0200 Subject: [PATCH 3/9] updated --- libs/yocto/yocto_bvh.cpp | 104 ++++++++++++++++++++----------------- libs/yocto/yocto_bvh.h | 34 +++++------- libs/yocto/yocto_trace.cpp | 4 +- 3 files changed, 69 insertions(+), 73 deletions(-) diff --git a/libs/yocto/yocto_bvh.cpp b/libs/yocto/yocto_bvh.cpp index 03cb9cbad..54ea9ea04 100644 --- a/libs/yocto/yocto_bvh.cpp +++ b/libs/yocto/yocto_bvh.cpp @@ -235,15 +235,17 @@ static pair<int, int> split_middle(vector<int>& primitives, const int bvh_max_prims = 4; // Build BVH nodes -static void build_bvh(vector<bvh_node>& nodes, vector<int>& primitives, - const vector<bbox3f>& bboxes, bool highquality) { +static bvh_tree make_bvh(const vector<bbox3f>& bboxes, bool highquality) { + // bvh + auto bvh = bvh_tree{}; + // prepare to build nodes - nodes.clear(); - nodes.reserve(bboxes.size() * 2); + bvh.nodes.clear(); + bvh.nodes.reserve(bboxes.size() * 2); // prepare primitives - primitives.resize(bboxes.size()); - for (auto idx : range(bboxes.size())) primitives[idx] = (int)idx; + bvh.primitives.resize(bboxes.size()); + for (auto idx : range(bboxes.size())) bvh.primitives[idx] = (int)idx; // prepare centers auto centers = vector<vec3f>(bboxes.size()); @@ -251,7 +253,7 @@ static void build_bvh(vector<bvh_node>& nodes, vector<int>& primitives, // push first node onto the stack auto stack = vector<vec3i>{{0, 0, (int)bboxes.size()}}; - nodes.emplace_back(); + bvh.nodes.emplace_back(); // create nodes until the stack is empty while (!stack.empty()) { @@ -260,27 +262,28 @@ static void build_bvh(vector<bvh_node>& nodes, vector<int>& primitives, stack.pop_back(); // grab node - auto& node = nodes[nodeid]; + auto& node = bvh.nodes[nodeid]; // compute bounds node.bbox = invalidb3f; for (auto i = start; i < end; i++) - node.bbox = merge(node.bbox, bboxes[primitives[i]]); + node.bbox = merge(node.bbox, bboxes[bvh.primitives[i]]); // split into two children if (end - start > bvh_max_prims) { // get split auto [mid, axis] = - highquality ? split_sah(primitives, bboxes, centers, start, end) - : split_middle(primitives, bboxes, centers, start, end); + highquality + ? split_sah(bvh.primitives, bboxes, centers, start, end) + : split_middle(bvh.primitives, bboxes, centers, start, end); // make an internal node node.internal = true; node.axis = (uint8_t)axis; node.num = 2; - node.start = (int)nodes.size(); - nodes.emplace_back(); - nodes.emplace_back(); + node.start = (int)bvh.nodes.size(); + bvh.nodes.emplace_back(); + bvh.nodes.emplace_back(); stack.push_back({node.start + 0, start, mid}); stack.push_back({node.start + 1, mid, end}); } else { @@ -292,22 +295,24 @@ static void build_bvh(vector<bvh_node>& nodes, vector<int>& primitives, } // cleanup - nodes.shrink_to_fit(); + bvh.nodes.shrink_to_fit(); + + // done + return bvh; } // Update bvh -static void refit_bvh(vector<bvh_node>& nodes, const vector<int>& primitives, - const vector<bbox3f>& bboxes) { - for (auto nodeid = (int)nodes.size() - 1; nodeid >= 0; nodeid--) { - auto& node = nodes[nodeid]; +static void refit_bvh(bvh_tree& bvh, const vector<bbox3f>& bboxes) { + for (auto nodeid = (int)bvh.nodes.size() - 1; nodeid >= 0; nodeid--) { + auto& node = bvh.nodes[nodeid]; node.bbox = invalidb3f; if (node.internal) { for (auto idx : range(2)) { - node.bbox = merge(node.bbox, nodes[node.start + idx].bbox); + node.bbox = merge(node.bbox, bvh.nodes[node.start + idx].bbox); } } else { for (auto idx : range(node.num)) { - node.bbox = merge(node.bbox, bboxes[primitives[node.start + idx]]); + node.bbox = merge(node.bbox, bboxes[bvh.primitives[node.start + idx]]); } } } @@ -350,10 +355,7 @@ shape_bvh make_shape_bvh(const shape_data& shape, bool highquality) { } // build nodes - build_bvh(bvh.nodes, bvh.primitives, bboxes, highquality); - - // done - return bvh; + return make_bvh(bboxes, highquality); } scene_bvh make_scene_bvh( @@ -384,7 +386,7 @@ scene_bvh make_scene_bvh( } // build nodes - build_bvh(bvh.nodes, bvh.primitives, bboxes, highquality); + bvh.instances = make_bvh(bboxes, highquality); // done return bvh; @@ -423,7 +425,7 @@ void update_shape_bvh(shape_bvh& bvh, const shape_data& shape) { } // update nodes - refit_bvh(bvh.nodes, bvh.primitives, bboxes); + refit_bvh(bvh, bboxes); } void update_scene_bvh(scene_bvh& bvh, const scene_data& scene, @@ -442,7 +444,7 @@ void update_scene_bvh(scene_bvh& bvh, const scene_data& scene, } // update nodes - refit_bvh(bvh.nodes, bvh.primitives, bboxes); + refit_bvh(bvh.instances, bboxes); } } // namespace yocto @@ -543,8 +545,11 @@ shape_intersection intersect_shape_bvh(const shape_bvh& bvh, return intersection; } -scene_intersection intersect_scene_bvh(const scene_bvh& bvh, +scene_intersection intersect_scene_bvh(const scene_bvh& sbvh, const scene_data& scene, const ray3f& ray_, bool find_any) { + // get instances bvh + auto& bvh = sbvh.instances; + // check empty if (bvh.nodes.empty()) return {}; @@ -589,7 +594,7 @@ scene_intersection intersect_scene_bvh(const scene_bvh& bvh, for (auto idx = node.start; idx < node.start + node.num; idx++) { auto& instance_ = scene.instances[bvh.primitives[idx]]; auto inv_ray = transform_ray(inverse(instance_.frame, true), ray); - auto sintersection = intersect_shape_bvh(bvh.shapes[instance_.shape], + auto sintersection = intersect_shape_bvh(sbvh.shapes[instance_.shape], scene.shapes[instance_.shape], inv_ray, find_any); if (!sintersection.hit) continue; intersection = {bvh.primitives[idx], sintersection.element, @@ -710,9 +715,12 @@ shape_intersection overlap_shape_bvh(const shape_bvh& bvh, } // Intersect ray with a bvh. -scene_intersection overlap_scene_bvh(const scene_bvh& bvh, +scene_intersection overlap_scene_bvh(const scene_bvh& sbvh, const scene_data& scene, const vec3f& pos, float max_distance, bool find_any) { + // get instances bvh + auto& bvh = sbvh.instances; + // check if empty if (bvh.nodes.empty()) return {}; @@ -742,11 +750,9 @@ scene_intersection overlap_scene_bvh(const scene_bvh& bvh, for (auto idx : range(node.num)) { auto primitive = bvh.primitives[node.start + idx]; auto& instance_ = scene.instances[primitive]; - auto& shape = scene.shapes[instance_.shape]; - auto& sbvh = bvh.shapes[instance_.shape]; auto inv_pos = transform_point(inverse(instance_.frame, true), pos); - auto sintersection = overlap_shape_bvh( - sbvh, shape, inv_pos, max_distance, find_any); + auto sintersection = overlap_shape_bvh(sbvh.shapes[instance_.shape], + scene.shapes[instance_.shape], inv_pos, max_distance, find_any); if (!sintersection.hit) continue; intersection = {primitive, sintersection.element, sintersection.uv, sintersection.distance, true}; @@ -886,9 +892,9 @@ void clear_ebvh(void* ebvh) { shape_ebvh make_shape_ebvh(const shape_data& shape, bool highquality) { auto bvh = shape_ebvh{}; auto edevice = embree_device(); - bvh.bvh = unique_ptr<void, void (*)(void*)>{ - rtcNewScene(edevice), &clear_ebvh}; - auto escene = (RTCScene)bvh.bvh.get(); + bvh.ebvh = unique_ptr<void, void (*)(void*)>{ + rtcNewScene(edevice), &clear_ebvh}; + auto escene = (RTCScene)bvh.ebvh.get(); if (highquality) { rtcSetSceneBuildQuality(escene, RTC_BUILD_QUALITY_HIGH); } else { @@ -984,10 +990,10 @@ scene_ebvh make_scene_ebvh( } // scene bvh - auto edevice = embree_device(); - bvh.bvh = unique_ptr<void, void (*)(void*)>{ - rtcNewScene(edevice), &clear_ebvh}; - auto escene = (RTCScene)bvh.bvh.get(); + auto edevice = embree_device(); + bvh.instances.ebvh = unique_ptr<void, void (*)(void*)>{ + rtcNewScene(edevice), &clear_ebvh}; + auto escene = (RTCScene)bvh.instances.ebvh.get(); if (highquality) { rtcSetSceneBuildQuality(escene, RTC_BUILD_QUALITY_HIGH); } else { @@ -996,9 +1002,9 @@ scene_ebvh make_scene_ebvh( for (auto instance_id = 0; instance_id < (int)scene.instances.size(); instance_id++) { auto& instance = scene.instances[instance_id]; - auto& sbvh = bvh.shapes[instance.shape]; auto egeometry = rtcNewGeometry(edevice, RTC_GEOMETRY_TYPE_INSTANCE); - rtcSetGeometryInstancedScene(egeometry, (RTCScene)sbvh.bvh.get()); + rtcSetGeometryInstancedScene( + egeometry, (RTCScene)bvh.shapes[instance.shape].ebvh.get()); rtcSetGeometryTransform( egeometry, 0, RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR, &instance.frame); rtcCommitGeometry(egeometry); @@ -1016,12 +1022,12 @@ void update_shape_ebvh(shape_ebvh& bvh, const shape_data& shape) { void update_scene_ebvh(scene_ebvh& bvh, const scene_data& scene, const vector<int>& updated_instances, const vector<int>& updated_shapes) { // scene bvh - auto escene = (RTCScene)bvh.bvh.get(); + auto escene = (RTCScene)bvh.instances.ebvh.get(); for (auto instance_id : updated_instances) { auto& instance = scene.instances[instance_id]; - auto& sbvh = bvh.shapes[instance.shape]; auto embree_geom = rtcGetGeometry(escene, instance_id); - rtcSetGeometryInstancedScene(embree_geom, (RTCScene)sbvh.bvh.get()); + rtcSetGeometryInstancedScene( + embree_geom, (RTCScene)bvh.shapes[instance.shape].ebvh.get()); rtcSetGeometryTransform( embree_geom, 0, RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR, &instance.frame); rtcCommitGeometry(embree_geom); @@ -1050,7 +1056,7 @@ shape_intersection intersect_shape_ebvh(const shape_ebvh& bvh, embree_ray.hit.instID[0] = RTC_INVALID_GEOMETRY_ID; RTCIntersectContext embree_ctx; rtcInitIntersectContext(&embree_ctx); - rtcIntersect1((RTCScene)bvh.bvh.get(), &embree_ctx, &embree_ray); + rtcIntersect1((RTCScene)bvh.ebvh.get(), &embree_ctx, &embree_ray); if (embree_ray.hit.geomID == RTC_INVALID_GEOMETRY_ID) return {}; auto element = (int)embree_ray.hit.primID; auto uv = vec2f{embree_ray.hit.u, embree_ray.hit.v}; @@ -1076,7 +1082,7 @@ scene_intersection intersect_scene_ebvh(const scene_ebvh& bvh, embree_ray.hit.instID[0] = RTC_INVALID_GEOMETRY_ID; RTCIntersectContext embree_ctx; rtcInitIntersectContext(&embree_ctx); - rtcIntersect1((RTCScene)bvh.bvh.get(), &embree_ctx, &embree_ray); + rtcIntersect1((RTCScene)bvh.instances.ebvh.get(), &embree_ctx, &embree_ray); if (embree_ray.hit.geomID == RTC_INVALID_GEOMETRY_ID) return {}; auto instance = (int)embree_ray.hit.instID[0]; auto element = (int)embree_ray.hit.primID; diff --git a/libs/yocto/yocto_bvh.h b/libs/yocto/yocto_bvh.h index c1a4b41c7..821042eb7 100644 --- a/libs/yocto/yocto_bvh.h +++ b/libs/yocto/yocto_bvh.h @@ -66,24 +66,14 @@ using std::vector; // ----------------------------------------------------------------------------- namespace yocto { -// BVH tree stored as a node array with the tree structure is encoded using -// array indices. BVH nodes indices refer to either the node array, -// for internal nodes, or the primitive arrays, for leaf nodes. -// Application data is not stored explicitly. -struct shape_bvh { - vector<bvh_node> nodes = {}; - vector<int> primitives = {}; -}; +// Shape BVHs are just the bvh for the shape. +using shape_bvh = bvh_tree; -// BVH tree stored as a node array with the tree structure is encoded using -// array indices. BVH nodes indices refer to either the node array, -// for internal nodes, or the primitive arrays, for leaf nodes. -// We also store the BVH of the contained shapes. +// Scene BVHs store the bvh for instances and shapes. // Application data is not stored explicitly. struct scene_bvh { - vector<bvh_node> nodes = {}; - vector<int> primitives = {}; - vector<shape_bvh> shapes = {}; // shapes + bvh_tree instances = {}; + vector<bvh_tree> shapes = {}; }; // Build the bvh acceleration structure. @@ -138,18 +128,18 @@ scene_intersection overlap_scene_bvh(const scene_bvh& bvh, // ----------------------------------------------------------------------------- namespace yocto { -// Intel Embree tree -using ebvh_tree = unique_ptr<void, void (*)(void*)>; +// Wrapper for Intel's Embree +struct ebvh_tree { + unique_ptr<void, void (*)(void*)> ebvh = {nullptr, nullptr}; +}; // Wrapper for Intel Embree. -struct shape_ebvh { - unique_ptr<void, void (*)(void*)> bvh = {nullptr, nullptr}; // embree -}; +using shape_ebvh = ebvh_tree; // Wrapper for Intel Embree. struct scene_ebvh { - vector<shape_ebvh> shapes = {}; // shapes - unique_ptr<void, void (*)(void*)> bvh = {nullptr, nullptr}; // embree + ebvh_tree instances = {}; // instances + vector<ebvh_tree> shapes = {}; // shapes }; // Check if embree is supported diff --git a/libs/yocto/yocto_trace.cpp b/libs/yocto/yocto_trace.cpp index fb0b8501f..2c3a664f8 100644 --- a/libs/yocto/yocto_trace.cpp +++ b/libs/yocto/yocto_trace.cpp @@ -98,7 +98,7 @@ trace_bvh make_trace_bvh(const scene_data& scene, const trace_params& params) { // Ray-intersection shortcuts static scene_intersection intersect_scene(const trace_bvh& bvh, const scene_data& scene, const ray3f& ray, bool find_any = false) { - if (bvh.ebvh.bvh) { + if (bvh.ebvh.instances.ebvh) { return intersect_scene_ebvh(bvh.ebvh, scene, ray, find_any); } else { return intersect_scene_bvh(bvh.bvh, scene, ray, find_any); @@ -107,7 +107,7 @@ static scene_intersection intersect_scene(const trace_bvh& bvh, static scene_intersection intersect_instance(const trace_bvh& bvh, const scene_data& scene, int instance, const ray3f& ray, bool find_any = false) { - if (bvh.ebvh.bvh) { + if (bvh.ebvh.instances.ebvh) { return intersect_instance_ebvh(bvh.ebvh, scene, instance, ray, find_any); } else { return intersect_instance_bvh(bvh.bvh, scene, instance, ray, find_any); From ff1c8f6f671de89df284045c7cda302459520094 Mon Sep 17 00:00:00 2001 From: Fabio Pellacini <fabio.pellacini@gmail.com> Date: Sun, 7 Aug 2022 10:19:40 +0200 Subject: [PATCH 4/9] updated --- libs/yocto/yocto_shape.cpp | 91 ++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 48 deletions(-) diff --git a/libs/yocto/yocto_shape.cpp b/libs/yocto/yocto_shape.cpp index 8d52d97e4..a144bd3e7 100644 --- a/libs/yocto/yocto_shape.cpp +++ b/libs/yocto/yocto_shape.cpp @@ -1159,16 +1159,16 @@ shape_data make_cube(float scale, int subdivisions) { {+1, +1, +1}, {+1, +1, -1}, {-1, +1, -1}, {+1, -1, +1}, {-1, -1, +1}, {-1, -1, -1}, {+1, -1, -1}}; static const auto cube_normals = vector<vec3f>{{0, 0, +1}, {0, 0, +1}, - {0, 0, +1}, {0, 0, +1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, - {+1, 0, 0}, {+1, 0, 0}, {+1, 0, 0}, {+1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, - {-1, 0, 0}, {-1, 0, 0}, {0, +1, 0}, {0, +1, 0}, {0, +1, 0}, {0, +1, 0}, - {0, -1, 0}, {0, -1, 0}, {0, -1, 0}, {0, -1, 0}}; + {0, 0, +1}, {0, 0, +1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, + {+1, 0, 0}, {+1, 0, 0}, {+1, 0, 0}, {+1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, + {-1, 0, 0}, {-1, 0, 0}, {0, +1, 0}, {0, +1, 0}, {0, +1, 0}, {0, +1, 0}, + {0, -1, 0}, {0, -1, 0}, {0, -1, 0}, {0, -1, 0}}; static const auto cube_texcoords = vector<vec2f>{{0, 1}, {1, 1}, {1, 0}, {0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}}; static const auto cube_quads = vector<vec4i>{{0, 1, 2, 3}, {4, 5, 6, 7}, - {8, 9, 10, 11}, {12, 13, 14, 15}, {16, 17, 18, 19}, {20, 21, 22, 23}}; + {8, 9, 10, 11}, {12, 13, 14, 15}, {16, 17, 18, 19}, {20, 21, 22, 23}}; auto shape = shape_data{}; if (subdivisions == 0) { @@ -1194,16 +1194,16 @@ fvshape_data make_fvcube(float scale, int subdivisions) { {+1, +1, +1}, {-1, +1, +1}, {+1, -1, -1}, {-1, -1, -1}, {-1, +1, -1}, {+1, +1, -1}}; static const auto fvcube_normals = vector<vec3f>{{0, 0, +1}, {0, 0, +1}, - {0, 0, +1}, {0, 0, +1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, - {+1, 0, 0}, {+1, 0, 0}, {+1, 0, 0}, {+1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, - {-1, 0, 0}, {-1, 0, 0}, {0, +1, 0}, {0, +1, 0}, {0, +1, 0}, {0, +1, 0}, - {0, -1, 0}, {0, -1, 0}, {0, -1, 0}, {0, -1, 0}}; + {0, 0, +1}, {0, 0, +1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, + {+1, 0, 0}, {+1, 0, 0}, {+1, 0, 0}, {+1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, + {-1, 0, 0}, {-1, 0, 0}, {0, +1, 0}, {0, +1, 0}, {0, +1, 0}, {0, +1, 0}, + {0, -1, 0}, {0, -1, 0}, {0, -1, 0}, {0, -1, 0}}; static const auto fvcube_texcoords = vector<vec2f>{{0, 1}, {1, 1}, {1, 0}, {0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}}; static const auto fvcube_quadspos = vector<vec4i>{{0, 1, 2, 3}, {4, 5, 6, 7}, - {1, 4, 7, 2}, {5, 0, 3, 6}, {3, 2, 7, 6}, {1, 0, 5, 4}}; + {1, 4, 7, 2}, {5, 0, 3, 6}, {3, 2, 7, 6}, {1, 0, 5, 4}}; static const auto fvcube_quadsnorm = vector<vec4i>{{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}, {12, 13, 14, 15}, {16, 17, 18, 19}, {20, 21, 22, 23}}; static const auto fvcube_quadstexcoord = vector<vec4i>{{0, 1, 2, 3}, @@ -2046,14 +2046,13 @@ static pair<int, int> split_middle(vector<int>& primitives, const int bvh_max_prims = 4; // Build BVH nodes -static void build_bvh(bvh_tree& bvh, vector<bbox3f>& bboxes) { - // get values - auto& nodes = bvh.nodes; - auto& primitives = bvh.primitives; +static bvh_tree make_bvh(vector<bbox3f>& bboxes) { + // bvh + auto bvh = bvh_tree{}; // prepare to build nodes - nodes.clear(); - nodes.reserve(bboxes.size() * 2); + bvh.nodes.clear(); + bvh.nodes.reserve(bboxes.size() * 2); // prepare primitives bvh.primitives.resize(bboxes.size()); @@ -2065,7 +2064,7 @@ static void build_bvh(bvh_tree& bvh, vector<bbox3f>& bboxes) { // queue up first node auto queue = deque<vec3i>{{0, 0, (int)bboxes.size()}}; - nodes.emplace_back(); + bvh.nodes.emplace_back(); // create nodes until the queue is empty while (!queue.empty()) { @@ -2075,25 +2074,26 @@ static void build_bvh(bvh_tree& bvh, vector<bbox3f>& bboxes) { auto nodeid = next.x, start = next.y, end = next.z; // grab node - auto& node = nodes[nodeid]; + auto& node = bvh.nodes[nodeid]; // compute bounds node.bbox = invalidb3f; for (auto i = start; i < end; i++) - node.bbox = merge(node.bbox, bboxes[primitives[i]]); + node.bbox = merge(node.bbox, bboxes[bvh.primitives[i]]); // split into two children if (end - start > bvh_max_prims) { // get split - auto [mid, axis] = split_middle(primitives, bboxes, centers, start, end); + auto [mid, axis] = split_middle( + bvh.primitives, bboxes, centers, start, end); // make an internal node node.internal = true; node.axis = (int8_t)axis; node.num = 2; - node.start = (int)nodes.size(); - nodes.emplace_back(); - nodes.emplace_back(); + node.start = (int)bvh.nodes.size(); + bvh.nodes.emplace_back(); + bvh.nodes.emplace_back(); queue.push_back({node.start + 0, start, mid}); queue.push_back({node.start + 1, mid, end}); } else { @@ -2105,7 +2105,10 @@ static void build_bvh(bvh_tree& bvh, vector<bbox3f>& bboxes) { } // cleanup - nodes.shrink_to_fit(); + bvh.nodes.shrink_to_fit(); + + // done + return bvh; } // Update bvh @@ -2136,9 +2139,7 @@ bvh_tree make_points_bvh(const vector<int>& points, } // build nodes - auto bvh = bvh_tree{}; - build_bvh(bvh, bboxes); - return bvh; + return make_bvh(bboxes); } bvh_tree make_lines_bvh(const vector<vec2i>& lines, const vector<vec3f>& positions, const vector<float>& radius) { @@ -2151,9 +2152,7 @@ bvh_tree make_lines_bvh(const vector<vec2i>& lines, } // build nodes - auto bvh = bvh_tree{}; - build_bvh(bvh, bboxes); - return bvh; + return make_bvh(bboxes); } bvh_tree make_triangles_bvh(const vector<vec3i>& triangles, const vector<vec3f>& positions, const vector<float>& radius) { @@ -2166,9 +2165,7 @@ bvh_tree make_triangles_bvh(const vector<vec3i>& triangles, } // build nodes - auto bvh = bvh_tree{}; - build_bvh(bvh, bboxes); - return bvh; + return make_bvh(bboxes); } bvh_tree make_quads_bvh(const vector<vec4i>& quads, const vector<vec3f>& positions, const vector<float>& radius) { @@ -2181,9 +2178,7 @@ bvh_tree make_quads_bvh(const vector<vec4i>& quads, } // build nodes - auto bvh = bvh_tree{}; - build_bvh(bvh, bboxes); - return bvh; + return make_bvh(bboxes); } void update_points_bvh(bvh_tree& bvh, const vector<int>& points, @@ -3769,8 +3764,8 @@ void make_bezier_circle( // constant from http://spencermortensen.com/articles/bezier-circle/ const auto c = 0.551915024494f; static auto circle_pos = vector<vec3f>{{1, 0, 0}, {1, c, 0}, {c, 1, 0}, - {0, 1, 0}, {-c, 1, 0}, {-1, c, 0}, {-1, 0, 0}, {-1, -c, 0}, {-c, -1, 0}, - {0, -1, 0}, {c, -1, 0}, {1, -c, 0}}; + {0, 1, 0}, {-c, 1, 0}, {-1, c, 0}, {-1, 0, 0}, {-1, -c, 0}, {-c, -1, 0}, + {0, -1, 0}, {c, -1, 0}, {1, -c, 0}}; static auto circle_beziers = vector<vec4i>{ {0, 1, 2, 3}, {3, 4, 5, 6}, {6, 7, 8, 9}, {9, 10, 11, 0}}; positions = circle_pos; @@ -3892,16 +3887,16 @@ void make_cube(vector<vec4i>& quads, vector<vec3f>& positions, {+1, +1, +1}, {+1, +1, -1}, {-1, +1, -1}, {+1, -1, +1}, {-1, -1, +1}, {-1, -1, -1}, {+1, -1, -1}}; static const auto cube_normals = vector<vec3f>{{0, 0, +1}, {0, 0, +1}, - {0, 0, +1}, {0, 0, +1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, - {+1, 0, 0}, {+1, 0, 0}, {+1, 0, 0}, {+1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, - {-1, 0, 0}, {-1, 0, 0}, {0, +1, 0}, {0, +1, 0}, {0, +1, 0}, {0, +1, 0}, - {0, -1, 0}, {0, -1, 0}, {0, -1, 0}, {0, -1, 0}}; + {0, 0, +1}, {0, 0, +1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, + {+1, 0, 0}, {+1, 0, 0}, {+1, 0, 0}, {+1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, + {-1, 0, 0}, {-1, 0, 0}, {0, +1, 0}, {0, +1, 0}, {0, +1, 0}, {0, +1, 0}, + {0, -1, 0}, {0, -1, 0}, {0, -1, 0}, {0, -1, 0}}; static const auto cube_texcoords = vector<vec2f>{{0, 1}, {1, 1}, {1, 0}, {0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}}; static const auto cube_quads = vector<vec4i>{{0, 1, 2, 3}, {4, 5, 6, 7}, - {8, 9, 10, 11}, {12, 13, 14, 15}, {16, 17, 18, 19}, {20, 21, 22, 23}}; + {8, 9, 10, 11}, {12, 13, 14, 15}, {16, 17, 18, 19}, {20, 21, 22, 23}}; if (subdivisions == 0) { quads = cube_quads; positions = cube_positions; @@ -3928,16 +3923,16 @@ void make_fvcube(vector<vec4i>& quadspos, vector<vec4i>& quadsnorm, {+1, +1, +1}, {-1, +1, +1}, {+1, -1, -1}, {-1, -1, -1}, {-1, +1, -1}, {+1, +1, -1}}; static const auto fvcube_normals = vector<vec3f>{{0, 0, +1}, {0, 0, +1}, - {0, 0, +1}, {0, 0, +1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, - {+1, 0, 0}, {+1, 0, 0}, {+1, 0, 0}, {+1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, - {-1, 0, 0}, {-1, 0, 0}, {0, +1, 0}, {0, +1, 0}, {0, +1, 0}, {0, +1, 0}, - {0, -1, 0}, {0, -1, 0}, {0, -1, 0}, {0, -1, 0}}; + {0, 0, +1}, {0, 0, +1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, + {+1, 0, 0}, {+1, 0, 0}, {+1, 0, 0}, {+1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, + {-1, 0, 0}, {-1, 0, 0}, {0, +1, 0}, {0, +1, 0}, {0, +1, 0}, {0, +1, 0}, + {0, -1, 0}, {0, -1, 0}, {0, -1, 0}, {0, -1, 0}}; static const auto fvcube_texcoords = vector<vec2f>{{0, 1}, {1, 1}, {1, 0}, {0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}}; static const auto fvcube_quadspos = vector<vec4i>{{0, 1, 2, 3}, {4, 5, 6, 7}, - {1, 4, 7, 2}, {5, 0, 3, 6}, {3, 2, 7, 6}, {1, 0, 5, 4}}; + {1, 4, 7, 2}, {5, 0, 3, 6}, {3, 2, 7, 6}, {1, 0, 5, 4}}; static const auto fvcube_quadsnorm = vector<vec4i>{{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}, {12, 13, 14, 15}, {16, 17, 18, 19}, {20, 21, 22, 23}}; static const auto fvcube_quadstexcoord = vector<vec4i>{{0, 1, 2, 3}, From 9992a4e74e1afdad575b904c8cd23c1287af0590 Mon Sep 17 00:00:00 2001 From: Fabio Pellacini <fabio.pellacini@gmail.com> Date: Sun, 7 Aug 2022 10:42:44 +0200 Subject: [PATCH 5/9] updated --- libs/yocto/yocto_bvh.cpp | 115 +++++++++++++++++++++------------------ libs/yocto/yocto_bvh.h | 8 ++- 2 files changed, 67 insertions(+), 56 deletions(-) diff --git a/libs/yocto/yocto_bvh.cpp b/libs/yocto/yocto_bvh.cpp index 54ea9ea04..ff4af3f71 100644 --- a/libs/yocto/yocto_bvh.cpp +++ b/libs/yocto/yocto_bvh.cpp @@ -320,7 +320,7 @@ static void refit_bvh(bvh_tree& bvh, const vector<bbox3f>& bboxes) { shape_bvh make_shape_bvh(const shape_data& shape, bool highquality) { // bvh - auto bvh = shape_bvh{}; + auto sbvh = shape_bvh{}; // build primitives auto bboxes = vector<bbox3f>{}; @@ -355,23 +355,26 @@ shape_bvh make_shape_bvh(const shape_data& shape, bool highquality) { } // build nodes - return make_bvh(bboxes, highquality); + sbvh.bvh = make_bvh(bboxes, highquality); + + // done + return sbvh; } scene_bvh make_scene_bvh( const scene_data& scene, bool highquality, bool noparallel) { // bvh - auto bvh = scene_bvh{}; + auto sbvh = scene_bvh{}; // build shape bvh - bvh.shapes.resize(scene.shapes.size()); + sbvh.shapes.resize(scene.shapes.size()); if (noparallel) { for (auto idx : range(scene.shapes.size())) { - bvh.shapes[idx] = make_shape_bvh(scene.shapes[idx], highquality); + sbvh.shapes[idx] = make_shape_bvh(scene.shapes[idx], highquality); } } else { parallel_for(scene.shapes.size(), [&](size_t idx) { - bvh.shapes[idx] = make_shape_bvh(scene.shapes[idx], highquality); + sbvh.shapes[idx] = make_shape_bvh(scene.shapes[idx], highquality); }); } @@ -379,20 +382,20 @@ scene_bvh make_scene_bvh( auto bboxes = vector<bbox3f>(scene.instances.size()); for (auto idx : range(bboxes.size())) { auto& instance = scene.instances[idx]; - auto& sbvh = bvh.shapes[instance.shape]; - bboxes[idx] = sbvh.nodes.empty() + bboxes[idx] = sbvh.shapes[instance.shape].bvh.nodes.empty() ? invalidb3f - : transform_bbox(instance.frame, sbvh.nodes[0].bbox); + : transform_bbox(instance.frame, + sbvh.shapes[instance.shape].bvh.nodes[0].bbox); } // build nodes - bvh.instances = make_bvh(bboxes, highquality); + sbvh.bvh = make_bvh(bboxes, highquality); // done - return bvh; + return sbvh; } -void update_shape_bvh(shape_bvh& bvh, const shape_data& shape) { +void update_shape_bvh(shape_bvh& sbvh, const shape_data& shape) { // build primitives auto bboxes = vector<bbox3f>{}; if (!shape.points.empty()) { @@ -425,26 +428,26 @@ void update_shape_bvh(shape_bvh& bvh, const shape_data& shape) { } // update nodes - refit_bvh(bvh, bboxes); + refit_bvh(sbvh.bvh, bboxes); } -void update_scene_bvh(scene_bvh& bvh, const scene_data& scene, +void update_scene_bvh(scene_bvh& sbvh, const scene_data& scene, const vector<int>& updated_instances, const vector<int>& updated_shapes) { // update shapes for (auto shape : updated_shapes) { - update_shape_bvh(bvh.shapes[shape], scene.shapes[shape]); + update_shape_bvh(sbvh.shapes[shape], scene.shapes[shape]); } // handle instances auto bboxes = vector<bbox3f>(scene.instances.size()); for (auto idx : range(bboxes.size())) { auto& instance = scene.instances[idx]; - auto& sbvh = bvh.shapes[instance.shape]; - bboxes[idx] = transform_bbox(instance.frame, sbvh.nodes[0].bbox); + bboxes[idx] = transform_bbox( + instance.frame, sbvh.shapes[instance.shape].bvh.nodes[0].bbox); } // update nodes - refit_bvh(bvh.instances, bboxes); + refit_bvh(sbvh.bvh, bboxes); } } // namespace yocto @@ -454,8 +457,11 @@ void update_scene_bvh(scene_bvh& bvh, const scene_data& scene, // ----------------------------------------------------------------------------- namespace yocto { -shape_intersection intersect_shape_bvh(const shape_bvh& bvh, +shape_intersection intersect_shape_bvh(const shape_bvh& sbvh, const shape_data& shape, const ray3f& ray_, bool find_any) { + // get bvh tree + auto& bvh = sbvh.bvh; + // check empty if (bvh.nodes.empty()) return {}; @@ -548,7 +554,7 @@ shape_intersection intersect_shape_bvh(const shape_bvh& bvh, scene_intersection intersect_scene_bvh(const scene_bvh& sbvh, const scene_data& scene, const ray3f& ray_, bool find_any) { // get instances bvh - auto& bvh = sbvh.instances; + auto& bvh = sbvh.bvh; // check empty if (bvh.nodes.empty()) return {}; @@ -610,11 +616,11 @@ scene_intersection intersect_scene_bvh(const scene_bvh& sbvh, return intersection; } -scene_intersection intersect_instance_bvh(const scene_bvh& bvh, +scene_intersection intersect_instance_bvh(const scene_bvh& sbvh, const scene_data& scene, int instance_, const ray3f& ray, bool find_any) { auto& instance = scene.instances[instance_]; auto inv_ray = transform_ray(inverse(instance.frame, true), ray); - auto intersection = intersect_shape_bvh(bvh.shapes[instance.shape], + auto intersection = intersect_shape_bvh(sbvh.shapes[instance.shape], scene.shapes[instance.shape], inv_ray, find_any); if (!intersection.hit) return {}; return {instance_, intersection.element, intersection.uv, @@ -629,9 +635,12 @@ scene_intersection intersect_instance_bvh(const scene_bvh& bvh, namespace yocto { // Intersect ray with a bvh. -shape_intersection overlap_shape_bvh(const shape_bvh& bvh, +shape_intersection overlap_shape_bvh(const shape_bvh& sbvh, const shape_data& shape, const vec3f& pos, float max_distance, bool find_any) { + // get bvh tree + auto& bvh = sbvh.bvh; + // check if empty if (bvh.nodes.empty()) return {}; @@ -719,7 +728,7 @@ scene_intersection overlap_scene_bvh(const scene_bvh& sbvh, const scene_data& scene, const vec3f& pos, float max_distance, bool find_any) { // get instances bvh - auto& bvh = sbvh.instances; + auto& bvh = sbvh.bvh; // check if empty if (bvh.nodes.empty()) return {}; @@ -890,11 +899,11 @@ void clear_ebvh(void* ebvh) { // Build the bvh acceleration structure. shape_ebvh make_shape_ebvh(const shape_data& shape, bool highquality) { - auto bvh = shape_ebvh{}; + auto sbvh = shape_ebvh{}; auto edevice = embree_device(); - bvh.ebvh = unique_ptr<void, void (*)(void*)>{ - rtcNewScene(edevice), &clear_ebvh}; - auto escene = (RTCScene)bvh.ebvh.get(); + sbvh.ebvh = unique_ptr<void, void (*)(void*)>{ + rtcNewScene(edevice), &clear_ebvh}; + auto escene = (RTCScene)sbvh.ebvh.get(); if (highquality) { rtcSetSceneBuildQuality(escene, RTC_BUILD_QUALITY_HIGH); } else { @@ -969,31 +978,31 @@ shape_ebvh make_shape_ebvh(const shape_data& shape, bool highquality) { throw std::runtime_error("empty shapes not supported"); } rtcCommitScene(escene); - return bvh; + return sbvh; } scene_ebvh make_scene_ebvh( const scene_data& scene, bool highquality, bool noparallel) { // scene bvh - auto bvh = scene_ebvh{}; + auto sbvh = scene_ebvh{}; // shape bvhs - bvh.shapes.resize(scene.shapes.size()); + sbvh.shapes.resize(scene.shapes.size()); if (noparallel) { for (auto idx : range(scene.shapes.size())) { - bvh.shapes[idx] = make_shape_ebvh(scene.shapes[idx], highquality); + sbvh.shapes[idx] = make_shape_ebvh(scene.shapes[idx], highquality); } } else { parallel_for(scene.shapes.size(), [&](size_t idx) { - bvh.shapes[idx] = make_shape_ebvh(scene.shapes[idx], highquality); + sbvh.shapes[idx] = make_shape_ebvh(scene.shapes[idx], highquality); }); } // scene bvh - auto edevice = embree_device(); - bvh.instances.ebvh = unique_ptr<void, void (*)(void*)>{ + auto edevice = embree_device(); + sbvh.instances.ebvh = unique_ptr<void, void (*)(void*)>{ rtcNewScene(edevice), &clear_ebvh}; - auto escene = (RTCScene)bvh.instances.ebvh.get(); + auto escene = (RTCScene)sbvh.instances.ebvh.get(); if (highquality) { rtcSetSceneBuildQuality(escene, RTC_BUILD_QUALITY_HIGH); } else { @@ -1004,7 +1013,7 @@ scene_ebvh make_scene_ebvh( auto& instance = scene.instances[instance_id]; auto egeometry = rtcNewGeometry(edevice, RTC_GEOMETRY_TYPE_INSTANCE); rtcSetGeometryInstancedScene( - egeometry, (RTCScene)bvh.shapes[instance.shape].ebvh.get()); + egeometry, (RTCScene)sbvh.shapes[instance.shape].ebvh.get()); rtcSetGeometryTransform( egeometry, 0, RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR, &instance.frame); rtcCommitGeometry(egeometry); @@ -1012,22 +1021,22 @@ scene_ebvh make_scene_ebvh( rtcReleaseGeometry(egeometry); } rtcCommitScene(escene); - return bvh; + return sbvh; } // Refit bvh data -void update_shape_ebvh(shape_ebvh& bvh, const shape_data& shape) { +void update_shape_ebvh(shape_ebvh& sbvh, const shape_data& shape) { throw embree_error{"feature not supported"}; } -void update_scene_ebvh(scene_ebvh& bvh, const scene_data& scene, +void update_scene_ebvh(scene_ebvh& sbvh, const scene_data& scene, const vector<int>& updated_instances, const vector<int>& updated_shapes) { // scene bvh - auto escene = (RTCScene)bvh.instances.ebvh.get(); + auto escene = (RTCScene)sbvh.instances.ebvh.get(); for (auto instance_id : updated_instances) { auto& instance = scene.instances[instance_id]; auto embree_geom = rtcGetGeometry(escene, instance_id); rtcSetGeometryInstancedScene( - embree_geom, (RTCScene)bvh.shapes[instance.shape].ebvh.get()); + embree_geom, (RTCScene)sbvh.shapes[instance.shape].ebvh.get()); rtcSetGeometryTransform( embree_geom, 0, RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR, &instance.frame); rtcCommitGeometry(embree_geom); @@ -1038,7 +1047,7 @@ void update_scene_ebvh(scene_ebvh& bvh, const scene_data& scene, // Intersect ray with a bvh returning either the first or any intersection // depending on `find_any`. Returns the ray distance , the instance id, // the shape element index and the element barycentric coordinates. -shape_intersection intersect_shape_ebvh(const shape_ebvh& bvh, +shape_intersection intersect_shape_ebvh(const shape_ebvh& sbvh, const shape_data& shape, const ray3f& ray, bool find_any) { RTCRayHit embree_ray; embree_ray.ray.org_x = ray.o.x; @@ -1056,7 +1065,7 @@ shape_intersection intersect_shape_ebvh(const shape_ebvh& bvh, embree_ray.hit.instID[0] = RTC_INVALID_GEOMETRY_ID; RTCIntersectContext embree_ctx; rtcInitIntersectContext(&embree_ctx); - rtcIntersect1((RTCScene)bvh.ebvh.get(), &embree_ctx, &embree_ray); + rtcIntersect1((RTCScene)sbvh.ebvh.get(), &embree_ctx, &embree_ray); if (embree_ray.hit.geomID == RTC_INVALID_GEOMETRY_ID) return {}; auto element = (int)embree_ray.hit.primID; auto uv = vec2f{embree_ray.hit.u, embree_ray.hit.v}; @@ -1064,7 +1073,7 @@ shape_intersection intersect_shape_ebvh(const shape_ebvh& bvh, return {element, uv, distance, true}; } -scene_intersection intersect_scene_ebvh(const scene_ebvh& bvh, +scene_intersection intersect_scene_ebvh(const scene_ebvh& sbvh, const scene_data& scene, const ray3f& ray, bool find_any) { RTCRayHit embree_ray; embree_ray.ray.org_x = ray.o.x; @@ -1082,7 +1091,7 @@ scene_intersection intersect_scene_ebvh(const scene_ebvh& bvh, embree_ray.hit.instID[0] = RTC_INVALID_GEOMETRY_ID; RTCIntersectContext embree_ctx; rtcInitIntersectContext(&embree_ctx); - rtcIntersect1((RTCScene)bvh.instances.ebvh.get(), &embree_ctx, &embree_ray); + rtcIntersect1((RTCScene)sbvh.instances.ebvh.get(), &embree_ctx, &embree_ray); if (embree_ray.hit.geomID == RTC_INVALID_GEOMETRY_ID) return {}; auto instance = (int)embree_ray.hit.instID[0]; auto element = (int)embree_ray.hit.primID; @@ -1091,11 +1100,11 @@ scene_intersection intersect_scene_ebvh(const scene_ebvh& bvh, return {instance, element, uv, distance, true}; } -scene_intersection intersect_instance_ebvh(const scene_ebvh& bvh, +scene_intersection intersect_instance_ebvh(const scene_ebvh& sbvh, const scene_data& scene, int instance_, const ray3f& ray, bool find_any) { auto& instance = scene.instances[instance_]; auto inv_ray = transform_ray(inverse(instance.frame, true), ray); - auto intersection = intersect_shape_ebvh(bvh.shapes[instance.shape], + auto intersection = intersect_shape_ebvh(sbvh.shapes[instance.shape], scene.shapes[instance.shape], inv_ray, find_any); if (!intersection.hit) return {}; return {instance_, intersection.element, intersection.uv, @@ -1117,24 +1126,24 @@ scene_ebvh make_scene_ebvh( } // Not implemented -void update_shape_ebvh(shape_ebvh& bvh, const shape_data& shape) { +void update_shape_ebvh(shape_ebvh& sbvh, const shape_data& shape) { throw embree_error{"Embree not available"}; } -void update_scene_ebvh(scene_ebvh& bvh, const scene_data& scene, +void update_scene_ebvh(scene_ebvh& sbvh, const scene_data& scene, const vector<int>& updated_instances, const vector<int>& updated_shapes) { throw embree_error{"Embree not available"}; } // Not implemented -shape_intersection intersect_shape_ebvh(const shape_ebvh& bvh, +shape_intersection intersect_shape_ebvh(const shape_ebvh& sbvh, const shape_data& shape, const ray3f& ray, bool find_any) { throw embree_error{"Embree not available"}; } -scene_intersection intersect_scene_ebvh(const scene_ebvh& bvh, +scene_intersection intersect_scene_ebvh(const scene_ebvh& sbvh, const scene_data& scene, const ray3f& ray, bool find_any) { throw embree_error{"Embree not available"}; } -scene_intersection intersect_instance_ebvh(const scene_ebvh& bvh, +scene_intersection intersect_instance_ebvh(const scene_ebvh& sbvh, const scene_data& scene, int instance, const ray3f& ray, bool find_any) { throw embree_error{"Embree not available"}; } diff --git a/libs/yocto/yocto_bvh.h b/libs/yocto/yocto_bvh.h index 821042eb7..d97f19cbb 100644 --- a/libs/yocto/yocto_bvh.h +++ b/libs/yocto/yocto_bvh.h @@ -67,13 +67,15 @@ using std::vector; namespace yocto { // Shape BVHs are just the bvh for the shape. -using shape_bvh = bvh_tree; +struct shape_bvh { + bvh_tree bvh = {}; +}; // Scene BVHs store the bvh for instances and shapes. // Application data is not stored explicitly. struct scene_bvh { - bvh_tree instances = {}; - vector<bvh_tree> shapes = {}; + bvh_tree bvh = {}; + vector<shape_bvh> shapes = {}; }; // Build the bvh acceleration structure. From d38fb4f3516d604fcd072f484fc1e10ac86c4a90 Mon Sep 17 00:00:00 2001 From: Fabio Pellacini <fabio.pellacini@gmail.com> Date: Sun, 7 Aug 2022 10:44:46 +0200 Subject: [PATCH 6/9] updated --- libs/yocto/yocto_bvh.cpp | 12 ++++++------ libs/yocto/yocto_bvh.h | 12 ++++++------ libs/yocto/yocto_trace.cpp | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/libs/yocto/yocto_bvh.cpp b/libs/yocto/yocto_bvh.cpp index ff4af3f71..38e6c51de 100644 --- a/libs/yocto/yocto_bvh.cpp +++ b/libs/yocto/yocto_bvh.cpp @@ -999,10 +999,10 @@ scene_ebvh make_scene_ebvh( } // scene bvh - auto edevice = embree_device(); - sbvh.instances.ebvh = unique_ptr<void, void (*)(void*)>{ - rtcNewScene(edevice), &clear_ebvh}; - auto escene = (RTCScene)sbvh.instances.ebvh.get(); + auto edevice = embree_device(); + sbvh.ebvh = unique_ptr<void, void (*)(void*)>{ + rtcNewScene(edevice), &clear_ebvh}; + auto escene = (RTCScene)sbvh.ebvh.get(); if (highquality) { rtcSetSceneBuildQuality(escene, RTC_BUILD_QUALITY_HIGH); } else { @@ -1031,7 +1031,7 @@ void update_shape_ebvh(shape_ebvh& sbvh, const shape_data& shape) { void update_scene_ebvh(scene_ebvh& sbvh, const scene_data& scene, const vector<int>& updated_instances, const vector<int>& updated_shapes) { // scene bvh - auto escene = (RTCScene)sbvh.instances.ebvh.get(); + auto escene = (RTCScene)sbvh.ebvh.get(); for (auto instance_id : updated_instances) { auto& instance = scene.instances[instance_id]; auto embree_geom = rtcGetGeometry(escene, instance_id); @@ -1091,7 +1091,7 @@ scene_intersection intersect_scene_ebvh(const scene_ebvh& sbvh, embree_ray.hit.instID[0] = RTC_INVALID_GEOMETRY_ID; RTCIntersectContext embree_ctx; rtcInitIntersectContext(&embree_ctx); - rtcIntersect1((RTCScene)sbvh.instances.ebvh.get(), &embree_ctx, &embree_ray); + rtcIntersect1((RTCScene)sbvh.ebvh.get(), &embree_ctx, &embree_ray); if (embree_ray.hit.geomID == RTC_INVALID_GEOMETRY_ID) return {}; auto instance = (int)embree_ray.hit.instID[0]; auto element = (int)embree_ray.hit.primID; diff --git a/libs/yocto/yocto_bvh.h b/libs/yocto/yocto_bvh.h index d97f19cbb..1fe6cffc4 100644 --- a/libs/yocto/yocto_bvh.h +++ b/libs/yocto/yocto_bvh.h @@ -131,17 +131,17 @@ scene_intersection overlap_scene_bvh(const scene_bvh& bvh, namespace yocto { // Wrapper for Intel's Embree -struct ebvh_tree { - unique_ptr<void, void (*)(void*)> ebvh = {nullptr, nullptr}; -}; +using ebvh_tree = unique_ptr<void, void (*)(void*)>; // Wrapper for Intel Embree. -using shape_ebvh = ebvh_tree; +struct shape_ebvh { + ebvh_tree ebvh = {nullptr, nullptr}; +}; // Wrapper for Intel Embree. struct scene_ebvh { - ebvh_tree instances = {}; // instances - vector<ebvh_tree> shapes = {}; // shapes + ebvh_tree ebvh = {nullptr, nullptr}; // instances + vector<shape_ebvh> shapes = {}; // shapes }; // Check if embree is supported diff --git a/libs/yocto/yocto_trace.cpp b/libs/yocto/yocto_trace.cpp index 2c3a664f8..82d049b06 100644 --- a/libs/yocto/yocto_trace.cpp +++ b/libs/yocto/yocto_trace.cpp @@ -98,7 +98,7 @@ trace_bvh make_trace_bvh(const scene_data& scene, const trace_params& params) { // Ray-intersection shortcuts static scene_intersection intersect_scene(const trace_bvh& bvh, const scene_data& scene, const ray3f& ray, bool find_any = false) { - if (bvh.ebvh.instances.ebvh) { + if (bvh.ebvh.ebvh) { return intersect_scene_ebvh(bvh.ebvh, scene, ray, find_any); } else { return intersect_scene_bvh(bvh.bvh, scene, ray, find_any); @@ -107,7 +107,7 @@ static scene_intersection intersect_scene(const trace_bvh& bvh, static scene_intersection intersect_instance(const trace_bvh& bvh, const scene_data& scene, int instance, const ray3f& ray, bool find_any = false) { - if (bvh.ebvh.instances.ebvh) { + if (bvh.ebvh.ebvh) { return intersect_instance_ebvh(bvh.ebvh, scene, instance, ray, find_any); } else { return intersect_instance_bvh(bvh.bvh, scene, instance, ray, find_any); From 72b93f2e192c47fbe7661d9733efbd2ec05261f6 Mon Sep 17 00:00:00 2001 From: Fabio Pellacini <fabio.pellacini@gmail.com> Date: Sun, 7 Aug 2022 15:06:23 +0200 Subject: [PATCH 7/9] updated --- libs/yocto/yocto_cutrace.cpp | 44 ++++++++++++++++++------------------ libs/yocto/yocto_cutrace.h | 31 +++++++++++++------------ 2 files changed, 38 insertions(+), 37 deletions(-) diff --git a/libs/yocto/yocto_cutrace.cpp b/libs/yocto/yocto_cutrace.cpp index 1097f1f63..c9ba31518 100644 --- a/libs/yocto/yocto_cutrace.cpp +++ b/libs/yocto/yocto_cutrace.cpp @@ -223,22 +223,22 @@ cuscene_data::~cuscene_data() { clear_buffer(environments); }; -cubvh_data::cubvh_data(cubvh_data&& other) { +cuscene_bvh::cuscene_bvh(cuscene_bvh&& other) { instances.swap(other.instances); - shapes_bvhs.swap(other.shapes_bvhs); - instances_bvh.buffer.swap(other.instances_bvh.buffer); - std::swap(instances_bvh.handle, other.instances_bvh.handle); + shapes.swap(other.shapes); + bvh.buffer.swap(other.bvh.buffer); + std::swap(bvh.handle, other.bvh.handle); } -cubvh_data& cubvh_data::operator=(cubvh_data&& other) { +cuscene_bvh& cuscene_bvh::operator=(cuscene_bvh&& other) { instances.swap(other.instances); - shapes_bvhs.swap(other.shapes_bvhs); - instances_bvh.buffer.swap(other.instances_bvh.buffer); - std::swap(instances_bvh.handle, other.instances_bvh.handle); + shapes.swap(other.shapes); + bvh.buffer.swap(other.bvh.buffer); + std::swap(bvh.handle, other.bvh.handle); return *this; } -cubvh_data::~cubvh_data() { - for (auto& shape_bvh : shapes_bvhs) { - clear_buffer(shape_bvh.buffer); +cuscene_bvh::~cuscene_bvh() { + for (auto& bvh : shapes) { + clear_buffer(bvh.buffer); // TODO: bvh } clear_buffer(instances); @@ -505,7 +505,7 @@ cutrace_context make_cutrace_context(const trace_params& params) { // start a new render void trace_start(cutrace_context& context, cutrace_state& state, - const cuscene_data& cuscene, const cubvh_data& bvh, + const cuscene_data& cuscene, const cuscene_bvh& bvh, const cutrace_lights& lights, const scene_data& scene, const trace_params& params) { auto globals = cutrace_globals{}; @@ -514,7 +514,7 @@ void trace_start(cutrace_context& context, cutrace_state& state, update_buffer_value(context.cuda_stream, context.globals_buffer, offsetof(cutrace_globals, scene), cuscene); update_buffer_value(context.cuda_stream, context.globals_buffer, - offsetof(cutrace_globals, bvh), bvh.instances_bvh.handle); + offsetof(cutrace_globals, bvh), bvh.bvh.handle); update_buffer_value(context.cuda_stream, context.globals_buffer, offsetof(cutrace_globals, lights), lights); update_buffer_value(context.cuda_stream, context.globals_buffer, @@ -525,7 +525,7 @@ void trace_start(cutrace_context& context, cutrace_state& state, // render a batch of samples void trace_samples(cutrace_context& context, cutrace_state& state, - const cuscene_data& cuscene, const cubvh_data& bvh, + const cuscene_data& cuscene, const cuscene_bvh& bvh, const cutrace_lights& lights, const scene_data& scene, const trace_params& params) { if (state.samples >= params.samples) return; @@ -700,9 +700,9 @@ void update_cutrace_cameras(cutrace_context& context, cuscene_data& cuscene, sync_gpu(context.cuda_stream); } -cubvh_data make_cutrace_bvh(cutrace_context& context, const cuscene_data& scene, - const trace_params& params) { - auto bvh = cubvh_data{}; +cutrace_bvh make_cutrace_bvh(cutrace_context& context, + const cuscene_data& scene, const trace_params& params) { + auto bvh = cutrace_bvh{}; // download shapes and instances // this is not efficient, but keeps the API very clean @@ -711,7 +711,7 @@ cubvh_data make_cutrace_bvh(cutrace_context& context, const cuscene_data& scene, auto instances_data = download_buffer_vector(scene.instances); // shapes - bvh.shapes_bvhs.resize(scene.shapes.size()); + bvh.shapes.resize(scene.shapes.size()); for (auto shape_id = (size_t)0; shape_id < scene.shapes.size(); shape_id++) { auto& shape = shapes_data[shape_id]; @@ -757,7 +757,7 @@ cubvh_data make_cutrace_bvh(cutrace_context& context, const cuscene_data& scene, context.cuda_stream, accelerator_sizes.tempSizeInBytes, (byte*)nullptr); auto bvh_buffer = make_buffer(context.cuda_stream, accelerator_sizes.outputSizeInBytes, (byte*)nullptr); - auto& sbvh = bvh.shapes_bvhs[shape_id]; + auto& sbvh = bvh.shapes[shape_id]; check_result(optixAccelBuild(context.optix_context, /* cuda_stream */ 0, &accelerator_options, &built_input, (int)1, temporary_buffer.device_ptr(), temporary_buffer.size_in_bytes(), @@ -796,7 +796,7 @@ cubvh_data make_cutrace_bvh(cutrace_context& context, const cuscene_data& scene, memcpy(opinstance.transform, &transform, sizeof(float) * 12); opinstance.sbtOffset = 0; opinstance.instanceId = instance_id; - opinstance.traversableHandle = bvh.shapes_bvhs[instance.shape].handle; + opinstance.traversableHandle = bvh.shapes[instance.shape].handle; opinstance.flags = OPTIX_INSTANCE_FLAG_NONE; opinstance.visibilityMask = 0xff; } @@ -830,7 +830,7 @@ cubvh_data make_cutrace_bvh(cutrace_context& context, const cuscene_data& scene, auto bvh_buffer = make_buffer(context.cuda_stream, accelerator_sizes.outputSizeInBytes, (byte*)nullptr); - auto& ibvh = bvh.instances_bvh; + auto& ibvh = bvh.bvh; check_result(optixAccelBuild(context.optix_context, /* cuda_stream */ 0, &accelerator_options, &build_input, (int)1, temporary_buffer.device_ptr(), temporary_buffer.size_in_bytes(), @@ -979,7 +979,7 @@ image_data cutrace_image(const scene_data& scene, const trace_params& params) { // render preview void trace_preview(image_data& image, cutrace_context& context, - cutrace_state& pstate, const cuscene_data& cuscene, const cubvh_data& bvh, + cutrace_state& pstate, const cuscene_data& cuscene, const cutrace_bvh& bvh, const cutrace_lights& lights, const scene_data& scene, const trace_params& params) { auto pparams = params; diff --git a/libs/yocto/yocto_cutrace.h b/libs/yocto/yocto_cutrace.h index d373d44ef..27302365a 100644 --- a/libs/yocto/yocto_cutrace.h +++ b/libs/yocto/yocto_cutrace.h @@ -79,10 +79,11 @@ namespace yocto { // forward declarations struct cuscene_data; -struct cubvh_data; +struct cuscene_bvh; struct cutrace_state; struct cutrace_lights; struct cutrace_context; +using cutrace_bvh = cuscene_bvh; // Initialize GPU context. cutrace_context make_cutrace_context(const trace_params& params); @@ -94,7 +95,7 @@ void update_cutrace_cameras(cutrace_context& context, cuscene_data& cuscene, const scene_data& scene, const trace_params& params); // Build the bvh acceleration structure. -cubvh_data make_cutrace_bvh(cutrace_context& context, +cutrace_bvh make_cutrace_bvh(cutrace_context& context, const cuscene_data& cuscene, const trace_params& params); // Initialize state. @@ -109,18 +110,18 @@ cutrace_lights make_cutrace_lights(cutrace_context& context, // Start rendering an image. void trace_start(cutrace_context& context, cutrace_state& state, - const cuscene_data& cuscene, const cubvh_data& bvh, + const cuscene_data& cuscene, const cutrace_bvh& bvh, const cutrace_lights& lights, const scene_data& scene, const trace_params& params); // Progressively computes an image. void trace_samples(cutrace_context& context, cutrace_state& state, - const cuscene_data& cuscene, const cubvh_data& bvh, + const cuscene_data& cuscene, const cutrace_bvh& bvh, const cutrace_lights& lights, const scene_data& scene, const trace_params& params); void trace_preview(image_data& image, cutrace_context& context, - cutrace_state& pstate, const cuscene_data& cuscene, const cubvh_data& bvh, + cutrace_state& pstate, const cuscene_data& cuscene, const cutrace_bvh& bvh, const cutrace_lights& lights, const scene_data& scene, const trace_params& params); @@ -191,8 +192,8 @@ struct cuspan { CUdeviceptr device_ptr() const { return _data; } size_t size_in_bytes() const { return _size * sizeof(T); } void swap(cuspan& other) { - std::swap(_data, other._data); - std::swap(_size, other._size); + std::swap(_data, other._data); + std::swap(_size, other._size); } CUdeviceptr _data = 0; @@ -283,15 +284,15 @@ struct cubvh_tree { OptixTraversableHandle handle = 0; }; -struct cubvh_data { - cuspan<OptixInstance> instances = {}; - cubvh_tree instances_bvh = {}; - vector<cubvh_tree> shapes_bvhs = {}; +struct cuscene_bvh { + cubvh_tree bvh = {}; + vector<cubvh_tree> shapes = {}; + cuspan<OptixInstance> instances = {}; - cubvh_data() {} - cubvh_data(cubvh_data&&); - cubvh_data& operator=(cubvh_data&&); - ~cubvh_data(); + cuscene_bvh() {} + cuscene_bvh(cuscene_bvh&&); + cuscene_bvh& operator=(cuscene_bvh&&); + ~cuscene_bvh(); }; // state From 1f9c4ddccb48c1cea3717e417304ab4aa4135160 Mon Sep 17 00:00:00 2001 From: Fabio Pellacini <fabio.pellacini@gmail.com> Date: Sun, 7 Aug 2022 15:13:23 +0200 Subject: [PATCH 8/9] updated --- libs/yocto/yocto_cutrace.cpp | 23 ++++++++++++++--------- libs/yocto/yocto_cutrace.h | 11 ++++++++++- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/libs/yocto/yocto_cutrace.cpp b/libs/yocto/yocto_cutrace.cpp index c9ba31518..eaaa828eb 100644 --- a/libs/yocto/yocto_cutrace.cpp +++ b/libs/yocto/yocto_cutrace.cpp @@ -223,6 +223,17 @@ cuscene_data::~cuscene_data() { clear_buffer(environments); }; +cushape_bvh::cushape_bvh(cushape_bvh&& other) { + bvh.buffer.swap(other.bvh.buffer); + std::swap(bvh.handle, other.bvh.handle); +} +cushape_bvh& cushape_bvh::operator=(cushape_bvh&& other) { + bvh.buffer.swap(other.bvh.buffer); + std::swap(bvh.handle, other.bvh.handle); + return *this; +} +cushape_bvh::~cushape_bvh() { clear_buffer(bvh.buffer); } + cuscene_bvh::cuscene_bvh(cuscene_bvh&& other) { instances.swap(other.instances); shapes.swap(other.shapes); @@ -236,13 +247,7 @@ cuscene_bvh& cuscene_bvh::operator=(cuscene_bvh&& other) { std::swap(bvh.handle, other.bvh.handle); return *this; } -cuscene_bvh::~cuscene_bvh() { - for (auto& bvh : shapes) { - clear_buffer(bvh.buffer); - // TODO: bvh - } - clear_buffer(instances); -} +cuscene_bvh::~cuscene_bvh() { clear_buffer(instances); } cutrace_context::cutrace_context(cutrace_context&& other) { std::swap(denoiser, other.denoiser); @@ -757,7 +762,7 @@ cutrace_bvh make_cutrace_bvh(cutrace_context& context, context.cuda_stream, accelerator_sizes.tempSizeInBytes, (byte*)nullptr); auto bvh_buffer = make_buffer(context.cuda_stream, accelerator_sizes.outputSizeInBytes, (byte*)nullptr); - auto& sbvh = bvh.shapes[shape_id]; + auto& sbvh = bvh.shapes[shape_id].bvh; check_result(optixAccelBuild(context.optix_context, /* cuda_stream */ 0, &accelerator_options, &built_input, (int)1, temporary_buffer.device_ptr(), temporary_buffer.size_in_bytes(), @@ -796,7 +801,7 @@ cutrace_bvh make_cutrace_bvh(cutrace_context& context, memcpy(opinstance.transform, &transform, sizeof(float) * 12); opinstance.sbtOffset = 0; opinstance.instanceId = instance_id; - opinstance.traversableHandle = bvh.shapes[instance.shape].handle; + opinstance.traversableHandle = bvh.shapes[instance.shape].bvh.handle; opinstance.flags = OPTIX_INSTANCE_FLAG_NONE; opinstance.visibilityMask = 0xff; } diff --git a/libs/yocto/yocto_cutrace.h b/libs/yocto/yocto_cutrace.h index 27302365a..ba62c7b2e 100644 --- a/libs/yocto/yocto_cutrace.h +++ b/libs/yocto/yocto_cutrace.h @@ -284,9 +284,18 @@ struct cubvh_tree { OptixTraversableHandle handle = 0; }; +struct cushape_bvh { + cubvh_tree bvh = {}; + + cushape_bvh() {} + cushape_bvh(cushape_bvh&&); + cushape_bvh& operator=(cushape_bvh&&); + ~cushape_bvh(); +}; + struct cuscene_bvh { cubvh_tree bvh = {}; - vector<cubvh_tree> shapes = {}; + vector<cushape_bvh> shapes = {}; cuspan<OptixInstance> instances = {}; cuscene_bvh() {} From 38e7d2106760d7aed590a309d7871bfcfea99ece Mon Sep 17 00:00:00 2001 From: Fabio Pellacini <fabio.pellacini@gmail.com> Date: Sun, 7 Aug 2022 15:21:40 +0200 Subject: [PATCH 9/9] updated --- libs/yocto/yocto_cutrace.cpp | 13 ++++++++++++- libs/yocto/yocto_cutrace.h | 5 +++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/libs/yocto/yocto_cutrace.cpp b/libs/yocto/yocto_cutrace.cpp index eaaa828eb..b31459695 100644 --- a/libs/yocto/yocto_cutrace.cpp +++ b/libs/yocto/yocto_cutrace.cpp @@ -223,6 +223,17 @@ cuscene_data::~cuscene_data() { clear_buffer(environments); }; +cubvh_tree::cubvh_tree(cubvh_tree&& other) { + buffer.swap(other.buffer); + std::swap(handle, other.handle); +} +cubvh_tree& cubvh_tree::operator=(cubvh_tree&& other) { + buffer.swap(other.buffer); + std::swap(handle, other.handle); + return *this; +} +cubvh_tree::~cubvh_tree() { clear_buffer(buffer); } + cushape_bvh::cushape_bvh(cushape_bvh&& other) { bvh.buffer.swap(other.bvh.buffer); std::swap(bvh.handle, other.bvh.handle); @@ -232,7 +243,7 @@ cushape_bvh& cushape_bvh::operator=(cushape_bvh&& other) { std::swap(bvh.handle, other.bvh.handle); return *this; } -cushape_bvh::~cushape_bvh() { clear_buffer(bvh.buffer); } +cushape_bvh::~cushape_bvh() {} cuscene_bvh::cuscene_bvh(cuscene_bvh&& other) { instances.swap(other.instances); diff --git a/libs/yocto/yocto_cutrace.h b/libs/yocto/yocto_cutrace.h index ba62c7b2e..779384ba5 100644 --- a/libs/yocto/yocto_cutrace.h +++ b/libs/yocto/yocto_cutrace.h @@ -282,6 +282,11 @@ struct cuscene_data { struct cubvh_tree { cuspan<byte> buffer = {}; OptixTraversableHandle handle = 0; + + cubvh_tree() {} + cubvh_tree(cubvh_tree&&); + cubvh_tree& operator=(cubvh_tree&&); + ~cubvh_tree(); }; struct cushape_bvh {