@@ -409,19 +409,24 @@ void copyMetadataTables(const Model& parentModel, Model& result);
409
409
* the indices from an index accessor view, or generates new indices.
410
410
*/
411
411
template <typename TIndex> struct IndicesViewOrGenerator {
412
- IndicesViewOrGenerator (AccessorView<TIndex>&& accessorView_)
413
- : accessorView(accessorView_), indicesCount(accessorView->size ()) {}
414
-
415
- IndicesViewOrGenerator (int64_t indicesCount_) : indicesCount(indicesCount_) {}
416
-
417
412
IndicesViewOrGenerator (
418
413
const Model& model,
414
+ const MeshPrimitive& primitive,
419
415
int32_t primitiveIndices,
420
- int64_t numVertices) {
416
+ int64_t numVertices)
417
+ : primitiveMode(primitive.mode) {
421
418
AccessorView<TIndex> view (model, primitiveIndices);
422
419
if (view.status () == AccessorViewStatus::Valid) {
423
420
accessorView = std::move (view);
424
- indicesCount = accessorView->size ();
421
+ if (primitiveMode == MeshPrimitive::Mode::TRIANGLES) {
422
+ indicesCount = accessorView->size ();
423
+ } else if (
424
+ primitiveMode == MeshPrimitive::Mode::TRIANGLE_STRIP ||
425
+ primitiveMode == MeshPrimitive::Mode::TRIANGLE_FAN) {
426
+ // With a triangle strip or fan, each additional vertex past the first
427
+ // three adds an additional triangle
428
+ indicesCount = (accessorView->size () - 2 ) * 3 ;
429
+ }
425
430
} else {
426
431
indicesCount = numVertices;
427
432
}
@@ -442,8 +447,31 @@ template <typename TIndex> struct IndicesViewOrGenerator {
442
447
throw std::range_error (" index out of range" );
443
448
}
444
449
445
- if (accessorView) {
450
+ if (accessorView && primitiveMode == MeshPrimitive::Mode::TRIANGLES ) {
446
451
return (*accessorView)[i];
452
+ } else if (
453
+ accessorView && primitiveMode == MeshPrimitive::Mode::TRIANGLE_STRIP) {
454
+ // Indices 0, 1, 2 map normally, indices 3, 4, 5 map to 2, 1, 3,
455
+ // indices 6, 7, 8 map to 2, 3, 4, etc.
456
+ const int64_t startIndex = i / 3 ;
457
+ const int64_t triIndex = i % 3 ;
458
+ // For every other triangle we need to reverse the order of the first two
459
+ // indices to maintain proper winding.
460
+ if (startIndex % 2 == 1 && triIndex < 2 ) {
461
+ return triIndex == 0 ? (*accessorView)[startIndex + 1 ]
462
+ : (*accessorView)[startIndex];
463
+ }
464
+ return (*accessorView)[startIndex + triIndex];
465
+ } else if (
466
+ accessorView && primitiveMode == MeshPrimitive::Mode::TRIANGLE_FAN) {
467
+ // Indices 0, 1, 2 map normally, indices 3, 4, 5 map to 0, 2, 3,
468
+ // indices 6, 7, 8 map to 0, 3, 4, etc.
469
+ const int64_t startIndex = i / 3 ;
470
+ const int64_t triIndex = i % 3 ;
471
+ if (triIndex == 0 ) {
472
+ return (*accessorView)[0 ];
473
+ }
474
+ return (*accessorView)[startIndex + triIndex];
447
475
}
448
476
449
477
// The indices of a non-indexed primitive are simply 0, 1, 2, 3, 4...
@@ -453,6 +481,7 @@ template <typename TIndex> struct IndicesViewOrGenerator {
453
481
private:
454
482
std::optional<AccessorView<TIndex>> accessorView;
455
483
int64_t indicesCount;
484
+ int32_t primitiveMode;
456
485
};
457
486
458
487
} // namespace
@@ -958,6 +987,7 @@ bool upsamplePrimitiveForRasterOverlays(
958
987
const AccessorView<glm::vec2> uvView (parentModel, uvAccessorIndex);
959
988
const IndicesViewOrGenerator<TIndex> indicesView (
960
989
parentModel,
990
+ primitive,
961
991
primitive.indices ,
962
992
positionAttributeCount);
963
993
@@ -1624,7 +1654,9 @@ bool upsamplePrimitiveForRasterOverlays(
1624
1654
const std::string_view& textureCoordinateAttributeBaseName,
1625
1655
int32_t textureCoordinateIndex,
1626
1656
const CesiumGeospatial::Ellipsoid& ellipsoid) {
1627
- if (primitive.mode != MeshPrimitive::Mode::TRIANGLES) {
1657
+ if (primitive.mode != MeshPrimitive::Mode::TRIANGLES &&
1658
+ primitive.mode != MeshPrimitive::Mode::TRIANGLE_FAN &&
1659
+ primitive.mode != MeshPrimitive::Mode::TRIANGLE_STRIP) {
1628
1660
// Not triangles, so we don't know how to divide this primitive
1629
1661
// (yet). So remove it.
1630
1662
return false ;
0 commit comments