| 391 | |
| 392 | template <class E, class I> |
| 393 | void addSkirt( |
| 394 | const CesiumGeospatial::Ellipsoid& ellipsoid, |
| 395 | const glm::dvec3& center, |
| 396 | const CesiumGeospatial::GlobeRectangle& rectangle, |
| 397 | double minimumHeight, |
| 398 | double maximumHeight, |
| 399 | uint32_t currentVertexCount, |
| 400 | uint32_t currentIndicesCount, |
| 401 | double skirtHeight, |
| 402 | double longitudeOffset, |
| 403 | double latitudeOffset, |
| 404 | const std::vector<glm::dvec3>& uvsAndHeights, |
| 405 | const std::span<const E>& edgeIndices, |
| 406 | const std::span<float>& positions, |
| 407 | const std::span<float>& normals, |
| 408 | const std::span<I>& indices, |
| 409 | glm::dvec3& positionMinimums, |
| 410 | glm::dvec3& positionMaximums) { |
| 411 | const double west = rectangle.getWest(); |
| 412 | const double south = rectangle.getSouth(); |
| 413 | const double east = rectangle.getEast(); |
| 414 | const double north = rectangle.getNorth(); |
| 415 | |
| 416 | size_t newEdgeIndex = currentVertexCount; |
| 417 | size_t positionIdx = static_cast<size_t>(currentVertexCount * 3); |
| 418 | size_t indexIdx = currentIndicesCount; |
| 419 | for (size_t i = 0; i < edgeIndices.size(); ++i) { |
| 420 | E edgeIdx = edgeIndices[i]; |
| 421 | |
| 422 | const double uRatio = uvsAndHeights[edgeIdx].x; |
| 423 | const double vRatio = uvsAndHeights[edgeIdx].y; |
| 424 | const double heightRatio = uvsAndHeights[edgeIdx].z; |
| 425 | const double longitude = Math::lerp(west, east, uRatio) + longitudeOffset; |
| 426 | const double latitude = Math::lerp(south, north, vRatio) + latitudeOffset; |
| 427 | const double heightMeters = |
| 428 | Math::lerp(minimumHeight, maximumHeight, heightRatio) - skirtHeight; |
| 429 | glm::dvec3 position = ellipsoid.cartographicToCartesian( |
| 430 | Cartographic(longitude, latitude, heightMeters)); |
| 431 | position -= center; |
| 432 | |
| 433 | positions[positionIdx] = static_cast<float>(position.x); |
| 434 | positions[positionIdx + 1] = static_cast<float>(position.y); |
| 435 | positions[positionIdx + 2] = static_cast<float>(position.z); |
| 436 | |
| 437 | positionMinimums = glm::min(positionMinimums, position); |
| 438 | positionMaximums = glm::max(positionMaximums, position); |
| 439 | |
| 440 | if (!normals.empty()) { |
| 441 | const size_t componentIndex = static_cast<size_t>(3 * edgeIdx); |
| 442 | normals[positionIdx] = normals[componentIndex]; |
| 443 | normals[positionIdx + 1] = normals[componentIndex + 1]; |
| 444 | normals[positionIdx + 2] = normals[componentIndex + 2]; |
| 445 | } |
| 446 | |
| 447 | if (i < edgeIndices.size() - 1) { |
| 448 | E nextEdgeIdx = edgeIndices[i + 1]; |
| 449 | indices[indexIdx++] = static_cast<I>(edgeIdx); |
| 450 | indices[indexIdx++] = static_cast<I>(nextEdgeIdx); |
no test coverage detected