Cogs.Core
DensityFieldTask.cpp
1#include "Platform/Instrumentation.h"
2
3#include "../Extensions/IsoSurfaces/IsoSurfaces.h"
4
5#include "Resources/Buffer.h"
6
7#include "Blur.h"
8
9#include "../Tasks/DensityFieldTask.h"
10#include "../Systems/DensityFieldSystem.h"
11
12#include "Foundation/Platform/Timer.h"
13
14void Cogs::Core::Volumetric::DensityFieldTaskData::update(Context * ctx,
15 DensityFieldComponent &fieldComp,
16 DensityFieldData& fieldData,
17 BufferView<glm::vec3> positions,
18 BufferView<float> data)
19{
20 CpuInstrumentationScope(SCOPE_VOLUMETRIC, "DensityTask::update");
21
22 context = ctx;
23
24 thresholds = fieldComp.thresholds;
25 if (16 < thresholds.size()) thresholds.resize(16);
26
27 resolution = fieldData.resolution;
28
29 dataAttached = fieldComp.attachData
30 && data
31 && data.size() == positions.size();
32
33 const auto extent = fieldComp.extentMax - fieldComp.extentMin;
34 const auto cellSize = glm::vec3(1.f / fieldComp.resolution.x,
35 1.f / fieldComp.resolution.y,
36 1.f / fieldComp.resolution.z)*extent;
37
38
39 densityWeight = fieldComp.pointWeight;
40 boxFilterWidth = Blur::boxFilterWidthFromStdDev(fieldComp.basisStdDev / glm::max(glm::max(cellSize.x, cellSize.y), cellSize.z),
41 fieldComp.basisQuality);
42 boxFilterIterations = fieldComp.basisQuality;
43 extentMin = fieldComp.extentMin;
44 extentMax = fieldComp.extentMax;
45
46 rPositions.resize(positions.size());
47 rData.resize(positions.size());
48
49 std::memcpy(rPositions.data(), positions.data(), rPositions.size() * sizeof(glm::vec3));
50 if (dataAttached) {
51 std::memcpy(rData.data(), data.data(), rData.size() * sizeof(float));
52 }
53
54 attachedDataScale = fieldComp.attachedDataScale;
55 attachedDataOffset = fieldComp.attachedDataOffset;
56}
57
58void Cogs::Core::Volumetric::DensityFieldTask::operator()()
59{
60 CpuInstrumentationScope(SCOPE_VOLUMETRIC, "DensityTask::compute");
61
62 auto & data = *persistentData.get();
63
64 const glm::vec3 s = glm::vec3(data.resolution) / (data.extentMax - data.extentMin);
65 const glm::vec3 o = -data.extentMin;
66 const auto dts = data.attachedDataScale;
67 const auto dto = data.attachedDataOffset;
68
69 data.points.clear();
70 data.points.reserve(data.rPositions.size());
71
72 for (size_t i = 0; i < data.rPositions.size(); i++) {
73 glm::uvec3 k(s*(data.rPositions.data()[i] + o));
74 if ((k.x < data.resolution.x)
75 && (k.y < data.resolution.y)
76 && (k.z < data.resolution.z)) {
77 data.points.push_back({ k, data.dataAttached ? dts * (data.rData.data()[i] + dto) : 0.f });
78 }
79 }
80
81 const auto X = data.resolution.x;
82 const auto Y = data.resolution.y;
83 const auto Z = data.resolution.y;
84 const auto numCells = X * Y * Z;
85 const auto w = data.densityWeight;
86
87 data.densityField.resize(numCells, false);
88 std::memset(data.densityField.data(), 0, data.densityField.byteSize());
89
90 auto phi = data.densityField.data();
91 for (auto & p : data.points) {
92 phi[(p.ix.z*Y + p.ix.y)*X + p.ix.x] += w;
93 }
94
95 data.densityFieldOut.resize(numCells, false);
96 Blur::boxFilterIterations3D(data.context,
97 data.densityFieldOut.data(),
98 data.densityField.data(),
99 data.resolution,
100 data.boxFilterWidth,
101 data.boxFilterIterations);
102
103 if (data.dataAttached) {
104 data.dataField.resize(numCells);
105 std::memset(data.dataField.data(), 0, data.dataField.byteSize());
106
107 auto F = data.dataField.data();
108
109 for (auto & p : data.points) {
110 F[(p.ix.z*Y + p.ix.y)*X + p.ix.x] += w * p.data;
111 }
112
113 data.dataFieldOut.resize(numCells);
114 Blur::boxFilterIterations3D(data.context,
115 data.dataFieldOut.data(),
116 data.dataField.data(),
117 data.resolution,
118 data.boxFilterWidth,
119 data.boxFilterIterations);
120 }
121
122 IsoSurfaces::Scratch scratch;
123 data.mesh = IsoSurfaces::createIsoSurfacesMesh(data.context,
124 scratch,
125 data.thresholds,
126 data.densityFieldOut.data(),
127 data.dataAttached ? data.dataFieldOut.data() : nullptr,
128 data.resolution,
129 data.extentMin, data.extentMax, false, false, true, true, true, true, true, true,
130 data.mesh);
131}