//============================================================================ // Copyright (c) Kitware, Inc. // All rights reserved. // See LICENSE.txt for details. // // 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_Ray_h #define vtk_m_rendering_raytracing_Ray_h #include #include #include #include #include #include #include #define RAY_ACTIVE 0 #define RAY_COMPLETE 1 #define RAY_TERMINATED 2 #define RAY_EXITED_MESH 3 #define RAY_EXITED_DOMAIN 4 #define RAY_LOST 5 #define RAY_ABANDONED 6 #define RAY_TUG_EPSILON 0.001 namespace vtkm { namespace rendering { namespace raytracing { template class Ray { protected: bool IntersectionDataEnabled; public: // composite vectors to hold array handles typename //tell the compiler we have a dependent type vtkm::cont::ArrayHandleCompositeVector, vtkm::cont::ArrayHandle, vtkm::cont::ArrayHandle> Intersection; typename //tell the compiler we have a dependent type vtkm::cont::ArrayHandleCompositeVector, vtkm::cont::ArrayHandle, vtkm::cont::ArrayHandle> Normal; typename //tell the compiler we have a dependent type vtkm::cont::ArrayHandleCompositeVector, vtkm::cont::ArrayHandle, vtkm::cont::ArrayHandle> Origin; typename //tell the compiler we have a dependent type vtkm::cont::ArrayHandleCompositeVector, vtkm::cont::ArrayHandle, vtkm::cont::ArrayHandle> Dir; vtkm::cont::ArrayHandle IntersectionX; //ray Intersection vtkm::cont::ArrayHandle IntersectionY; vtkm::cont::ArrayHandle IntersectionZ; vtkm::cont::ArrayHandle OriginX; //ray Origin vtkm::cont::ArrayHandle OriginY; vtkm::cont::ArrayHandle OriginZ; vtkm::cont::ArrayHandle DirX; //ray Dir vtkm::cont::ArrayHandle DirY; vtkm::cont::ArrayHandle DirZ; vtkm::cont::ArrayHandle U; //barycentric coordinates vtkm::cont::ArrayHandle V; vtkm::cont::ArrayHandle NormalX; //ray Normal vtkm::cont::ArrayHandle NormalY; vtkm::cont::ArrayHandle NormalZ; vtkm::cont::ArrayHandle Scalar; //scalar vtkm::cont::ArrayHandle Distance; //distance to hit vtkm::cont::ArrayHandle HitIdx; vtkm::cont::ArrayHandle PixelIdx; vtkm::cont::ArrayHandle MinDistance; // distance to hit vtkm::cont::ArrayHandle MaxDistance; // distance to hit vtkm::cont::ArrayHandle Status; // 0 = active 1 = miss 2 = lost std::vector> Buffers; vtkm::Id DebugWidth; vtkm::Id DebugHeight; vtkm::Id NumRays; VTKM_CONT Ray() { IntersectionDataEnabled = false; NumRays = 0; Intersection = vtkm::cont::make_ArrayHandleCompositeVector(IntersectionX, IntersectionY, IntersectionZ); Normal = vtkm::cont::make_ArrayHandleCompositeVector(NormalX, NormalY, NormalZ); Origin = vtkm::cont::make_ArrayHandleCompositeVector(OriginX, OriginY, OriginZ); Dir = vtkm::cont::make_ArrayHandleCompositeVector(DirX, DirY, DirZ); ChannelBuffer buffer; buffer.Resize(NumRays); Buffers.push_back(buffer); DebugWidth = -1; DebugHeight = -1; } struct EnableIntersectionDataFunctor { template VTKM_CONT bool operator()(Device, Ray* self) { VTKM_IS_DEVICE_ADAPTER_TAG(Device); self->EnableIntersectionData(Device()); return true; } }; void EnableIntersectionData() { vtkm::cont::TryExecute(EnableIntersectionDataFunctor(), this); } template void EnableIntersectionData(Device) { if (IntersectionDataEnabled) { return; } vtkm::cont::Token token; IntersectionDataEnabled = true; IntersectionX.PrepareForOutput(NumRays, Device(), token); IntersectionY.PrepareForOutput(NumRays, Device(), token); IntersectionZ.PrepareForOutput(NumRays, Device(), token); U.PrepareForOutput(NumRays, Device(), token); V.PrepareForOutput(NumRays, Device(), token); Scalar.PrepareForOutput(NumRays, Device(), token); NormalX.PrepareForOutput(NumRays, Device(), token); NormalY.PrepareForOutput(NumRays, Device(), token); NormalZ.PrepareForOutput(NumRays, Device(), token); } void DisableIntersectionData() { if (!IntersectionDataEnabled) { return; } IntersectionDataEnabled = false; IntersectionX.ReleaseResources(); IntersectionY.ReleaseResources(); IntersectionZ.ReleaseResources(); U.ReleaseResources(); V.ReleaseResources(); Scalar.ReleaseResources(); NormalX.ReleaseResources(); NormalY.ReleaseResources(); NormalZ.ReleaseResources(); } template VTKM_CONT Ray(const vtkm::Int32 size, Device, bool enableIntersectionData = false) { NumRays = size; IntersectionDataEnabled = enableIntersectionData; ChannelBuffer buffer; this->Buffers.push_back(buffer); DebugWidth = -1; DebugHeight = -1; this->Resize(size, Device()); } struct ResizeFunctor { template VTKM_CONT bool operator()(Device, Ray* self, const vtkm::Int32 size) { VTKM_IS_DEVICE_ADAPTER_TAG(Device); self->Resize(size, Device()); return true; } }; VTKM_CONT void Resize(const vtkm::Int32 size) { vtkm::cont::TryExecute(ResizeFunctor(), size); } template VTKM_CONT void Resize(const vtkm::Int32 size, Device) { NumRays = size; vtkm::cont::Token token; if (IntersectionDataEnabled) { IntersectionX.PrepareForOutput(NumRays, Device(), token); IntersectionY.PrepareForOutput(NumRays, Device(), token); IntersectionZ.PrepareForOutput(NumRays, Device(), token); U.PrepareForOutput(NumRays, Device(), token); V.PrepareForOutput(NumRays, Device(), token); Scalar.PrepareForOutput(NumRays, Device(), token); NormalX.PrepareForOutput(NumRays, Device(), token); NormalY.PrepareForOutput(NumRays, Device(), token); NormalZ.PrepareForOutput(NumRays, Device(), token); } OriginX.PrepareForOutput(NumRays, Device(), token); OriginY.PrepareForOutput(NumRays, Device(), token); OriginZ.PrepareForOutput(NumRays, Device(), token); DirX.PrepareForOutput(NumRays, Device(), token); DirY.PrepareForOutput(NumRays, Device(), token); DirZ.PrepareForOutput(NumRays, Device(), token); Distance.PrepareForOutput(NumRays, Device(), token); MinDistance.PrepareForOutput(NumRays, Device(), token); MaxDistance.PrepareForOutput(NumRays, Device(), token); Status.PrepareForOutput(NumRays, Device(), token); HitIdx.PrepareForOutput(NumRays, Device(), token); PixelIdx.PrepareForOutput(NumRays, Device(), token); Intersection = vtkm::cont::make_ArrayHandleCompositeVector(IntersectionX, IntersectionY, IntersectionZ); Normal = vtkm::cont::make_ArrayHandleCompositeVector(NormalX, NormalY, NormalZ); Origin = vtkm::cont::make_ArrayHandleCompositeVector(OriginX, OriginY, OriginZ); Dir = vtkm::cont::make_ArrayHandleCompositeVector(DirX, DirY, DirZ); const size_t numBuffers = this->Buffers.size(); for (size_t i = 0; i < numBuffers; ++i) { this->Buffers[i].Resize(NumRays, Device()); } } VTKM_CONT void AddBuffer(const vtkm::Int32 numChannels, const std::string name) { ChannelBuffer buffer(numChannels, this->NumRays); buffer.SetName(name); this->Buffers.push_back(buffer); } VTKM_CONT bool HasBuffer(const std::string name) { size_t numBuffers = this->Buffers.size(); bool found = false; for (size_t i = 0; i < numBuffers; ++i) { if (this->Buffers[i].GetName() == name) { found = true; break; } } return found; } VTKM_CONT ChannelBuffer& GetBuffer(const std::string name) { const size_t numBuffers = this->Buffers.size(); bool found = false; size_t index = 0; for (size_t i = 0; i < numBuffers; ++i) { if (this->Buffers[i].GetName() == name) { found = true; index = i; } } if (found) { return this->Buffers.at(index); } else { throw vtkm::cont::ErrorBadValue("No channel buffer with requested name: " + name); } } void PrintRay(vtkm::Id pixelId) { for (vtkm::Id i = 0; i < NumRays; ++i) { if (PixelIdx.WritePortal().Get(i) == pixelId) { std::cout << "Ray " << pixelId << "\n"; std::cout << "Origin " << "[" << OriginX.WritePortal().Get(i) << "," << OriginY.WritePortal().Get(i) << "," << OriginZ.WritePortal().Get(i) << "]\n"; std::cout << "Dir " << "[" << DirX.WritePortal().Get(i) << "," << DirY.WritePortal().Get(i) << "," << DirZ.WritePortal().Get(i) << "]\n"; } } } friend class RayOperations; }; // class ray } } } //namespace vtkm::rendering::raytracing #endif //vtk_m_rendering_raytracing_Ray_h