1 | // Copyright 2009-2021 Intel Corporation |
2 | // SPDX-License-Identifier: Apache-2.0 |
3 | |
4 | #pragma once |
5 | |
6 | #include "default.h" |
7 | #include "rtcore.h" |
8 | #include "point_query.h" |
9 | |
10 | namespace embree |
11 | { |
12 | class Scene; |
13 | |
14 | struct IntersectContext |
15 | { |
16 | public: |
17 | __forceinline IntersectContext(Scene* scene, RTCIntersectContext* user_context) |
18 | : scene(scene), user(user_context) {} |
19 | |
20 | __forceinline bool hasContextFilter() const { |
21 | return user->filter != nullptr; |
22 | } |
23 | |
24 | __forceinline bool isCoherent() const { |
25 | return embree::isCoherent(flags: user->flags); |
26 | } |
27 | |
28 | __forceinline bool isIncoherent() const { |
29 | return embree::isIncoherent(flags: user->flags); |
30 | } |
31 | |
32 | public: |
33 | Scene* scene; |
34 | RTCIntersectContext* user; |
35 | }; |
36 | |
37 | template<int M, typename Geometry> |
38 | __forceinline Vec4vf<M> enlargeRadiusToMinWidth(const IntersectContext* context, const Geometry* geom, const Vec3vf<M>& ray_org, const Vec4vf<M>& v) |
39 | { |
40 | #if RTC_MIN_WIDTH |
41 | const vfloat<M> d = length(Vec3vf<M>(v) - ray_org); |
42 | const vfloat<M> r = clamp(context->user->minWidthDistanceFactor*d, v.w, geom->maxRadiusScale*v.w); |
43 | return Vec4vf<M>(v.x,v.y,v.z,r); |
44 | #else |
45 | return v; |
46 | #endif |
47 | } |
48 | |
49 | template<typename Geometry> |
50 | __forceinline Vec3ff enlargeRadiusToMinWidth(const IntersectContext* context, const Geometry* geom, const Vec3fa& ray_org, const Vec3ff& v) |
51 | { |
52 | #if RTC_MIN_WIDTH |
53 | const float d = length(Vec3fa(v) - ray_org); |
54 | const float r = clamp(context->user->minWidthDistanceFactor*d, v.w, geom->maxRadiusScale*v.w); |
55 | return Vec3ff(v.x,v.y,v.z,r); |
56 | #else |
57 | return v; |
58 | #endif |
59 | } |
60 | |
61 | enum PointQueryType |
62 | { |
63 | POINT_QUERY_TYPE_UNDEFINED = 0, |
64 | POINT_QUERY_TYPE_SPHERE = 1, |
65 | POINT_QUERY_TYPE_AABB = 2, |
66 | }; |
67 | |
68 | typedef bool (*PointQueryFunction)(struct RTCPointQueryFunctionArguments* args); |
69 | |
70 | struct PointQueryContext |
71 | { |
72 | public: |
73 | __forceinline PointQueryContext(Scene* scene, |
74 | PointQuery* query_ws, |
75 | PointQueryType query_type, |
76 | PointQueryFunction func, |
77 | RTCPointQueryContext* userContext, |
78 | float similarityScale, |
79 | void* userPtr) |
80 | : scene(scene) |
81 | , query_ws(query_ws) |
82 | , query_type(query_type) |
83 | , func(func) |
84 | , userContext(userContext) |
85 | , similarityScale(similarityScale) |
86 | , userPtr(userPtr) |
87 | , primID(RTC_INVALID_GEOMETRY_ID) |
88 | , geomID(RTC_INVALID_GEOMETRY_ID) |
89 | , query_radius(query_ws->radius) |
90 | { |
91 | if (query_type == POINT_QUERY_TYPE_AABB) { |
92 | assert(similarityScale == 0.f); |
93 | updateAABB(); |
94 | } |
95 | if (userContext->instStackSize == 0) { |
96 | assert(similarityScale == 1.f); |
97 | } |
98 | } |
99 | |
100 | public: |
101 | __forceinline void updateAABB() |
102 | { |
103 | if (likely(query_ws->radius == (float)inf || userContext->instStackSize == 0)) { |
104 | query_radius = Vec3fa(query_ws->radius); |
105 | return; |
106 | } |
107 | |
108 | const AffineSpace3fa m = AffineSpace3fa_load_unaligned(ptr: (AffineSpace3fa*)userContext->world2inst[userContext->instStackSize-1]); |
109 | BBox3fa bbox(Vec3fa(-query_ws->radius), Vec3fa(query_ws->radius)); |
110 | bbox = xfmBounds(m, b: bbox); |
111 | query_radius = 0.5f * (bbox.upper - bbox.lower); |
112 | } |
113 | |
114 | public: |
115 | Scene* scene; |
116 | |
117 | PointQuery* query_ws; // the original world space point query |
118 | PointQueryType query_type; |
119 | PointQueryFunction func; |
120 | RTCPointQueryContext* userContext; |
121 | const float similarityScale; |
122 | |
123 | void* userPtr; |
124 | |
125 | unsigned int primID; |
126 | unsigned int geomID; |
127 | |
128 | Vec3fa query_radius; // used if the query is converted to an AABB internally |
129 | }; |
130 | } |
131 | |
132 | |