1 //============================================================================
2 //  Copyright (c) Kitware, Inc.
3 //  All rights reserved.
4 //  See LICENSE.txt for details.
5 //
6 //  This software is distributed WITHOUT ANY WARRANTY; without even
7 //  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8 //  PURPOSE.  See the above copyright notice for more information.
9 //============================================================================
10 
11 #include <vtkm/rendering/MapperCylinder.h>
12 
13 #include <vtkm/cont/Timer.h>
14 #include <vtkm/cont/TryExecute.h>
15 
16 #include <vtkm/rendering/CanvasRayTracer.h>
17 #include <vtkm/rendering/Cylinderizer.h>
18 #include <vtkm/rendering/raytracing/Camera.h>
19 #include <vtkm/rendering/raytracing/CylinderExtractor.h>
20 #include <vtkm/rendering/raytracing/CylinderIntersector.h>
21 #include <vtkm/rendering/raytracing/Logger.h>
22 #include <vtkm/rendering/raytracing/RayOperations.h>
23 #include <vtkm/rendering/raytracing/RayTracer.h>
24 #include <vtkm/rendering/raytracing/Worklets.h>
25 
26 namespace vtkm
27 {
28 namespace rendering
29 {
30 
31 class CalcDistance : public vtkm::worklet::WorkletMapField
32 {
33 public:
34   VTKM_CONT
CalcDistance(const vtkm::Vec3f_32 & _eye_pos)35   CalcDistance(const vtkm::Vec3f_32& _eye_pos)
36     : eye_pos(_eye_pos)
37   {
38   }
39   typedef void ControlSignature(FieldIn, FieldOut);
40   typedef void ExecutionSignature(_1, _2);
41   template <typename VecType, typename OutType>
operator ()(const VecType & pos,OutType & out) const42   VTKM_EXEC inline void operator()(const VecType& pos, OutType& out) const
43   {
44     VecType tmp = eye_pos - pos;
45     out = static_cast<OutType>(vtkm::Sqrt(vtkm::dot(tmp, tmp)));
46   }
47 
48   const vtkm::Vec3f_32 eye_pos;
49 }; //class CalcDistance
50 
51 struct MapperCylinder::InternalsType
52 {
53   vtkm::rendering::CanvasRayTracer* Canvas;
54   vtkm::rendering::raytracing::RayTracer Tracer;
55   vtkm::rendering::raytracing::Camera RayCamera;
56   vtkm::rendering::raytracing::Ray<vtkm::Float32> Rays;
57   bool CompositeBackground;
58   vtkm::Float32 Radius;
59   vtkm::Float32 Delta;
60   bool UseVariableRadius;
61   VTKM_CONT
InternalsTypevtkm::rendering::MapperCylinder::InternalsType62   InternalsType()
63     : Canvas(nullptr)
64     , CompositeBackground(true)
65     , Radius(-1.0f)
66     , Delta(0.5)
67     , UseVariableRadius(false)
68   {
69   }
70 };
71 
MapperCylinder()72 MapperCylinder::MapperCylinder()
73   : Internals(new InternalsType)
74 {
75 }
76 
~MapperCylinder()77 MapperCylinder::~MapperCylinder() {}
78 
SetCanvas(vtkm::rendering::Canvas * canvas)79 void MapperCylinder::SetCanvas(vtkm::rendering::Canvas* canvas)
80 {
81   if (canvas != nullptr)
82   {
83     this->Internals->Canvas = dynamic_cast<CanvasRayTracer*>(canvas);
84     if (this->Internals->Canvas == nullptr)
85     {
86       throw vtkm::cont::ErrorBadValue("Ray Tracer: bad canvas type. Must be CanvasRayTracer");
87     }
88   }
89   else
90   {
91     this->Internals->Canvas = nullptr;
92   }
93 }
94 
GetCanvas() const95 vtkm::rendering::Canvas* MapperCylinder::GetCanvas() const
96 {
97   return this->Internals->Canvas;
98 }
99 
UseVariableRadius(bool useVariableRadius)100 void MapperCylinder::UseVariableRadius(bool useVariableRadius)
101 {
102   this->Internals->UseVariableRadius = useVariableRadius;
103 }
104 
SetRadius(const vtkm::Float32 & radius)105 void MapperCylinder::SetRadius(const vtkm::Float32& radius)
106 {
107   if (radius <= 0.f)
108   {
109     throw vtkm::cont::ErrorBadValue("MapperCylinder: radius must be positive");
110   }
111   this->Internals->Radius = radius;
112 }
SetRadiusDelta(const vtkm::Float32 & delta)113 void MapperCylinder::SetRadiusDelta(const vtkm::Float32& delta)
114 {
115   this->Internals->Delta = delta;
116 }
117 
RenderCells(const vtkm::cont::DynamicCellSet & cellset,const vtkm::cont::CoordinateSystem & coords,const vtkm::cont::Field & scalarField,const vtkm::cont::ColorTable & vtkmNotUsed (colorTable),const vtkm::rendering::Camera & camera,const vtkm::Range & scalarRange)118 void MapperCylinder::RenderCells(const vtkm::cont::DynamicCellSet& cellset,
119                                  const vtkm::cont::CoordinateSystem& coords,
120                                  const vtkm::cont::Field& scalarField,
121                                  const vtkm::cont::ColorTable& vtkmNotUsed(colorTable),
122                                  const vtkm::rendering::Camera& camera,
123                                  const vtkm::Range& scalarRange)
124 {
125   raytracing::Logger* logger = raytracing::Logger::GetInstance();
126   logger->OpenLogEntry("mapper_cylinder");
127   vtkm::cont::Timer tot_timer;
128   tot_timer.Start();
129   vtkm::cont::Timer timer;
130 
131 
132   vtkm::Bounds shapeBounds;
133   raytracing::CylinderExtractor cylExtractor;
134 
135   vtkm::Float32 baseRadius = this->Internals->Radius;
136   if (baseRadius == -1.f)
137   {
138     // set a default radius
139     vtkm::cont::ArrayHandle<vtkm::Float32> dist;
140     vtkm::worklet::DispatcherMapField<CalcDistance>(CalcDistance(camera.GetPosition()))
141       .Invoke(coords, dist);
142 
143 
144     vtkm::Float32 min_dist =
145       vtkm::cont::Algorithm::Reduce(dist, vtkm::Infinity<vtkm::Float32>(), vtkm::Minimum());
146 
147     baseRadius = 0.576769694f * min_dist - 0.603522029f * vtkm::Pow(vtkm::Float32(min_dist), 2.f) +
148       0.232171175f * vtkm::Pow(vtkm::Float32(min_dist), 3.f) -
149       0.038697244f * vtkm::Pow(vtkm::Float32(min_dist), 4.f) +
150       0.002366979f * vtkm::Pow(vtkm::Float32(min_dist), 5.f);
151     baseRadius /= min_dist;
152     vtkm::worklet::DispatcherMapField<vtkm::rendering::raytracing::MemSet<vtkm::Float32>>(
153       vtkm::rendering::raytracing::MemSet<vtkm::Float32>(baseRadius))
154       .Invoke(cylExtractor.GetRadii());
155   }
156 
157   if (this->Internals->UseVariableRadius)
158   {
159     vtkm::Float32 minRadius = baseRadius - baseRadius * this->Internals->Delta;
160     vtkm::Float32 maxRadius = baseRadius + baseRadius * this->Internals->Delta;
161 
162     cylExtractor.ExtractCells(cellset, scalarField, minRadius, maxRadius);
163   }
164   else
165   {
166     cylExtractor.ExtractCells(cellset, baseRadius);
167   }
168 
169   //
170   // Add supported shapes
171   //
172 
173   if (cylExtractor.GetNumberOfCylinders() > 0)
174   {
175     auto cylIntersector = std::make_shared<raytracing::CylinderIntersector>();
176     cylIntersector->SetData(coords, cylExtractor.GetCylIds(), cylExtractor.GetRadii());
177     this->Internals->Tracer.AddShapeIntersector(cylIntersector);
178     shapeBounds.Include(cylIntersector->GetShapeBounds());
179   }
180   //
181   // Create rays
182   //
183   vtkm::Int32 width = (vtkm::Int32)this->Internals->Canvas->GetWidth();
184   vtkm::Int32 height = (vtkm::Int32)this->Internals->Canvas->GetHeight();
185 
186   this->Internals->RayCamera.SetParameters(camera, width, height);
187 
188   this->Internals->RayCamera.CreateRays(this->Internals->Rays, shapeBounds);
189   this->Internals->Rays.Buffers.at(0).InitConst(0.f);
190   raytracing::RayOperations::MapCanvasToRays(
191     this->Internals->Rays, camera, *this->Internals->Canvas);
192 
193   this->Internals->Tracer.SetField(scalarField, scalarRange);
194   this->Internals->Tracer.GetCamera() = this->Internals->RayCamera;
195   this->Internals->Tracer.SetColorMap(this->ColorMap);
196   this->Internals->Tracer.Render(this->Internals->Rays);
197 
198   timer.Start();
199   this->Internals->Canvas->WriteToCanvas(
200     this->Internals->Rays, this->Internals->Rays.Buffers.at(0).Buffer, camera);
201 
202   if (this->Internals->CompositeBackground)
203   {
204     this->Internals->Canvas->BlendBackground();
205   }
206 
207   vtkm::Float64 time = timer.GetElapsedTime();
208   logger->AddLogData("write_to_canvas", time);
209   time = tot_timer.GetElapsedTime();
210   logger->CloseLogEntry(time);
211 }
212 
SetCompositeBackground(bool on)213 void MapperCylinder::SetCompositeBackground(bool on)
214 {
215   this->Internals->CompositeBackground = on;
216 }
217 
NewCopy() const218 vtkm::rendering::Mapper* MapperCylinder::NewCopy() const
219 {
220   return new vtkm::rendering::MapperCylinder(*this);
221 }
222 }
223 } // vtkm::rendering
224