2018-09-11 02:51:45 +00:00
|
|
|
//============================================================================
|
|
|
|
// Copyright (c) Kitware, Inc.
|
|
|
|
// All rights reserved.
|
|
|
|
// See LICENSE.txt for details.
|
2019-04-15 23:24:21 +00:00
|
|
|
//
|
2018-09-11 02:51:45 +00:00
|
|
|
// This software is distributed WITHOUT ANY WARRANTY; without even
|
|
|
|
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
|
|
// PURPOSE. See the above copyright notice for more information.
|
|
|
|
//============================================================================
|
|
|
|
#ifndef vtk_m_rendering_raytracing_BVH_Traverser_h
|
|
|
|
#define vtk_m_rendering_raytracing_BVH_Traverser_h
|
|
|
|
|
|
|
|
#include <vtkm/rendering/raytracing/BoundingVolumeHierarchy.h>
|
|
|
|
#include <vtkm/rendering/raytracing/Ray.h>
|
|
|
|
#include <vtkm/rendering/raytracing/RayTracingTypeDefs.h>
|
|
|
|
|
2019-03-29 18:45:10 +00:00
|
|
|
#include <vtkm/worklet/DispatcherMapField.h>
|
|
|
|
#include <vtkm/worklet/WorkletMapField.h>
|
|
|
|
|
2018-09-11 02:51:45 +00:00
|
|
|
namespace vtkm
|
|
|
|
{
|
|
|
|
namespace rendering
|
|
|
|
{
|
|
|
|
namespace raytracing
|
|
|
|
{
|
|
|
|
#define END_FLAG -1000000000
|
|
|
|
|
|
|
|
template <typename BVHPortalType, typename Precision>
|
|
|
|
VTKM_EXEC inline bool IntersectAABB(const BVHPortalType& bvh,
|
|
|
|
const vtkm::Int32& currentNode,
|
|
|
|
const vtkm::Vec<Precision, 3>& originDir,
|
|
|
|
const vtkm::Vec<Precision, 3>& invDir,
|
|
|
|
const Precision& closestDistance,
|
|
|
|
bool& hitLeftChild,
|
|
|
|
bool& hitRightChild,
|
|
|
|
const Precision& minDistance) //Find hit after this distance
|
|
|
|
{
|
2019-07-31 16:20:38 +00:00
|
|
|
vtkm::Vec4f_32 first4 = bvh.Get(currentNode);
|
|
|
|
vtkm::Vec4f_32 second4 = bvh.Get(currentNode + 1);
|
|
|
|
vtkm::Vec4f_32 third4 = bvh.Get(currentNode + 2);
|
2018-09-11 02:51:45 +00:00
|
|
|
|
|
|
|
Precision xmin0 = first4[0] * invDir[0] - originDir[0];
|
|
|
|
Precision ymin0 = first4[1] * invDir[1] - originDir[1];
|
|
|
|
Precision zmin0 = first4[2] * invDir[2] - originDir[2];
|
|
|
|
Precision xmax0 = first4[3] * invDir[0] - originDir[0];
|
|
|
|
Precision ymax0 = second4[0] * invDir[1] - originDir[1];
|
|
|
|
Precision zmax0 = second4[1] * invDir[2] - originDir[2];
|
|
|
|
|
|
|
|
Precision min0 = vtkm::Max(
|
|
|
|
vtkm::Max(vtkm::Max(vtkm::Min(ymin0, ymax0), vtkm::Min(xmin0, xmax0)), vtkm::Min(zmin0, zmax0)),
|
|
|
|
minDistance);
|
|
|
|
Precision max0 = vtkm::Min(
|
|
|
|
vtkm::Min(vtkm::Min(vtkm::Max(ymin0, ymax0), vtkm::Max(xmin0, xmax0)), vtkm::Max(zmin0, zmax0)),
|
|
|
|
closestDistance);
|
|
|
|
hitLeftChild = (max0 >= min0);
|
|
|
|
|
|
|
|
Precision xmin1 = second4[2] * invDir[0] - originDir[0];
|
|
|
|
Precision ymin1 = second4[3] * invDir[1] - originDir[1];
|
|
|
|
Precision zmin1 = third4[0] * invDir[2] - originDir[2];
|
|
|
|
Precision xmax1 = third4[1] * invDir[0] - originDir[0];
|
|
|
|
Precision ymax1 = third4[2] * invDir[1] - originDir[1];
|
|
|
|
Precision zmax1 = third4[3] * invDir[2] - originDir[2];
|
|
|
|
|
|
|
|
Precision min1 = vtkm::Max(
|
|
|
|
vtkm::Max(vtkm::Max(vtkm::Min(ymin1, ymax1), vtkm::Min(xmin1, xmax1)), vtkm::Min(zmin1, zmax1)),
|
|
|
|
minDistance);
|
|
|
|
Precision max1 = vtkm::Min(
|
|
|
|
vtkm::Min(vtkm::Min(vtkm::Max(ymin1, ymax1), vtkm::Max(xmin1, xmax1)), vtkm::Max(zmin1, zmax1)),
|
|
|
|
closestDistance);
|
|
|
|
hitRightChild = (max1 >= min1);
|
|
|
|
return (min0 > min1);
|
|
|
|
}
|
|
|
|
|
|
|
|
class BVHTraverser
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
class Intersector : public vtkm::worklet::WorkletMapField
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
VTKM_EXEC
|
|
|
|
inline vtkm::Float32 rcp(vtkm::Float32 f) const { return 1.0f / f; }
|
|
|
|
VTKM_EXEC
|
|
|
|
inline vtkm::Float32 rcp_safe(vtkm::Float32 f) const
|
|
|
|
{
|
|
|
|
return rcp((vtkm::Abs(f) < 1e-8f) ? 1e-8f : f);
|
|
|
|
}
|
|
|
|
VTKM_EXEC
|
|
|
|
inline vtkm::Float64 rcp(vtkm::Float64 f) const { return 1.0 / f; }
|
|
|
|
VTKM_EXEC
|
|
|
|
inline vtkm::Float64 rcp_safe(vtkm::Float64 f) const
|
|
|
|
{
|
|
|
|
return rcp((vtkm::Abs(f) < 1e-8f) ? 1e-8f : f);
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
VTKM_CONT
|
2018-10-30 15:09:11 +00:00
|
|
|
Intersector() {}
|
2019-01-10 18:59:25 +00:00
|
|
|
using ControlSignature = void(FieldIn,
|
|
|
|
FieldIn,
|
|
|
|
FieldOut,
|
|
|
|
FieldIn,
|
|
|
|
FieldIn,
|
|
|
|
FieldOut,
|
|
|
|
FieldOut,
|
|
|
|
FieldOut,
|
|
|
|
WholeArrayIn,
|
2018-10-30 14:46:42 +00:00
|
|
|
ExecObject leafIntersector,
|
2019-01-10 18:59:25 +00:00
|
|
|
WholeArrayIn,
|
|
|
|
WholeArrayIn);
|
2018-10-30 14:46:42 +00:00
|
|
|
using ExecutionSignature = void(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12);
|
2018-09-11 02:51:45 +00:00
|
|
|
|
|
|
|
|
2018-10-30 14:46:42 +00:00
|
|
|
template <typename PointPortalType,
|
|
|
|
typename Precision,
|
|
|
|
typename LeafType,
|
|
|
|
typename InnerNodePortalType,
|
|
|
|
typename LeafPortalType>
|
2018-09-11 02:51:45 +00:00
|
|
|
VTKM_EXEC void operator()(const vtkm::Vec<Precision, 3>& dir,
|
|
|
|
const vtkm::Vec<Precision, 3>& origin,
|
|
|
|
Precision& distance,
|
|
|
|
const Precision& minDistance,
|
|
|
|
const Precision& maxDistance,
|
|
|
|
Precision& minU,
|
|
|
|
Precision& minV,
|
|
|
|
vtkm::Id& hitIndex,
|
2018-10-30 14:46:42 +00:00
|
|
|
const PointPortalType& points,
|
|
|
|
LeafType& leafIntersector,
|
|
|
|
const InnerNodePortalType& flatBVH,
|
|
|
|
const LeafPortalType& leafs) const
|
2018-09-11 02:51:45 +00:00
|
|
|
{
|
|
|
|
Precision closestDistance = maxDistance;
|
|
|
|
distance = maxDistance;
|
|
|
|
hitIndex = -1;
|
|
|
|
|
|
|
|
vtkm::Vec<Precision, 3> invDir;
|
|
|
|
invDir[0] = rcp_safe(dir[0]);
|
|
|
|
invDir[1] = rcp_safe(dir[1]);
|
|
|
|
invDir[2] = rcp_safe(dir[2]);
|
|
|
|
vtkm::Int32 currentNode;
|
|
|
|
|
|
|
|
vtkm::Int32 todo[64];
|
|
|
|
vtkm::Int32 stackptr = 0;
|
|
|
|
vtkm::Int32 barrier = (vtkm::Int32)END_FLAG;
|
|
|
|
currentNode = 0;
|
|
|
|
|
|
|
|
todo[stackptr] = barrier;
|
|
|
|
|
|
|
|
vtkm::Vec<Precision, 3> originDir = origin * invDir;
|
|
|
|
|
|
|
|
while (currentNode != END_FLAG)
|
|
|
|
{
|
|
|
|
if (currentNode > -1)
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
bool hitLeftChild, hitRightChild;
|
2018-10-30 14:46:42 +00:00
|
|
|
bool rightCloser = IntersectAABB(flatBVH,
|
2018-09-11 02:51:45 +00:00
|
|
|
currentNode,
|
|
|
|
originDir,
|
|
|
|
invDir,
|
|
|
|
closestDistance,
|
|
|
|
hitLeftChild,
|
|
|
|
hitRightChild,
|
|
|
|
minDistance);
|
|
|
|
|
|
|
|
if (!hitLeftChild && !hitRightChild)
|
|
|
|
{
|
|
|
|
currentNode = todo[stackptr];
|
|
|
|
stackptr--;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-07-31 16:20:38 +00:00
|
|
|
vtkm::Vec4f_32 children = flatBVH.Get(currentNode + 3); //Children.Get(currentNode);
|
2018-09-11 02:51:45 +00:00
|
|
|
vtkm::Int32 leftChild;
|
|
|
|
memcpy(&leftChild, &children[0], 4);
|
|
|
|
vtkm::Int32 rightChild;
|
|
|
|
memcpy(&rightChild, &children[1], 4);
|
|
|
|
currentNode = (hitLeftChild) ? leftChild : rightChild;
|
|
|
|
if (hitLeftChild && hitRightChild)
|
|
|
|
{
|
|
|
|
if (rightCloser)
|
|
|
|
{
|
|
|
|
currentNode = rightChild;
|
|
|
|
stackptr++;
|
|
|
|
todo[stackptr] = leftChild;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
stackptr++;
|
|
|
|
todo[stackptr] = rightChild;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} // if inner node
|
|
|
|
|
|
|
|
if (currentNode < 0 && currentNode != barrier) //check register usage
|
|
|
|
{
|
|
|
|
currentNode = -currentNode - 1; //swap the neg address
|
2018-10-30 14:46:42 +00:00
|
|
|
leafIntersector.IntersectLeaf(currentNode,
|
2018-09-11 02:51:45 +00:00
|
|
|
origin,
|
|
|
|
dir,
|
|
|
|
points,
|
|
|
|
hitIndex,
|
|
|
|
closestDistance,
|
|
|
|
minU,
|
|
|
|
minV,
|
2018-10-30 14:46:42 +00:00
|
|
|
leafs,
|
2018-09-11 02:51:45 +00:00
|
|
|
minDistance);
|
|
|
|
currentNode = todo[stackptr];
|
|
|
|
stackptr--;
|
|
|
|
} // if leaf node
|
|
|
|
|
|
|
|
} //while
|
|
|
|
|
|
|
|
if (hitIndex != -1)
|
|
|
|
distance = closestDistance;
|
|
|
|
} // ()
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2018-10-30 14:46:42 +00:00
|
|
|
template <typename Precision, typename LeafIntersectorType>
|
2018-09-11 02:51:45 +00:00
|
|
|
VTKM_CONT void IntersectRays(Ray<Precision>& rays,
|
|
|
|
LinearBVH& bvh,
|
2018-10-30 14:46:42 +00:00
|
|
|
LeafIntersectorType& leafIntersector,
|
|
|
|
vtkm::cont::CoordinateSystem& coordsHandle)
|
2018-09-11 02:51:45 +00:00
|
|
|
{
|
2018-10-30 15:09:11 +00:00
|
|
|
vtkm::worklet::DispatcherMapField<Intersector> intersectDispatch;
|
2018-09-11 02:51:45 +00:00
|
|
|
intersectDispatch.Invoke(rays.Dir,
|
|
|
|
rays.Origin,
|
|
|
|
rays.Distance,
|
|
|
|
rays.MinDistance,
|
|
|
|
rays.MaxDistance,
|
|
|
|
rays.U,
|
|
|
|
rays.V,
|
|
|
|
rays.HitIdx,
|
2018-10-30 14:46:42 +00:00
|
|
|
coordsHandle,
|
|
|
|
leafIntersector,
|
|
|
|
bvh.FlatBVH,
|
|
|
|
bvh.Leafs);
|
2018-09-11 02:51:45 +00:00
|
|
|
}
|
|
|
|
}; // BVHTraverser
|
|
|
|
#undef END_FLAG
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} //namespace vtkm::rendering::raytracing
|
|
|
|
#endif //vtk_m_rendering_raytracing_BVHTraverser_h
|