1 #include "gui/Factory.h"
2 #include "gui/Project.h"
3 #include "gui/objects/Camera.h"
4 #include "gui/objects/Colorizer.h"
5 #include "gui/renderers/Brdf.h"
6 #include "gui/renderers/ContourRenderer.h"
7 #include "gui/renderers/FrameBuffer.h"
8 #include "gui/renderers/MeshRenderer.h"
9 #include "gui/renderers/ParticleRenderer.h"
10 #include "gui/renderers/RayMarcher.h"
11 #include "gui/renderers/VolumeRenderer.h"
12
13 NAMESPACE_SPH_BEGIN
14
getTracker(const GuiSettings & settings)15 AutoPtr<ITracker> Factory::getTracker(const GuiSettings& settings) {
16 const int trackedIndex = settings.get<int>(GuiSettingsId::CAMERA_TRACK_PARTICLE);
17 if (trackedIndex >= 0) {
18 return makeAuto<ParticleTracker>(trackedIndex);
19 }
20 const bool useMedian = settings.get<bool>(GuiSettingsId::CAMERA_TRACK_MEDIAN);
21 if (useMedian) {
22 const Vector offset = settings.get<Vector>(GuiSettingsId::CAMERA_TRACKING_OFFSET);
23 return makeAuto<MedianTracker>(offset);
24 }
25 return nullptr;
26 }
27
getCamera(const GuiSettings & settings,const Pixel size)28 AutoPtr<ICamera> Factory::getCamera(const GuiSettings& settings, const Pixel size) {
29 CameraEnum cameraId = settings.get<CameraEnum>(GuiSettingsId::CAMERA_TYPE);
30 CameraParams data;
31 data.imageSize = size;
32 data.position = settings.get<Vector>(GuiSettingsId::CAMERA_POSITION);
33 data.target = settings.get<Vector>(GuiSettingsId::CAMERA_TARGET);
34 data.up = settings.get<Vector>(GuiSettingsId::CAMERA_UP);
35 data.clipping = Interval(settings.get<Float>(GuiSettingsId::CAMERA_CLIP_NEAR),
36 settings.get<Float>(GuiSettingsId::CAMERA_CLIP_FAR));
37 data.perspective.fov = settings.get<Float>(GuiSettingsId::CAMERA_PERSPECTIVE_FOV);
38 data.ortho.fov = float(settings.get<Float>(GuiSettingsId::CAMERA_ORTHO_FOV));
39 data.ortho.cutoff = float(settings.get<Float>(GuiSettingsId::CAMERA_ORTHO_CUTOFF));
40 if (data.ortho.cutoff.value() == 0._f) {
41 data.ortho.cutoff = NOTHING;
42 }
43
44 switch (cameraId) {
45 case CameraEnum::ORTHO:
46 return makeAuto<OrthoCamera>(data);
47 case CameraEnum::PERSPECTIVE:
48 return makeAuto<PerspectiveCamera>(data);
49 case CameraEnum::FISHEYE:
50 return makeAuto<FisheyeCamera>(data);
51 case CameraEnum::SPHERICAL:
52 return makeAuto<SphericalCamera>(data);
53 default:
54 NOT_IMPLEMENTED;
55 }
56 }
57
getRenderer(const GuiSettings & settings)58 AutoPtr<IRenderer> Factory::getRenderer(const GuiSettings& settings) {
59 SharedPtr<IScheduler> scheduler = getScheduler(RunSettings::getDefaults());
60 return getRenderer(scheduler, settings);
61 }
62
getRenderer(SharedPtr<IScheduler> scheduler,const GuiSettings & settings)63 AutoPtr<IRenderer> Factory::getRenderer(SharedPtr<IScheduler> scheduler, const GuiSettings& settings) {
64 RendererEnum id = settings.get<RendererEnum>(GuiSettingsId::RENDERER);
65 AutoPtr<IRenderer> renderer;
66 switch (id) {
67 case RendererEnum::NONE:
68 class NullRenderer : public IRenderer {
69 virtual void initialize(const Storage&, const IColorizer&, const ICamera&) override {}
70 virtual bool isInitialized() const override {
71 return true;
72 }
73 virtual void setColorizer(const IColorizer&) override {}
74 virtual void render(const RenderParams&, Statistics&, IRenderOutput&) const override {}
75 virtual void cancelRender() override {}
76 };
77 renderer = makeAuto<NullRenderer>();
78 break;
79 case RendererEnum::PARTICLE:
80 renderer = makeAuto<ParticleRenderer>(settings);
81 break;
82 case RendererEnum::MESH:
83 renderer = makeAuto<MeshRenderer>(scheduler, settings);
84 break;
85 case RendererEnum::RAYMARCHER:
86 renderer = makeAuto<RayMarcher>(scheduler, settings);
87 break;
88 case RendererEnum::VOLUME:
89 renderer = makeAuto<VolumeRenderer>(scheduler, settings);
90 break;
91 case RendererEnum::CONTOUR:
92 renderer = makeAuto<ContourRenderer>(scheduler, settings);
93 break;
94 default:
95 NOT_IMPLEMENTED;
96 }
97
98 return renderer;
99 }
100
getBrdf(const GuiSettings & settings)101 AutoPtr<IBrdf> Factory::getBrdf(const GuiSettings& settings) {
102 const BrdfEnum id = settings.get<BrdfEnum>(GuiSettingsId::RAYTRACE_BRDF);
103 switch (id) {
104 case BrdfEnum::LAMBERT:
105 return makeAuto<LambertBrdf>(1._f);
106 case BrdfEnum::PHONG:
107 return makeAuto<PhongBrdf>(1._f);
108 default:
109 NOT_IMPLEMENTED;
110 }
111 }
112
getColorMap(const GuiSettings & settings)113 AutoPtr<IColorMap> Factory::getColorMap(const GuiSettings& settings) {
114 const ColorMapEnum id = settings.get<ColorMapEnum>(GuiSettingsId::COLORMAP_TYPE);
115 switch (id) {
116 case ColorMapEnum::LINEAR:
117 return nullptr;
118 case ColorMapEnum::LOGARITHMIC: {
119 const float factor = settings.get<Float>(GuiSettingsId::COLORMAP_LOGARITHMIC_FACTOR);
120 return makeAuto<LogarithmicColorMap>(factor);
121 }
122 case ColorMapEnum::FILMIC:
123 return makeAuto<FilmicColorMap>();
124 default:
125 NOT_IMPLEMENTED;
126 }
127 }
128
getColorizer(const GuiSettings & settings,const ExtColorizerId id)129 static AutoPtr<IColorizer> getColorizer(const GuiSettings& settings, const ExtColorizerId id) {
130 using Factory::getPalette;
131
132 switch (id) {
133 case ColorizerId::VELOCITY:
134 return makeAuto<VelocityColorizer>(getPalette(id));
135 case ColorizerId::ACCELERATION:
136 return makeAuto<AccelerationColorizer>(getPalette(id));
137 case ColorizerId::MOVEMENT_DIRECTION:
138 return makeAuto<DirectionColorizer>(Vector(0._f, 0._f, 1._f), getPalette(id));
139 case ColorizerId::COROTATING_VELOCITY:
140 return makeAuto<CorotatingVelocityColorizer>(getPalette(ColorizerId::VELOCITY));
141 case ColorizerId::DENSITY_PERTURBATION:
142 return makeAuto<DensityPerturbationColorizer>(getPalette(id));
143 case ColorizerId::SUMMED_DENSITY:
144 return makeAuto<SummedDensityColorizer>(RunSettings::getDefaults(), getPalette(QuantityId::DENSITY));
145 case ColorizerId::TOTAL_ENERGY:
146 return makeAuto<EnergyColorizer>(getPalette(id));
147 case ColorizerId::TEMPERATURE:
148 return makeAuto<TemperatureColorizer>();
149 case ColorizerId::TOTAL_STRESS:
150 return makeAuto<StressColorizer>(getPalette(id));
151 case ColorizerId::YIELD_REDUCTION:
152 return makeAuto<YieldReductionColorizer>(getPalette(id));
153 case ColorizerId::DAMAGE_ACTIVATION:
154 return makeAuto<DamageActivationColorizer>(getPalette(id));
155 case ColorizerId::RADIUS:
156 return makeAuto<RadiusColorizer>(getPalette(id));
157 case ColorizerId::BOUNDARY:
158 return makeAuto<BoundaryColorizer>(BoundaryColorizer::Detection::NEIGBOUR_THRESHOLD, 40);
159 case ColorizerId::UVW:
160 return makeAuto<UvwColorizer>();
161 case ColorizerId::PARTICLE_ID:
162 return makeAuto<ParticleIdColorizer>(settings);
163 case ColorizerId::COMPONENT_ID:
164 return makeAuto<ComponentIdColorizer>(
165 settings, Post::ComponentFlag::OVERLAP | Post::ComponentFlag::SORT_BY_MASS);
166 case ColorizerId::BOUND_COMPONENT_ID:
167 return makeAuto<ComponentIdColorizer>(
168 settings, Post::ComponentFlag::ESCAPE_VELOCITY | Post::ComponentFlag::SORT_BY_MASS);
169 case ColorizerId::AGGREGATE_ID:
170 return makeAuto<AggregateIdColorizer>(settings);
171 case ColorizerId::FLAG:
172 return makeAuto<IndexColorizer>(QuantityId::FLAG, settings);
173 case ColorizerId::MATERIAL_ID:
174 return makeAuto<MaterialColorizer>(settings);
175 case ColorizerId::BEAUTY:
176 return makeAuto<BeautyColorizer>();
177 default:
178 QuantityId quantity = QuantityId(id);
179 SPH_ASSERT(int(quantity) >= 0);
180
181 Palette palette = getPalette(id);
182 switch (getMetadata(quantity).expectedType) {
183 case ValueEnum::INDEX:
184 return makeAuto<TypedColorizer<Size>>(quantity, std::move(palette));
185 case ValueEnum::SCALAR:
186 return makeAuto<TypedColorizer<Float>>(quantity, std::move(palette));
187 case ValueEnum::VECTOR:
188 return makeAuto<TypedColorizer<Vector>>(quantity, std::move(palette));
189 case ValueEnum::TRACELESS_TENSOR:
190 return makeAuto<TypedColorizer<TracelessTensor>>(quantity, std::move(palette));
191 case ValueEnum::SYMMETRIC_TENSOR:
192 return makeAuto<TypedColorizer<SymmetricTensor>>(quantity, std::move(palette));
193 default:
194 NOT_IMPLEMENTED;
195 }
196 }
197 }
198
getColorizer(const Project & project,const ExtColorizerId id)199 AutoPtr<IColorizer> Factory::getColorizer(const Project& project, const ExtColorizerId id) {
200 AutoPtr<IColorizer> colorizer = Sph::getColorizer(project.getGuiSettings(), id);
201 Optional<Palette> palette = colorizer->getPalette();
202 if (palette && project.getPalette(colorizer->name(), palette.value())) {
203 colorizer->setPalette(palette.value());
204 }
205 return colorizer;
206 }
207
208 struct PaletteDesc {
209 Interval range;
210 PaletteScale scale;
211 };
212
213 static FlatMap<ExtColorizerId, PaletteDesc> paletteDescs(ELEMENTS_UNIQUE,
214 {
215 { QuantityId::DENSITY, { Interval(2650._f, 2750._f), PaletteScale::LINEAR } },
216 { QuantityId::MASS, { Interval(1.e5_f, 1.e10_f), PaletteScale::LOGARITHMIC } },
217 { QuantityId::PRESSURE, { Interval(-1.e5_f, 1.e10_f), PaletteScale::HYBRID } },
218 { QuantityId::ENERGY, { Interval(1._f, 1.e6_f), PaletteScale::LOGARITHMIC } },
219 { QuantityId::DEVIATORIC_STRESS, { Interval(0._f, 1.e10_f), PaletteScale::LINEAR } },
220 { QuantityId::DAMAGE, { Interval(0._f, 1._f), PaletteScale::LINEAR } },
221 { QuantityId::VELOCITY_DIVERGENCE, { Interval(-0.1_f, 0.1_f), PaletteScale::LINEAR } },
222 { QuantityId::VELOCITY_GRADIENT, { Interval(0._f, 1.e-3_f), PaletteScale::LINEAR } },
223 { QuantityId::VELOCITY_LAPLACIAN, { Interval(0._f, 1.e-3_f), PaletteScale::LINEAR } },
224 { QuantityId::VELOCITY_GRADIENT_OF_DIVERGENCE, { Interval(0._f, 1.e-3_f), PaletteScale::LINEAR } },
225 { QuantityId::VELOCITY_ROTATION, { Interval(0._f, 4._f), PaletteScale::LINEAR } },
226 { QuantityId::SOUND_SPEED, { Interval(0._f, 5.e3_f), PaletteScale::LINEAR } },
227 { QuantityId::VIBRATIONAL_VELOCITY, { Interval(0._f, 5.e3_f), PaletteScale::LINEAR } },
228 { QuantityId::AV_ALPHA, { Interval(0.1_f, 1.5_f), PaletteScale::LINEAR } },
229 { QuantityId::AV_BALSARA, { Interval(0._f, 1._f), PaletteScale::LINEAR } },
230 { QuantityId::AV_STRESS, { Interval(0._f, 1.e8_f), PaletteScale::LINEAR } },
231 { QuantityId::ANGULAR_FREQUENCY, { Interval(0._f, 1.e-3_f), PaletteScale::LINEAR } },
232 { QuantityId::MOMENT_OF_INERTIA, { Interval(0._f, 1.e10_f), PaletteScale::LINEAR } },
233 { QuantityId::PHASE_ANGLE, { Interval(0._f, 10._f), PaletteScale::LINEAR } },
234 { QuantityId::STRAIN_RATE_CORRECTION_TENSOR, { Interval(0._f, 5._f), PaletteScale::LINEAR } },
235 { QuantityId::EPS_MIN, { Interval(0._f, 1._f), PaletteScale::LINEAR } },
236 { QuantityId::FRICTION, { Interval(0._f, 1._f), PaletteScale::LINEAR } },
237 { QuantityId::DELTASPH_DENSITY_GRADIENT, { Interval(0._f, 1._f), PaletteScale::LINEAR } },
238 { QuantityId::NEIGHBOR_CNT, { Interval(50._f, 150._f), PaletteScale::LINEAR } },
239 { ColorizerId::VELOCITY, { Interval(0.1_f, 100._f), PaletteScale::LOGARITHMIC } },
240 { ColorizerId::ACCELERATION, { Interval(0.1_f, 100._f), PaletteScale::LOGARITHMIC } },
241 { ColorizerId::MOVEMENT_DIRECTION, { Interval(0._f, 2._f * PI), PaletteScale::LINEAR } },
242 { ColorizerId::RADIUS, { Interval(0._f, 1.e3_f), PaletteScale::LINEAR } },
243 { ColorizerId::TOTAL_ENERGY, { Interval(1.e6_f, 1.e10_f), PaletteScale::LOGARITHMIC } },
244 { ColorizerId::TEMPERATURE, { Interval(100._f, 1.e7_f), PaletteScale::LOGARITHMIC } },
245 { ColorizerId::DENSITY_PERTURBATION, { Interval(-1.e-6_f, 1.e-6_f), PaletteScale::LINEAR } },
246 { ColorizerId::DAMAGE_ACTIVATION, { Interval(2.e-4_f, 8.e-4_f), PaletteScale::LINEAR } },
247 { ColorizerId::YIELD_REDUCTION, { Interval(0._f, 1._f), PaletteScale::LINEAR } },
248 { ColorizerId::TOTAL_STRESS, { Interval(0._f, 1e6_f), PaletteScale::LINEAR } },
249 });
250
getDefaultPalette(const Interval range)251 static Palette getDefaultPalette(const Interval range) {
252 const float x0 = float(range.lower());
253 const float dx = float(range.size());
254 return Palette({ { x0, Rgba(0.f, 0.f, 0.6f) },
255 { x0 + 0.2f * dx, Rgba(0.1f, 0.1f, 0.1f) },
256 { x0 + 0.6f * dx, Rgba(0.9f, 0.9f, 0.9f) },
257 { x0 + 0.8f * dx, Rgba(1.f, 1.f, 0.f) },
258 { x0 + dx, Rgba(0.6f, 0.f, 0.f) } },
259 PaletteScale::LINEAR);
260 }
261
getPalette(const ExtColorizerId id)262 Palette Factory::getPalette(const ExtColorizerId id) {
263 const PaletteDesc desc = paletteDescs[id];
264 const Interval range = desc.range;
265 const PaletteScale scale = desc.scale;
266 const float x0 = float(range.lower());
267 const float dx = float(range.size());
268 switch (id) {
269 case ColorizerId::VELOCITY:
270 return Palette({ { x0, Rgba(0.5f, 0.5f, 0.5f) },
271 { x0 + 0.001f * dx, Rgba(0.0f, 0.0f, 0.2f) },
272 { x0 + 0.01f * dx, Rgba(0.0f, 0.0f, 1.0f) },
273 { x0 + 0.1f * dx, Rgba(1.0f, 0.0f, 0.2f) },
274 { x0 + dx, Rgba(1.0f, 1.0f, 0.2f) } },
275 scale);
276 case ColorizerId::ACCELERATION:
277 return Palette({ { x0, Rgba(0.5f, 0.5f, 0.5f) },
278 { x0 + 0.001f * dx, Rgba(0.0f, 0.0f, 0.2f) },
279 { x0 + 0.01f * dx, Rgba(0.0f, 0.0f, 1.0f) },
280 { x0 + 0.1f * dx, Rgba(1.0f, 0.0f, 0.2f) },
281 { x0 + dx, Rgba(1.0f, 1.0f, 0.2f) } },
282 scale);
283 case ColorizerId::MOVEMENT_DIRECTION: {
284 SPH_ASSERT(range == Interval(0.f, 2._f * PI)); // in radians
285 const float pi = float(PI);
286 return Palette({ { 0.f, Rgba(0.1f, 0.1f, 1.f) },
287 { pi / 3.f, Rgba(1.f, 0.1f, 1.f) },
288 { 2.f * pi / 3.f, Rgba(1.f, 0.1f, 0.1f) },
289 { 3.f * pi / 3.f, Rgba(1.f, 1.f, 0.1f) },
290 { 4.f * pi / 3.f, Rgba(0.1f, 1.f, 0.1f) },
291 { 5.f * pi / 3.f, Rgba(0.1f, 1.f, 1.f) },
292 { 2.f * pi, Rgba(0.1f, 0.1f, 1.f) } },
293 scale);
294 }
295 case ColorizerId::DENSITY_PERTURBATION:
296 return Palette({ { x0, Rgba(0.1f, 0.1f, 1.f) },
297 { x0 + 0.5f * dx, Rgba(0.7f, 0.7f, 0.7f) },
298 { x0 + dx, Rgba(1.f, 0.1f, 0.1f) } },
299 scale);
300 case ColorizerId::TOTAL_ENERGY:
301 return Palette({ { x0, Rgba(0.f, 0.f, 0.6f) },
302 { x0 + 0.01f * dx, Rgba(0.1f, 0.1f, 0.1f) },
303 { x0 + 0.05f * dx, Rgba(0.9f, 0.9f, 0.9f) },
304 { x0 + 0.2f * dx, Rgba(1.f, 1.f, 0.f) },
305 { x0 + dx, Rgba(0.6f, 0.f, 0.f) } },
306 scale);
307 case ColorizerId::TEMPERATURE:
308 return Palette({ { x0, Rgba(0.1f, 0.1f, 0.1f) },
309 { x0 + 0.001f * dx, Rgba(0.1f, 0.1f, 1.f) },
310 { x0 + 0.01f * dx, Rgba(1.f, 0.f, 0.f) },
311 { x0 + 0.1f * dx, Rgba(1.0f, 0.6f, 0.4f) },
312 { x0 + dx, Rgba(1.f, 1.f, 0.f) } },
313 scale);
314 case ColorizerId::YIELD_REDUCTION:
315 return Palette({ { 0._f, Rgba(0.1f, 0.1f, 0.1f) }, { 1._f, Rgba(0.9f, 0.9f, 0.9f) } }, scale);
316 case ColorizerId::DAMAGE_ACTIVATION:
317 return Palette({ { x0, Rgba(0.1f, 0.1f, 1.f) },
318 { x0 + 0.5f * dx, Rgba(0.7f, 0.7f, 0.7f) },
319 { x0 + dx, Rgba(1.f, 0.1f, 0.1f) } },
320 scale);
321 case ColorizerId::RADIUS:
322 return Palette({ { x0, Rgba(0.1f, 0.1f, 1.f) },
323 { x0 + 0.5f * dx, Rgba(0.7f, 0.7f, 0.7f) },
324 { x0 + dx, Rgba(1.f, 0.1f, 0.1f) } },
325 scale);
326 default:
327 // check extended values
328 switch (QuantityId(id)) {
329 case QuantityId::PRESSURE:
330 SPH_ASSERT(x0 < -1.f);
331 return Palette({ { x0, Rgba(0.3f, 0.3f, 0.8f) },
332 { -1.e4f, Rgba(0.f, 0.f, 0.2f) },
333 { 0.f, Rgba(0.2f, 0.2f, 0.2f) },
334 { 1.e4f, Rgba(0.8f, 0.8f, 0.8f) },
335 { 2.e4f, Rgba(1.f, 1.f, 0.2f) },
336 { x0 + dx, Rgba(0.5f, 0.f, 0.f) } },
337 scale);
338 case QuantityId::ENERGY:
339 return Palette({ { x0, Rgba(0.1f, 0.1f, 0.1f) },
340 { x0 + 0.001f * dx, Rgba(0.1f, 0.1f, 1.f) },
341 { x0 + 0.01f * dx, Rgba(1.f, 0.f, 0.f) },
342 { x0 + 0.1f * dx, Rgba(1.0f, 0.6f, 0.4f) },
343 { x0 + dx, Rgba(1.f, 1.f, 0.f) } },
344 scale);
345 case QuantityId::DEVIATORIC_STRESS:
346 return Palette({ { x0, Rgba(0.f, 0.f, 0.2f) },
347 { x0 + 0.1f * dx, Rgba(0.9f, 0.9f, 0.9f) },
348 { x0 + 0.25f * dx, Rgba(1.f, 1.f, 0.2f) },
349 { x0 + 0.5f * dx, Rgba(1.f, 0.5f, 0.f) },
350 { x0 + dx, Rgba(0.5f, 0.f, 0.f) } },
351 scale);
352 case QuantityId::DENSITY:
353 case QuantityId::VELOCITY_LAPLACIAN:
354 case QuantityId::FRICTION:
355 case QuantityId::VELOCITY_GRADIENT_OF_DIVERGENCE:
356 return Palette({ { x0, Rgba(0.4f, 0.f, 0.4f) },
357 { x0 + 0.3f * dx, Rgba(0.3f, 0.3f, 1.f) },
358 { x0 + 0.5f * dx, Rgba(0.9f, 0.9f, 0.9f) },
359 { x0 + 0.7f * dx, Rgba(1.f, 0.f, 0.f) },
360 { x0 + dx, Rgba(1.f, 1.f, 0.f) } },
361 scale);
362 case QuantityId::DAMAGE:
363 return Palette({ { x0, Rgba(0.1f, 0.1f, 0.1f) }, { x0 + dx, Rgba(0.9f, 0.9f, 0.9f) } }, scale);
364 case QuantityId::MASS:
365 return Palette({ { x0, Rgba(0.1f, 0.1f, 0.1f) }, { x0 + dx, Rgba(0.9f, 0.9f, 0.9f) } }, scale);
366 case QuantityId::VELOCITY_DIVERGENCE:
367 SPH_ASSERT(x0 < 0._f);
368 return Palette({ { x0, Rgba(0.3f, 0.3f, 0.8f) },
369 { 0.1f * x0, Rgba(0.f, 0.f, 0.2f) },
370 { 0.f, Rgba(0.2f, 0.2f, 0.2f) },
371 { 0.1f * (x0 + dx), Rgba(0.8f, 0.8f, 0.8f) },
372 { x0 + dx, Rgba(1.0f, 0.6f, 0.f) } },
373 scale);
374 case QuantityId::VELOCITY_GRADIENT:
375 SPH_ASSERT(x0 == 0._f);
376 return Palette({ { 0._f, Rgba(0.3f, 0.3f, 0.8f) },
377 { 0.01f * dx, Rgba(0.f, 0.f, 0.2f) },
378 { 0.05f * dx, Rgba(0.2f, 0.2f, 0.2f) },
379 { 0.2f * dx, Rgba(0.8f, 0.8f, 0.8f) },
380 { dx, Rgba(1.0f, 0.6f, 0.f) } },
381 scale);
382 case QuantityId::ANGULAR_FREQUENCY:
383 SPH_ASSERT(x0 == 0._f);
384 return Palette({ { 0._f, Rgba(0.3f, 0.3f, 0.8f) },
385 { 0.25f * dx, Rgba(0.f, 0.f, 0.2f) },
386 { 0.5f * dx, Rgba(0.2f, 0.2f, 0.2f) },
387 { 0.75f * dx, Rgba(0.8f, 0.8f, 0.8f) },
388 { dx, Rgba(1.0f, 0.6f, 0.f) } },
389 scale);
390 case QuantityId::STRAIN_RATE_CORRECTION_TENSOR: {
391 // sqrt(3) is an important value, as it corresponds to identity tensor
392 const float actDx = max(dx, sqrt(3.f) + 0.2f);
393 const float eps = 0.05f;
394 return Palette({ { 0._f, Rgba(0.f, 0.0f, 0.5f) },
395 { sqrt(3.f) - eps, Rgba(0.9f, 0.9f, 0.9f) },
396 { sqrt(3.f), Rgba(1.f, 1.f, 0.f) },
397 { sqrt(3.f) + eps, Rgba(0.9f, 0.9f, 0.9f) },
398 { actDx, Rgba(0.5f, 0.0f, 0.0f) } },
399 scale);
400 }
401 case QuantityId::AV_BALSARA:
402 return Palette({ { x0, Rgba(0.1f, 0.1f, 0.1f) }, { x0 + dx, Rgba(0.9f, 0.9f, 0.9f) } }, scale);
403 case QuantityId::EPS_MIN:
404 return Palette({ { x0, Rgba(0.1f, 0.1f, 1.f) },
405 { x0 + 0.5f * dx, Rgba(0.7f, 0.7f, 0.7f) },
406 { x0 + dx, Rgba(1.f, 0.1f, 0.1f) } },
407 scale);
408 case QuantityId::MOMENT_OF_INERTIA:
409 return Palette({ { x0, Rgba(0.1f, 0.1f, 1.f) },
410 { x0 + 0.5f * dx, Rgba(0.7f, 0.7f, 0.7f) },
411 { x0 + dx, Rgba(1.f, 0.1f, 0.1f) } },
412 scale);
413 default:
414 return getDefaultPalette(Interval(x0, x0 + dx));
415 }
416 }
417 }
418
419 NAMESPACE_SPH_END
420