4#include <glm/gtx/quaternion.hpp>
7#include "Resources/MeshManager.h"
28 glm::vec3 triplePlaneIntersection(
const glm::vec4& eq1,
33 auto A = glm::determinant(glm::mat3(eq1.x, eq2.x, eq3.x,
35 eq1.z, eq2.z, eq3.z));
37 auto A1 = glm::determinant(glm::mat3(-eq1.w, -eq2.w, -eq3.w,
39 eq1.z, eq2.z, eq3.z));
41 auto A2 = glm::determinant(glm::mat3(eq1.x, eq2.x, eq3.x,
42 -eq1.w, -eq2.w, -eq3.w,
43 eq1.z, eq2.z, eq3.z));
45 auto A3 = glm::determinant(glm::mat3(eq1.x, eq2.x, eq3.x,
47 -eq1.w, -eq2.w, -eq3.w));
49 return (1.f / A)*glm::vec3(A1, A2, A3);
54void EchoSounder::getBoundingFrustum(vec4* planes,
55 const glm::quat& rotation,
56 const glm::vec3& translation,
57 const uint32_t coordSys,
58 const float minDirX,
const float maxDirX,
59 const float minDirY,
const float maxDirY,
60 const float depthMin,
const float depthMax)
62 auto d00 = rotation * getBeamDir(coordSys, minDirX, minDirY);
63 auto d01 = rotation * getBeamDir(coordSys, maxDirX, minDirY);
64 auto d10 = rotation * getBeamDir(coordSys, minDirX, maxDirY);
65 auto d11 = rotation * getBeamDir(coordSys, maxDirX, maxDirY);
67 auto avg = normalize(d00 + d01 + d10 + d11);
70 normalize(cross(d00, d01)),
71 normalize(cross(d11, d10)),
72 normalize(cross(d01, d11)),
73 normalize(cross(d10, d00)),
76 auto b = min(min(dot(d00, avg), dot(d10, avg)),
77 min(dot(d01, avg), dot(d11, avg)));
79 planes[0] = vec4(n[0], -dot(n[0], translation));
80 planes[1] = vec4(n[1], -dot(n[1], translation));
81 planes[2] = vec4(n[2], -dot(n[2], translation));
82 planes[3] = vec4(n[3], -dot(n[3], translation));
83 planes[4] = vec4(avg, -b*depthMin - dot(avg, translation));
84 planes[5] = vec4(-avg, depthMax + dot(avg, translation));
94void EchoSounder::getAxisAlignedBoundingBox(glm::vec3& minCorner,
96 const glm::quat& rotation,
97 const glm::vec3& translation,
98 const uint32_t coordSys,
99 const float minDirX,
const float maxDirX,
100 const float minDirY,
const float maxDirY,
101 const float depthMin,
const float depthMax)
104 auto sx = sin(minDirX);
105 auto sy = sin(minDirY);
106 float r = glm::sqrt(1.f - sx*sx - sy*sy);
108 vec3 _min = depthMin*(rotation * vec3(sx, sy, r));
111 for (uint32_t j = 0; j < 25; j++) {
112 auto v = (1.f / 24.f)*j;
114 for (uint32_t i = 0; i < 25; i++) {
115 auto u = (1.f / 24.f)*i;
116 auto sx_ = sin((1.f - u)*minDirX + u*maxDirX);
117 auto sy_ = sin((1.f - v)*minDirY + v*maxDirY);
118 float r_ = glm::sqrt(1.f - sx_*sx_ - sy_*sy_);
119 auto p = (rotation * vec3(sx_, sy_, r_));
122 _min = min(_min, min(a, b));
123 _max = max(_max, max(a, b));
127 minCorner = _min + translation;
128 maxCorner = _max + translation;
131 assert(
false &&
"FIXME");
135vec3 EchoSounder::getBeamDir(uint32_t coordSys,
float dirX,
float dirY)
144 float r = glm::sqrt(1.f - sx*sx - sy*sy);
145 rv = vec3(sx, sy, r);
155 rv = vec3(sx, sy*cx, cx*cy);
164 rv = vec3(cx*cy, cx*sy, -sx);
168 assert(
false &&
"unrecognized coordinate system");
175bool EchoSounder::isXDominant(
const std::vector<float> &directionX,
const std::vector<float> &directionY)
177 return std::abs(directionY.back() - directionY.front()) < std::abs(directionX.back() - directionX.front());
181void EchoSounder::getArrayToVesselTransform(quat& rotation,
186 auto aX = angleAxis(alpha.x, vec3(1, 0, 0));
187 auto aY = angleAxis(alpha.y, vec3(0, 1, 0));
188 auto aZ = angleAxis(alpha.z, vec3(0, 0, 1));
189 auto a = aZ * aY * aX;
196 auto bX = angleAxis(radians(180.f), vec3(1, 0, 0));
197 auto bZ = angleAxis(radians(-90.f), vec3(0, 0, 1));
201 translation = b * offset;
206void EchoSounder::inflateFans(std::vector<float>& directionX,
207 std::vector<float>& directionY,
208 const std::vector<float>& inDirectionX,
209 const std::vector<float>& inBeamWidthX,
210 const std::vector<float>& inDirectionY,
211 const std::vector<float>& inBeamWidthY,
212 const std::vector<uint32_t>& beams,
214 const size_t minorCount)
216 const size_t majorCount = beams.size() / minorCount;
217 if (beams.size() == 1) {
218 const auto srcIx = beams[0];
219 directionX.resize(4);
220 directionY.resize(4);
221 directionX[0] = inDirectionX[srcIx] - 0.5f*inBeamWidthX[srcIx];
222 directionY[0] = inDirectionY[srcIx] - 0.5f*inBeamWidthY[srcIx];
223 directionX[1] = inDirectionX[srcIx] - 0.5f*inBeamWidthX[srcIx];
224 directionY[1] = inDirectionY[srcIx] + 0.5f*inBeamWidthY[srcIx];
225 directionX[2] = inDirectionX[srcIx] + 0.5f*inBeamWidthX[srcIx];
226 directionY[2] = inDirectionY[srcIx] - 0.5f*inBeamWidthY[srcIx];
227 directionX[3] = inDirectionX[srcIx] + 0.5f*inBeamWidthX[srcIx];
228 directionY[3] = inDirectionY[srcIx] + 0.5f*inBeamWidthY[srcIx];
230 else if (majorCount == 1 || minorCount == 1) {
231 size_t largestDimensionCount = std::max(majorCount, minorCount);
232 bool xDom = isXDominant(inDirectionX, inDirectionY);
233 directionX.resize(2 * largestDimensionCount);
234 directionY.resize(2 * largestDimensionCount);
235 for (
size_t i = 0; i < largestDimensionCount; i++) {
236 const auto srcIx = beams[i];
237 directionX[i] = inDirectionX[srcIx] - (xDom ? 0.0f : 0.5f)*inBeamWidthX[srcIx];
238 directionY[i] = inDirectionY[srcIx] - (xDom ? 0.5f : 0.f)*inBeamWidthY[srcIx];
239 directionX[i + minorCount] = inDirectionX[srcIx] + (xDom ? 0.f : 0.5f)*inBeamWidthX[srcIx];
240 directionY[i + minorCount] = inDirectionY[srcIx] + (xDom ? 0.5f : 0.f)*inBeamWidthY[srcIx];
248 const glm::quat& rotation,
249 const glm::vec3& translation,
250 const uint32_t coordSys,
251 const float* dirX,
const size_t nX,
252 const float* dirY,
const size_t nY,
253 const float depthMin,
const float depthMax)
255 auto minorCount = nX;
256 auto majorCount = nY;
258 auto mesh = context->meshManager->create();
260 auto P = mesh->mapPositions(0, 2 * minorCount*majorCount);
261 auto C = mesh->map<glm::vec4>(VertexDataType::Colors0, VertexFormats::Color4f, 0, 2 * minorCount*majorCount);
264 std::vector<uint32_t> indices;
265 indices.reserve(8 * majorCount*minorCount);
266 for (
size_t j = 0; j < majorCount; j++) {
267 for (
size_t i = 0; i < minorCount; i++) {
268 float v = i / (minorCount - 1.f);
269 float u = j / (majorCount - 1.f);
271 auto d = rotation *getBeamDir(coordSys, dirX[j], dirY[i]);
276 P[2 * (minorCount*j + i) + 0] = translation + depthMin*d;
277 P[2 * (minorCount*j + i) + 1] = translation + depthMax*d;
278 C[2 * (minorCount*j + i) + 0] = glm::vec4(u, v, 0.f, 1.f);
279 C[2 * (minorCount*j + i) + 1] = glm::vec4(u, v, 0.f, 1.f);
282 indices.push_back(
static_cast<uint32_t
>(2 * (minorCount*j + i - 1) + 0));
283 indices.push_back(
static_cast<uint32_t
>(2 * (minorCount*j + i) + 0));
284 indices.push_back(
static_cast<uint32_t
>(2 * (minorCount*j + i - 1) + 1));
285 indices.push_back(
static_cast<uint32_t
>(2 * (minorCount*j + i) + 1));
288 indices.push_back(
static_cast<uint32_t
>(2 * (minorCount*(j - 1) + i) + 0));
289 indices.push_back(
static_cast<uint32_t
>(2 * (minorCount*j + i) + 0));
290 indices.push_back(
static_cast<uint32_t
>(2 * (minorCount*(j - 1) + i) + 1));
291 indices.push_back(
static_cast<uint32_t
>(2 * (minorCount*j + i) + 1));
295 indices.push_back(
static_cast<uint32_t
>(2 * (minorCount * 0 + 0) + 0));
296 indices.push_back(
static_cast<uint32_t
>(2 * (minorCount * 0 + 0) + 1));
297 indices.push_back(
static_cast<uint32_t
>(2 * (minorCount * 0 + minorCount - 1) + 0));
298 indices.push_back(
static_cast<uint32_t
>(2 * (minorCount * 0 + minorCount - 1) + 1));
299 indices.push_back(
static_cast<uint32_t
>(2 * (minorCount * (majorCount - 1) + 0) + 0));
300 indices.push_back(
static_cast<uint32_t
>(2 * (minorCount * (majorCount - 1) + 0) + 1));
301 indices.push_back(
static_cast<uint32_t
>(2 * (minorCount * (majorCount - 1) + minorCount - 1) + 0));
302 indices.push_back(
static_cast<uint32_t
>(2 * (minorCount * (majorCount - 1) + minorCount - 1) + 1));
305 mesh->setIndexData(indices.data(), indices.size());
313void EchoSounder::buildBeamBundleOutline2(std::vector<glm::vec3>& V,
314 std::vector<uint32_t>& indices,
316 const glm::quat& rotation,
317 const glm::vec3& translation,
318 const uint32_t coordSys,
319 const float* dirX,
const size_t nX,
320 const float* dirY,
const size_t nY,
321 const float depthMin,
const float depthMax,
322 const bool minorClosed,
323 const bool individualBeams)
325 auto minorCount = nY;
326 auto majorCount = nX;
328 size_t numDepthRings = 2;
329 std::vector<float> depthRingValues;
330 for (
size_t k = 0; k < numDepthRings; ++k) {
331 depthRingValues.push_back((depthMax - depthMin) * (k / (numDepthRings - 1.f)) + depthMin);
334 auto mesh = context->meshManager->create();
336 for (uint32_t j = 0; j < majorCount; j++) {
337 for (uint32_t i = 0; i < minorCount; i++) {
338 auto d = rotation *getBeamDir(coordSys,
339 dirX[minorCount*j + i],
340 dirY[minorCount*j + i]);
342 for (
size_t k = 0; k < numDepthRings; ++k) {
343 V.push_back(translation + depthRingValues[k] * d);
347 if (0 < i && (individualBeams || j == 0 || j == majorCount -1)) {
348 for (
size_t k = 0; k < numDepthRings; ++k) {
349 indices.push_back(
static_cast<uint32_t
>(numDepthRings * (minorCount*j + i - 1) + k));
350 indices.push_back(
static_cast<uint32_t
>(numDepthRings * (minorCount*j + i) + k));
356 if (0 < j && (individualBeams || i == 0 || i == minorCount - 1)) {
357 for (
size_t k = 0; k < numDepthRings; ++k) {
358 indices.push_back(
static_cast<uint32_t
>(numDepthRings * (minorCount*(j - 1) + i) + k));
359 indices.push_back(
static_cast<uint32_t
>(numDepthRings * (minorCount*j + i) + k));
369 indices.push_back(
static_cast<uint32_t
>(numDepthRings * (minorCount * 0 + 0) + 0));
370 indices.push_back(
static_cast<uint32_t
>(numDepthRings * (minorCount * 0 + 0) + numDepthRings - 1));
371 indices.push_back(
static_cast<uint32_t
>(numDepthRings * (minorCount * 0 + minorCount - 1) + 0));
372 indices.push_back(
static_cast<uint32_t
>(numDepthRings * (minorCount * 0 + minorCount - 1) + numDepthRings - 1));
373 indices.push_back(
static_cast<uint32_t
>(numDepthRings * (minorCount * (majorCount - 1) + 0) + 0));
374 indices.push_back(
static_cast<uint32_t
>(numDepthRings * (minorCount * (majorCount - 1) + 0) + numDepthRings - 1));
375 indices.push_back(
static_cast<uint32_t
>(numDepthRings * (minorCount * (majorCount - 1) + minorCount - 1) + 0));
376 indices.push_back(
static_cast<uint32_t
>(numDepthRings * (minorCount * (majorCount - 1) + minorCount - 1) + numDepthRings - 1));
381 const glm::vec4* planes)
383 auto mesh = context->meshManager->create();
384 auto P = mesh->mapPositions(0, 8);
385 auto C = mesh->map<glm::vec4>(VertexDataType::Colors0, VertexFormats::Color4f, 0, 8);
387 for (
int i = 0; i < 8; i++) {
388 P[i] = triplePlaneIntersection(planes[0 + ((i >> 0) & 1)],
389 planes[2 + ((i >> 1) & 1)],
390 planes[4 + ((i >> 2) & 1)]);
391 C[i] = glm::vec4(0, 1, 1, 1);
394 std::vector<uint32_t> indices =
396 0, 1, 1, 3, 3, 2, 2, 0,
397 4, 5, 5, 7, 7, 6, 6, 4,
398 0, 4, 1, 5, 2, 6, 3, 7
401 mesh->setIndexData(indices.data(), indices.size());
410 const glm::vec3& minCorner,
411 const glm::vec3& maxCorner)
413 auto mesh = context->meshManager->create();
414 auto P = mesh->mapPositions(0, 8);
415 auto C = mesh->map<glm::vec4>(VertexDataType::Colors0, VertexFormats::Color4f, 0, 8);
417 for (
int i = 0; i < 8; i++) {
418 P[i] = vec3(((i >> 0) & 1) == 0 ? minCorner.x : maxCorner.x,
419 ((i >> 1) & 1) == 0 ? minCorner.y : maxCorner.y,
420 ((i >> 2) & 1) == 0 ? minCorner.z : maxCorner.z);
421 C[i] = glm::vec4(0, 0, 1, 1);
424 std::vector<uint32_t> indices =
426 0, 1, 1, 3, 3, 2, 2, 0,
427 4, 5, 5, 7, 7, 6, 6, 4,
428 0, 4, 1, 5, 2, 6, 3, 7
431 mesh->setIndexData(indices.data(), indices.size());
439 const glm::vec3& beamStartPos,
440 const std::vector<glm::vec3>& beamDir,
const size_t startBeamIndex,
441 const float minVerticalDepth,
const float maxVerticalDepth,
442 const float depthOffset,
const float depthStep,
const float maxRange,
443 const size_t beamCount,
const size_t sampleCount)
446 for (
size_t j = 0; j < beamCount; ++j) {
447 auto valueIndex = startValueIndex + j * sampleCount;
448 auto & d = beamDir[j + startBeamIndex];
449 auto & o = beamStartPos;
452 if (minVerticalDepth < 1.f) {
455 else if (-maxRange * d.z < minVerticalDepth) {
459 float t0 = -(minVerticalDepth + o.z) / d.z;
460 la =
static_cast<uint32_t
>(std::max(0.f, std::floor((t0 - depthOffset) / depthStep)));
462 la = std::min(la, sampleCount);
465 if (maxVerticalDepth <= minVerticalDepth) {
468 else if (-maxRange * d.z < minVerticalDepth) {
472 float t0 = -(maxVerticalDepth + o.z) / d.z;
473 lb = std::max(la,
static_cast<size_t>(std::max(0.f, std::floor((t0 - depthOffset) / depthStep))));
475 lb = std::min(lb, sampleCount);
477 auto out1 = valueIndex + 0;
478 for (
size_t i = 0; i < la; i++) {
479 values[out1++] = 0.f;
482 auto out2 = valueIndex + lb;
483 for (
size_t i = lb; i < sampleCount; i++) {
484 values[out2++] = 0.f;
A Context instance contains all the services, systems and runtime components needed to use Cogs.
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
Cogs::Geometry::BoundingBox COGSCORE_DLL_API calculateBounds(Mesh *mesh)
Calculate a bounding box for the given mesh.