1 // Copyright 2009-2021 Intel Corporation 2 // SPDX-License-Identifier: Apache-2.0 3 4 #include "instance_intersector.h" 5 #include "../common/scene.h" 6 #include "../common/instance_stack.h" 7 8 namespace embree 9 { 10 namespace isa 11 { 12 13 /* Push an instance to the stack. */ pushInstance(RTCPointQueryContext * context,unsigned int instanceId,AffineSpace3fa const & w2i,AffineSpace3fa const & i2w)14 RTC_FORCEINLINE bool pushInstance(RTCPointQueryContext* context, 15 unsigned int instanceId, 16 AffineSpace3fa const& w2i, 17 AffineSpace3fa const& i2w) 18 { 19 assert(context); 20 const size_t stackSize = context->instStackSize; 21 assert(stackSize < RTC_MAX_INSTANCE_LEVEL_COUNT); 22 context->instID[stackSize] = instanceId; 23 24 AffineSpace3fa_store_unaligned(w2i,(AffineSpace3fa*)context->world2inst[stackSize]); 25 AffineSpace3fa_store_unaligned(i2w,(AffineSpace3fa*)context->inst2world[stackSize]); 26 27 if (unlikely(stackSize > 0)) 28 { 29 const AffineSpace3fa world2inst = AffineSpace3fa_load_unaligned((AffineSpace3fa*)context->world2inst[stackSize ]) 30 * AffineSpace3fa_load_unaligned((AffineSpace3fa*)context->world2inst[stackSize-1]); 31 const AffineSpace3fa inst2world = AffineSpace3fa_load_unaligned((AffineSpace3fa*)context->inst2world[stackSize-1]) 32 * AffineSpace3fa_load_unaligned((AffineSpace3fa*)context->inst2world[stackSize ]); 33 AffineSpace3fa_store_unaligned(world2inst,(AffineSpace3fa*)context->world2inst[stackSize]); 34 AffineSpace3fa_store_unaligned(inst2world,(AffineSpace3fa*)context->inst2world[stackSize]); 35 } 36 context->instStackSize++; 37 return true; 38 } 39 40 /* Pop the last instance pushed to the stack. Do not call on an empty stack. */ popInstance(RTCPointQueryContext * context)41 RTC_FORCEINLINE void popInstance(RTCPointQueryContext* context) 42 { 43 assert(context && context->instStackSize > 0); 44 context->instID[--context->instStackSize] = RTC_INVALID_GEOMETRY_ID; 45 } 46 intersect(const Precalculations & pre,RayHit & ray,IntersectContext * context,const InstancePrimitive & prim)47 void InstanceIntersector1::intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const InstancePrimitive& prim) 48 { 49 const Instance* instance = prim.instance; 50 51 /* perform ray mask test */ 52 #if defined(EMBREE_RAY_MASK) 53 if ((ray.mask & instance->mask) == 0) 54 return; 55 #endif 56 57 RTCIntersectContext* user_context = context->user; 58 if (likely(instance_id_stack::push(user_context, prim.instID_))) 59 { 60 const AffineSpace3fa world2local = instance->getWorld2Local(); 61 const Vec3ff ray_org = ray.org; 62 const Vec3ff ray_dir = ray.dir; 63 ray.org = Vec3ff(xfmPoint(world2local, ray_org), ray.tnear()); 64 ray.dir = Vec3ff(xfmVector(world2local, ray_dir), ray.time()); 65 IntersectContext newcontext((Scene*)instance->object, user_context); 66 instance->object->intersectors.intersect((RTCRayHit&)ray, &newcontext); 67 ray.org = ray_org; 68 ray.dir = ray_dir; 69 instance_id_stack::pop(user_context); 70 } 71 } 72 occluded(const Precalculations & pre,Ray & ray,IntersectContext * context,const InstancePrimitive & prim)73 bool InstanceIntersector1::occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const InstancePrimitive& prim) 74 { 75 const Instance* instance = prim.instance; 76 77 /* perform ray mask test */ 78 #if defined(EMBREE_RAY_MASK) 79 if ((ray.mask & instance->mask) == 0) 80 return false; 81 #endif 82 83 RTCIntersectContext* user_context = context->user; 84 bool occluded = false; 85 if (likely(instance_id_stack::push(user_context, prim.instID_))) 86 { 87 const AffineSpace3fa world2local = instance->getWorld2Local(); 88 const Vec3ff ray_org = ray.org; 89 const Vec3ff ray_dir = ray.dir; 90 ray.org = Vec3ff(xfmPoint(world2local, ray_org), ray.tnear()); 91 ray.dir = Vec3ff(xfmVector(world2local, ray_dir), ray.time()); 92 IntersectContext newcontext((Scene*)instance->object, user_context); 93 instance->object->intersectors.occluded((RTCRay&)ray, &newcontext); 94 ray.org = ray_org; 95 ray.dir = ray_dir; 96 occluded = ray.tfar < 0.0f; 97 instance_id_stack::pop(user_context); 98 } 99 return occluded; 100 } 101 pointQuery(PointQuery * query,PointQueryContext * context,const InstancePrimitive & prim)102 bool InstanceIntersector1::pointQuery(PointQuery* query, PointQueryContext* context, const InstancePrimitive& prim) 103 { 104 const Instance* instance = prim.instance; 105 106 const AffineSpace3fa local2world = instance->getLocal2World(); 107 const AffineSpace3fa world2local = instance->getWorld2Local(); 108 float similarityScale = 0.f; 109 const bool similtude = context->query_type == POINT_QUERY_TYPE_SPHERE 110 && similarityTransform(world2local, &similarityScale); 111 assert((similtude && similarityScale > 0) || !similtude); 112 113 if (likely(pushInstance(context->userContext, prim.instID_, world2local, local2world))) 114 { 115 PointQuery query_inst; 116 query_inst.time = query->time; 117 query_inst.p = xfmPoint(world2local, query->p); 118 query_inst.radius = query->radius * similarityScale; 119 120 PointQueryContext context_inst( 121 (Scene*)instance->object, 122 context->query_ws, 123 similtude ? POINT_QUERY_TYPE_SPHERE : POINT_QUERY_TYPE_AABB, 124 context->func, 125 context->userContext, 126 similarityScale, 127 context->userPtr); 128 129 bool changed = instance->object->intersectors.pointQuery(&query_inst, &context_inst); 130 popInstance(context->userContext); 131 return changed; 132 } 133 return false; 134 } 135 intersect(const Precalculations & pre,RayHit & ray,IntersectContext * context,const InstancePrimitive & prim)136 void InstanceIntersector1MB::intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const InstancePrimitive& prim) 137 { 138 const Instance* instance = prim.instance; 139 140 /* perform ray mask test */ 141 #if defined(EMBREE_RAY_MASK) 142 if ((ray.mask & instance->mask) == 0) 143 return; 144 #endif 145 146 RTCIntersectContext* user_context = context->user; 147 if (likely(instance_id_stack::push(user_context, prim.instID_))) 148 { 149 const AffineSpace3fa world2local = instance->getWorld2Local(ray.time()); 150 const Vec3ff ray_org = ray.org; 151 const Vec3ff ray_dir = ray.dir; 152 ray.org = Vec3ff(xfmPoint(world2local, ray_org), ray.tnear()); 153 ray.dir = Vec3ff(xfmVector(world2local, ray_dir), ray.time()); 154 IntersectContext newcontext((Scene*)instance->object, user_context); 155 instance->object->intersectors.intersect((RTCRayHit&)ray, &newcontext); 156 ray.org = ray_org; 157 ray.dir = ray_dir; 158 instance_id_stack::pop(user_context); 159 } 160 } 161 occluded(const Precalculations & pre,Ray & ray,IntersectContext * context,const InstancePrimitive & prim)162 bool InstanceIntersector1MB::occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const InstancePrimitive& prim) 163 { 164 const Instance* instance = prim.instance; 165 166 /* perform ray mask test */ 167 #if defined(EMBREE_RAY_MASK) 168 if ((ray.mask & instance->mask) == 0) 169 return false; 170 #endif 171 172 RTCIntersectContext* user_context = context->user; 173 bool occluded = false; 174 if (likely(instance_id_stack::push(user_context, prim.instID_))) 175 { 176 const AffineSpace3fa world2local = instance->getWorld2Local(ray.time()); 177 const Vec3ff ray_org = ray.org; 178 const Vec3ff ray_dir = ray.dir; 179 ray.org = Vec3ff(xfmPoint(world2local, ray_org), ray.tnear()); 180 ray.dir = Vec3ff(xfmVector(world2local, ray_dir), ray.time()); 181 IntersectContext newcontext((Scene*)instance->object, user_context); 182 instance->object->intersectors.occluded((RTCRay&)ray, &newcontext); 183 ray.org = ray_org; 184 ray.dir = ray_dir; 185 occluded = ray.tfar < 0.0f; 186 instance_id_stack::pop(user_context); 187 } 188 return occluded; 189 } 190 pointQuery(PointQuery * query,PointQueryContext * context,const InstancePrimitive & prim)191 bool InstanceIntersector1MB::pointQuery(PointQuery* query, PointQueryContext* context, const InstancePrimitive& prim) 192 { 193 const Instance* instance = prim.instance; 194 195 const AffineSpace3fa local2world = instance->getLocal2World(query->time); 196 const AffineSpace3fa world2local = instance->getWorld2Local(query->time); 197 float similarityScale = 0.f; 198 const bool similtude = context->query_type == POINT_QUERY_TYPE_SPHERE 199 && similarityTransform(world2local, &similarityScale); 200 201 if (likely(pushInstance(context->userContext, prim.instID_, world2local, local2world))) 202 { 203 PointQuery query_inst; 204 query_inst.time = query->time; 205 query_inst.p = xfmPoint(world2local, query->p); 206 query_inst.radius = query->radius * similarityScale; 207 208 PointQueryContext context_inst( 209 (Scene*)instance->object, 210 context->query_ws, 211 similtude ? POINT_QUERY_TYPE_SPHERE : POINT_QUERY_TYPE_AABB, 212 context->func, 213 context->userContext, 214 similarityScale, 215 context->userPtr); 216 217 bool changed = instance->object->intersectors.pointQuery(&query_inst, &context_inst); 218 popInstance(context->userContext); 219 return changed; 220 } 221 return false; 222 } 223 224 template<int K> intersect(const vbool<K> & valid_i,const Precalculations & pre,RayHitK<K> & ray,IntersectContext * context,const InstancePrimitive & prim)225 void InstanceIntersectorK<K>::intersect(const vbool<K>& valid_i, const Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const InstancePrimitive& prim) 226 { 227 vbool<K> valid = valid_i; 228 const Instance* instance = prim.instance; 229 //ray.geomID = 10; 230 231 /* perform ray mask test */ 232 #if defined(EMBREE_RAY_MASK) 233 valid &= (ray.mask & instance->mask) != 0; 234 if (none(valid)) return; 235 #endif 236 237 RTCIntersectContext* user_context = context->user; 238 if (likely(instance_id_stack::push(user_context, prim.instID_))) 239 { 240 AffineSpace3vf<K> world2local = instance->getWorld2Local(); 241 const Vec3vf<K> ray_org = ray.org; 242 const Vec3vf<K> ray_dir = ray.dir; 243 ray.org = xfmPoint(world2local, ray_org); 244 ray.dir = xfmVector(world2local, ray_dir); 245 IntersectContext newcontext((Scene*)instance->object, user_context); 246 instance->object->intersectors.intersect(valid, ray, &newcontext); 247 ray.org = ray_org; 248 ray.dir = ray_dir; 249 instance_id_stack::pop(user_context); 250 } 251 } 252 253 template<int K> occluded(const vbool<K> & valid_i,const Precalculations & pre,RayK<K> & ray,IntersectContext * context,const InstancePrimitive & prim)254 vbool<K> InstanceIntersectorK<K>::occluded(const vbool<K>& valid_i, const Precalculations& pre, RayK<K>& ray, IntersectContext* context, const InstancePrimitive& prim) 255 { 256 vbool<K> valid = valid_i; 257 const Instance* instance = prim.instance; 258 259 /* perform ray mask test */ 260 #if defined(EMBREE_RAY_MASK) 261 valid &= (ray.mask & instance->mask) != 0; 262 if (none(valid)) return false; 263 #endif 264 265 RTCIntersectContext* user_context = context->user; 266 vbool<K> occluded = false; 267 if (likely(instance_id_stack::push(user_context, prim.instID_))) 268 { 269 AffineSpace3vf<K> world2local = instance->getWorld2Local(); 270 const Vec3vf<K> ray_org = ray.org; 271 const Vec3vf<K> ray_dir = ray.dir; 272 ray.org = xfmPoint(world2local, ray_org); 273 ray.dir = xfmVector(world2local, ray_dir); 274 IntersectContext newcontext((Scene*)instance->object, user_context); 275 instance->object->intersectors.occluded(valid, ray, &newcontext); 276 ray.org = ray_org; 277 ray.dir = ray_dir; 278 occluded = ray.tfar < 0.0f; 279 instance_id_stack::pop(user_context); 280 } 281 return occluded; 282 } 283 284 template<int K> intersect(const vbool<K> & valid_i,const Precalculations & pre,RayHitK<K> & ray,IntersectContext * context,const InstancePrimitive & prim)285 void InstanceIntersectorKMB<K>::intersect(const vbool<K>& valid_i, const Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const InstancePrimitive& prim) 286 { 287 vbool<K> valid = valid_i; 288 const Instance* instance = prim.instance; 289 290 /* perform ray mask test */ 291 #if defined(EMBREE_RAY_MASK) 292 valid &= (ray.mask & instance->mask) != 0; 293 if (none(valid)) return; 294 #endif 295 296 RTCIntersectContext* user_context = context->user; 297 if (likely(instance_id_stack::push(user_context, prim.instID_))) 298 { 299 AffineSpace3vf<K> world2local = instance->getWorld2Local<K>(valid, ray.time()); 300 const Vec3vf<K> ray_org = ray.org; 301 const Vec3vf<K> ray_dir = ray.dir; 302 ray.org = xfmPoint(world2local, ray_org); 303 ray.dir = xfmVector(world2local, ray_dir); 304 IntersectContext newcontext((Scene*)instance->object, user_context); 305 instance->object->intersectors.intersect(valid, ray, &newcontext); 306 ray.org = ray_org; 307 ray.dir = ray_dir; 308 instance_id_stack::pop(user_context); 309 } 310 } 311 312 template<int K> occluded(const vbool<K> & valid_i,const Precalculations & pre,RayK<K> & ray,IntersectContext * context,const InstancePrimitive & prim)313 vbool<K> InstanceIntersectorKMB<K>::occluded(const vbool<K>& valid_i, const Precalculations& pre, RayK<K>& ray, IntersectContext* context, const InstancePrimitive& prim) 314 { 315 vbool<K> valid = valid_i; 316 const Instance* instance = prim.instance; 317 318 /* perform ray mask test */ 319 #if defined(EMBREE_RAY_MASK) 320 valid &= (ray.mask & instance->mask) != 0; 321 if (none(valid)) return false; 322 #endif 323 324 RTCIntersectContext* user_context = context->user; 325 vbool<K> occluded = false; 326 if (likely(instance_id_stack::push(user_context, prim.instID_))) 327 { 328 AffineSpace3vf<K> world2local = instance->getWorld2Local<K>(valid, ray.time()); 329 const Vec3vf<K> ray_org = ray.org; 330 const Vec3vf<K> ray_dir = ray.dir; 331 ray.org = xfmPoint(world2local, ray_org); 332 ray.dir = xfmVector(world2local, ray_dir); 333 IntersectContext newcontext((Scene*)instance->object, user_context); 334 instance->object->intersectors.occluded(valid, ray, &newcontext); 335 ray.org = ray_org; 336 ray.dir = ray_dir; 337 occluded = ray.tfar < 0.0f; 338 instance_id_stack::pop(user_context); 339 } 340 return occluded; 341 } 342 343 #if defined(__SSE__) 344 template struct InstanceIntersectorK<4>; 345 template struct InstanceIntersectorKMB<4>; 346 #endif 347 348 #if defined(__AVX__) 349 template struct InstanceIntersectorK<8>; 350 template struct InstanceIntersectorKMB<8>; 351 #endif 352 353 #if defined(__AVX512F__) 354 template struct InstanceIntersectorK<16>; 355 template struct InstanceIntersectorKMB<16>; 356 #endif 357 } 358 } 359