1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
// Copyright 2009 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#include "World.ih"
OSPRAY_BEGIN_ISPC_NAMESPACE
#ifndef OSPRAY_TARGET_SYCL
unmasked void clippingIntersectionFilterV(
const RTCFilterFunctionNArguments *uniform args)
{
// Set execution mask
uniform int *uniform valid = args->valid;
if (!valid[programIndex])
return;
// Get pointer to the intersection context
RayQueryContextClipping *uniform context =
(RayQueryContextClipping * uniform) args->context;
// We skip this intersection to collect all remaining intersections
valid[programIndex] = 0;
// Skip if array is full
if (context->hitsCount >= CLIPPING_HITS_MAX_COUNT)
return;
// Get ray and hit
varying Ray *uniform ray = (varying Ray * uniform) args->ray;
varying const RTCHit *uniform hit = (varying const RTCHit *uniform)args->hit;
// Prepare clipping normal
vec3f Nc;
{
// The postIntersect function needs the hit part of the Ray structure to be
// initialized. Making a ray copy here is quite costly. That is why just
// the necessary ray fields are set here.
DifferentialGeometry dg;
ray->Ng = make_vec3f(hit->Ng_x, hit->Ng_y, hit->Ng_z);
ray->u = hit->u;
ray->v = hit->v;
ray->primID = hit->primID;
ray->geomID = hit->geomID;
// We need to call postIntersect on clipping geometry
foreach_unique (instID in hit->instID[0]) {
// Call postIntersect to get shading normal
Instance *uniform instance = *(context->world->instances + instID);
Instance_postIntersect(
instance, NULL, dg, *ray, DG_NG | DG_NS, true, *context->super.ffh);
// Use geometry normal for clipping
// but use shading normal to check if inversion is needed
Nc = (dot(dg.Ns, dg.Ng) > 0.f) ? ray->Ng : neg(ray->Ng);
}
// Restore IDs initial values
ray->primID = RTC_INVALID_GEOMETRY_ID;
ray->geomID = RTC_INVALID_GEOMETRY_ID;
}
// Based on clipping normal vector decide if the ray is
// entering clipping geometry (set positive hit value) or exiting clipping
// geometry (set negative hit value)
const bool exitsClipping = (dot(ray->dir, Nc) > 0.f);
ClippingHit cHit;
cHit.t = (exitsClipping) ? -ray->t : ray->t;
cHit.primID = hit->primID;
cHit.geomID = hit->geomID;
cHit.instID = hit->instID[0];
// Some geometry types (e.g. curves, subdivisions)
// may give more than 2 intersections, we have to filter them out
for (uint32 i = 0; i < context->hitsCount; i++) {
if ((context->hits[i].primID == cHit.primID)
&& (context->hits[i].geomID == cHit.geomID)
&& (context->hits[i].instID == cHit.instID)
&& floatUlpCompare(context->hits[i].t, cHit.t, 512))
return;
}
// Now we know that this intersection will be taken into account,
// so we can update clipping depth correction value accordingly
if (exitsClipping) {
context->corrClippingDepth--;
} else {
context->corrClippingDepth++;
}
// Insert hit value into sorted array
for (uint32 i = 0; i < context->hitsCount; i++) {
if (abs(context->hits[i].t) > abs(cHit.t)) {
const ClippingHit tmp = context->hits[i];
context->hits[i] = cHit;
cHit = tmp;
}
}
context->hits[context->hitsCount] = cHit;
context->hitsCount++;
}
#endif
OSPRAY_END_ISPC_NAMESPACE
|