1#include "Resources/MeshManager.h"
3#include "../Components/BeamGroupComponent.h"
4#include "../Components/DataSetComponent.h"
5#include "../Components/WindowComponent.h"
6#include "../Systems/SwathBottomSystem.h"
8#include "../BeamUtils.h"
10#include "../Tasks/SwathSeabedBuildMeshTask.h"
11#include "../Tasks/BeamResampleTask.h"
13#include <glm/gtx/compatibility.hpp>
15Cogs::Core::EchoSounder::SwathSeabedBuildMeshTask::SwathSeabedBuildMeshTask(
Cogs::Core::Context* context,
17 const uint32_t chunkIndex,
22: SwathBuildMeshTask(context, mesh, chunkIndex, swathData.pathSpacing, swathData.beamSpacing, groupComp, dataData, swathData.resamplingPositions, swathData.chunks),
23 uTexDom(swathComp.uTextureDomain),
24 uTexRange(swathComp.uTextureRange),
25 vTexDom(swathComp.vTextureDomain),
26 vTexRange(swathComp.vTextureRange)
28 const auto & dataConf = dataData.persistent->config;
29 const auto & buffer = dataData.persistent->buffer;
31 depths.resize(beamCount * sliceCount);
32 reflectivities.resize(beamCount * sliceCount);
34 const auto beamCount_src = dataConf.beamCount;
35 for (uint32_t i = 0; i < sliceCount; i++) {
36 uint32_t k = (bix_a + i) % dataConf.capacity;
37 for (uint32_t j = 0; j < beamCount; j++) {
38 const auto ix = beams[j];
39 depths[beamCount*i + j] = buffer.bottomDepths[beamCount_src*k + ix];
40 reflectivities[beamCount*i + j] = buffer.bottomReflectivities[beamCount_src*k + ix];
45Cogs::Core::EchoSounder::SwathSeabedBuildMeshTask::SwathSeabedBuildMeshTask(
const SwathSeabedBuildMeshTask& other)
46: SwathBuildMeshTask(other),
47 uTexDom(other.uTexDom),
48 vTexDom(other.vTexDom),
49 uTexRange(other.uTexRange),
50 vTexRange(other.vTexRange)
52 depths.copy(other.depths);
53 reflectivities.copy(other.reflectivities);
56void Cogs::Core::EchoSounder::SwathSeabedBuildMeshTask::operator()()
62 for (uint32_t i = 0; i < sliceCount*beamCount; i++) {
63 if (depths[i] == 0.f) depths[i] = std::numeric_limits<float>::quiet_NaN();
66 if (pathSpacing != 0.f) {
70 std::vector<glm::vec3> beamDir(beamCount);
71 for (uint32_t i = 0; i < beamCount; i++) {
72 beamDir[i] = metaPings[0].arrayOrientationVessel * EchoSounder::getBeamDir(coordSys, directionX[i], directionY[i]);
75 if (beamSpacing != 0.f) {
76 beamResample(beamDir);
79 auto proxy = context->meshManager->createLocked();
80 auto P = proxy->mapPositions(0, sliceCount*beamCount);
81 auto N = proxy->map<glm::vec3>(VertexDataType::Normals, VertexFormats::Norm3f, 0, sliceCount*beamCount);
82 auto T = proxy->map<glm::vec2>(VertexDataType::TexCoords0, VertexFormats::Tex2f, 0, sliceCount*beamCount);
83 auto bbox = Cogs::Geometry::makeEmptyBoundingBox<Cogs::Geometry::BoundingBox>();
84 std::vector<uint32_t> indices;
85 std::vector<uint32_t> supportIndices;
87 calcVertexPositions(bbox, P, T, beamDir);
88 calcIndices(indices, supportIndices);
89 calcNormalVectors(P, N, indices, supportIndices);
90 if (!indices.empty()) {
91 proxy->setIndexData(indices.data(), indices.size());
94 proxy->setBounds(bbox);
96 mesh = proxy.getHandle();
97 if (context->callbacks.resourceLoadCallback) {
100 context->callbacks.resourceLoadCallback(context, 0, -1, 0);
105void Cogs::Core::EchoSounder::SwathSeabedBuildMeshTask::pathResample()
107 auto sliceCount_new =
static_cast<uint32_t
>(resamplingPositions.size());
109 decltype(depths) newDepths(beamCount * sliceCount_new);
110 decltype(reflectivities) newReflectivities(beamCount * sliceCount_new);
111 decltype(metaPings) newMetaPings(sliceCount_new);
113 const auto o = resamplingPositions[0].bufferIndex;
114 for (uint32_t i = 0; i < sliceCount_new; i++) {
115 const auto k = (resamplingPositions[i].bufferIndex - o + bufferCapacity) % bufferCapacity;
116 const auto t = resamplingPositions[i].fractional;
117 const auto s = (1.f - t);
119 newMetaPings[i].vesselPositionGlobal = s*metaPings[k].vesselPositionGlobal + t*metaPings[k + 1].vesselPositionGlobal;
120 newMetaPings[i].arrayPositionVessel = metaPings[k].arrayPositionVessel;
121 newMetaPings[i].arrayPositionGlobal = s*metaPings[k].arrayPositionGlobal + t*metaPings[k + 1].arrayPositionGlobal;
123 newMetaPings[i].vesselOrientationGlobal = glm::slerp(metaPings[k].vesselOrientationGlobal, metaPings[k + 1].vesselOrientationGlobal, t);
124 newMetaPings[i].arrayOrientationVessel = metaPings[k].arrayOrientationVessel;
125 newMetaPings[i].arrayOrientationGlobal = newMetaPings[i].vesselOrientationGlobal * newMetaPings[i].arrayOrientationVessel;
128 for (uint32_t j = 0; j < beamCount; j++) {
129 newDepths[beamCount*i + j] = s*depths[beamCount*k + j] + t*depths[beamCount*(k + 1) + j];
130 newReflectivities[beamCount*i + j] = s*reflectivities[beamCount*k + j] + t*reflectivities[beamCount*(k + 1) + j];
134 depths.swap(newDepths);
135 reflectivities.swap(newReflectivities);
136 metaPings.swap(newMetaPings);
137 sliceCount = sliceCount_new;
140void Cogs::Core::EchoSounder::SwathSeabedBuildMeshTask::beamResample(std::vector<glm::vec3>& beamDir)
142 if (beamSpacing == 0.0)
return;
144 std::vector<float> minorAngles(beamCount);
145 minorAngles[0] = 0.f;
146 for (uint32_t i = 1; i < beamCount; i++) {
147 minorAngles[i] = minorAngles[i - 1] + std::acos(glm::dot(beamDir[i - 1], beamDir[i]));
149 float clampedStep = std::max(beamSpacing, abs((minorAngles.back() - minorAngles.front()) / (maxBeamUpsample*beamCount)));
151 std::vector<InterpolationSamplePos> samplesOut;
152 SetupBeamFilterUnivariate(samplesOut, minorAngles, clampedStep, beamCount);
154 uint32_t beamCountNew =
static_cast<uint32_t
>(samplesOut.size());
156 std::vector<glm::vec3> beamDirNew(beamCountNew);
157 for (uint32_t i = 0; i < beamCountNew; i++) {
158 const auto & d0 = beamDir[samplesOut[i].i + 0];
159 const auto & d1 = beamDir[samplesOut[i].i + 1];
162 const auto G = std::acos(glm::dot(d0, d1));
163 const auto t = samplesOut[i].t;
164 const auto d = (1.f / std::sin(G))*(std::sin(G*(1.f - t))*d0 + std::sin(G*t)*d1);
171 for (uint32_t j = 0; j < sliceCount; j++) {
172 for (uint32_t i = 0; i < beamCountNew; i++) {
174 const auto & s = samplesOut[i];
175 const auto depthA = depths[j*beamCount + s.i] * beamDir[s.i].z;
176 const auto depthB = depths[j*beamCount + s.i + 1] * beamDir[s.i + 1].z;
177 const auto depth = ((1.f - s.t)*depthA + s.t*depthB) / beamDirNew[i].z;
178 depths_new[j*beamCountNew + i] = depth;
179 const auto reflA = reflectivities[j*beamCount + s.i];
180 const auto reflB = reflectivities[j*beamCount + s.i + 1];
181 reflectivities_new[j*beamCountNew + i] = (1.f - s.t)*reflA + s.t*reflB;
185 beamDir.swap(beamDirNew);
186 depths.swap(depths_new);
187 reflectivities.swap(reflectivities_new);
188 beamCount = beamCountNew;
191template<
typename PType,
typename TType,
typename DType>
192void Cogs::Core::EchoSounder::SwathSeabedBuildMeshTask::calcVertexPositions(Cogs::Geometry::BoundingBox& bbox, PType& P, TType& T, DType& beamDir)
194 const glm::vec2 uReMap(uTexRange.x, 1.f / glm::max(std::numeric_limits<float>::min(), uTexRange.y - uTexRange.x));
195 const glm::vec2 vReMap(vTexRange.x, 1.f / glm::max(std::numeric_limits<float>::min(), vTexRange.y - vTexRange.x));
196 for (uint32_t s = 0; s < sliceCount; s++) {
197 for (uint32_t b = 0; b < beamCount; b++) {
198 const auto o = s*beamCount + b;
199 const auto d = depths[o];
200 const auto p = metaPings[s].arrayPositionGlobal + d * (metaPings[s].vesselOrientationGlobal * beamDir[b]);
202 if (std::isfinite(d)) {
208 float e[
static_cast<int32_t
>(EchoSounder::SwathBottomComponent::TextureDomain::Size)];
209 e[
static_cast<int32_t
>(EchoSounder::SwathBottomComponent::TextureDomain::Zero)] = 0.f;
210 e[
static_cast<int32_t
>(EchoSounder::SwathBottomComponent::TextureDomain::One)] = 1.f;
211 e[
static_cast<int32_t
>(EchoSounder::SwathBottomComponent::TextureDomain::PositionX)] = p.x;
212 e[
static_cast<int32_t
>(EchoSounder::SwathBottomComponent::TextureDomain::PositionY)] = p.y;
213 e[
static_cast<int32_t
>(EchoSounder::SwathBottomComponent::TextureDomain::VerticalDepth)] = -p.z;
214 e[
static_cast<int32_t
>(EchoSounder::SwathBottomComponent::TextureDomain::BeamDistance)] = d;
215 e[
static_cast<int32_t
>(EchoSounder::SwathBottomComponent::TextureDomain::Reflectivity)] = reflectivities[o];
216 float tu = e[
static_cast<int32_t
>(uTexDom)];
217 float tv = e[
static_cast<int32_t
>(vTexDom)];
218 T[o].x = uReMap.y*(tu - uReMap.x);
219 T[o].y = vReMap.y*(tv - vReMap.x);
224template<
typename PType,
typename NType,
typename IType>
225void Cogs::Core::EchoSounder::SwathSeabedBuildMeshTask::calcNormalVectors(PType& P, NType& N, IType& I1, IType& I2) {
226 for (uint32_t i = 0; i < sliceCount*beamCount; i++) {
227 N[i] = glm::vec3(0.0);
230 calcNormalVectors(P, N, I1);
231 calcNormalVectors(P, N, I2);
233 for (uint32_t i = 0; i < sliceCount*beamCount; i++) {
234 N[i] = glm::normalize(N[i]);
235 if (!glm::all(glm::isfinite(N[i]))) {
236 N[i] = glm::vec3(0, 0, 1);
241template<
typename PType,
typename NType,
typename IType>
242void Cogs::Core::EchoSounder::SwathSeabedBuildMeshTask::calcNormalVectors(PType& P, NType& N, IType& I)
244 for (uint32_t i = 0; i < I.size(); ) {
245 auto index0 = I[i++];
246 auto index1 = I[i++];
247 auto index2 = I[i++];
251 auto n = glm::cross(p2 - p0, p1 - p0);
258void Cogs::Core::EchoSounder::SwathSeabedBuildMeshTask::calcIndices(std::vector<uint32_t>& indices,
259 std::vector<uint32_t>& supportIndices)
262 indices.reserve(6 * sliceCount*beamCount);
263 supportIndices.clear();
264 supportIndices.reserve(6 * beamCount *(sliceA + (sliceCount-1 - sliceB)));
266 for (uint32_t s = 0; s + 1 < sliceCount; ++s) {
267 for (uint32_t b = 0; b + 1 < beamCount; b++) {
268 auto c00 = (s + 0)*beamCount + (b + 0);
269 auto c01 = (s + 0)*beamCount + (b + 1);
270 auto c10 = (s + 1)*beamCount + (b + 0);
271 auto c11 = (s + 1)*beamCount + (b + 1);
273 uint32_t CellIndices[2][3] = { { (uint32_t)c00, (uint32_t)c01, (uint32_t)c10 },{ (uint32_t)c11, (uint32_t)c10, (uint32_t)c01 } };
274 if (!isfinite(depths[c01]) || !isfinite(depths[c10])) {
275 CellIndices[0][0] = c01;
276 CellIndices[0][1] = c11;
277 CellIndices[0][2] = c00;
278 CellIndices[1][0] = c10;
279 CellIndices[1][1] = c00;
280 CellIndices[1][2] = c11;
283 for (
int t = 0; t < 2; t++) {
284 if (!isfinite(depths[CellIndices[t][0]]) ||
285 !isfinite(depths[CellIndices[t][1]]) ||
286 !isfinite(depths[CellIndices[t][2]]))
290 auto& indicesList = (s < sliceA || s >= sliceB) ? supportIndices : indices;
292 indicesList.push_back(CellIndices[t][0]);
293 indicesList.push_back(CellIndices[t][1]);
294 indicesList.push_back(CellIndices[t][2]);
A Context instance contains all the services, systems and runtime components needed to use Cogs.
@ ClockwiseWinding
The mesh uses clockwise winding order for it's triangles as opposed to the counter-clockwise default.
@ TriangleList
List of triangles.