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