@@ -328,6 +328,10 @@ void loadPrimitive(
328328 using namespace DotNet ::Unity::Collections;
329329 using namespace DotNet ::Unity::Collections::LowLevel::Unsafe;
330330
331+ static int flipMask = 0 ;
332+ if (flipMask++ > 15 )
333+ flipMask = 0 ;
334+
331335 CESIUM_TRACE (" Cesium::loadPrimitive<T>" );
332336 int32_t indexCount = 0 ;
333337 switch (primitive.mode ) {
@@ -368,6 +372,19 @@ void loadPrimitive(
368372 !primitiveInfo.isUnlit && primitive.mode != MeshPrimitive::Mode::POINTS) {
369373 computeFlatNormals = hasNormals = true ;
370374 }
375+ const bool duplicateVertices = computeFlatNormals;
376+
377+
378+ static bool ignoreTangents = true ;
379+ bool hasTangents = false ;
380+ AccessorView<UnityEngine::Vector4> tangentView {};
381+ auto tangentAccessorIt = primitive.attributes .find (" TANGENT" );
382+ if (tangentAccessorIt != primitive.attributes .end ()) {
383+ tangentView =
384+ AccessorView<UnityEngine::Vector4>(gltf, tangentAccessorIt->second );
385+ hasTangents = tangentView.status () == AccessorViewStatus::Valid;
386+ }
387+ hasTangents &= !ignoreTangents;
371388
372389 // Check if we need to upgrade to a large index type to accommodate the
373390 // larger number of vertices we need for flat normals.
@@ -450,6 +467,15 @@ void loadPrimitive(
450467 ++numberOfAttributes;
451468 }
452469
470+ if (hasTangents) {
471+ assert (numberOfAttributes < MAX_ATTRIBUTES);
472+ descriptor[numberOfAttributes].attribute = VertexAttribute::Tangent;
473+ descriptor[numberOfAttributes].format = VertexAttributeFormat::Float32;
474+ descriptor[numberOfAttributes].dimension = 4 ;
475+ descriptor[numberOfAttributes].stream = streamIndex;
476+ ++numberOfAttributes;
477+ }
478+
453479 // Add the COLOR_0 attribute, if it exists.
454480 auto colorAccessorIt = primitive.attributes .find (" COLOR_0" );
455481 bool hasVertexColors =
@@ -554,9 +580,9 @@ void loadPrimitive(
554580 attributes.Item (i, descriptor[i]);
555581 }
556582
557- int32_t vertexCount = computeFlatNormals
558- ? indexCount
559- : static_cast <int32_t >(positionView.size ());
583+ const int32_t vertexCount = computeFlatNormals
584+ ? indexCount
585+ : static_cast <int32_t >(positionView.size ());
560586 meshData.SetVertexBufferParams (vertexCount, attributes);
561587
562588 NativeArray1<uint8_t > nativeVertexBuffer =
@@ -571,15 +597,22 @@ void loadPrimitive(
571597 // The vertex layout will be as follows:
572598 // 1. position
573599 // 2. normals (skip if N/A)
574- // 3. vertex colors (skip if N/A)
575- // 4. texcoords (first all TEXCOORD_i, then all _CESIUMOVERLAY_i)
600+ // 3. tangents (skip if N/A)
601+ // 4. vertex colors (skip if N/A)
602+ // 5. texcoords (first all TEXCOORD_i, then all _CESIUMOVERLAY_i)
576603
577604 size_t stride = sizeof (Vector3);
578- size_t normalByteOffset, colorByteOffset ;
605+ size_t normalByteOffset;
579606 if (hasNormals) {
580607 normalByteOffset = stride;
581608 stride += sizeof (Vector3);
582609 }
610+
611+ if (hasTangents) {
612+ stride += sizeof (Vector4);
613+ }
614+
615+ size_t colorByteOffset;
583616 if (hasVertexColors) {
584617 colorByteOffset = stride;
585618 stride += sizeof (uint32_t );
@@ -593,63 +626,71 @@ void loadPrimitive(
593626 indices,
594627 indexCount,
595628 positionView);
596- for (int64_t i = 0 ; i < vertexCount; ++i) {
597- TIndex vertexIndex = indices[i];
598- *reinterpret_cast <Vector3*>(pWritePos) = positionView[vertexIndex];
599- // skip position and normal
600- pWritePos += 2 * sizeof (Vector3);
601- // Skip the slot allocated for vertex colors, we will fill them in
602- // bulk later.
603- if (hasVertexColors) {
604- pWritePos += sizeof (uint32_t );
605- }
606- for (uint32_t texCoordIndex = 0 ; texCoordIndex < numTexCoords;
607- ++texCoordIndex) {
608- *reinterpret_cast <Vector2*>(pWritePos) =
609- texCoordViews[texCoordIndex][vertexIndex];
610- pWritePos += sizeof (Vector2);
611- }
612- }
613- } else {
614- for (int64_t i = 0 ; i < vertexCount; ++i) {
615- *reinterpret_cast <Vector3*>(pWritePos) = positionView[i];
629+ }
630+
631+ for (int64_t i = 0 ; i < vertexCount; ++i) {
632+ const TIndex vertexIndex = duplicateVertices ? indices[i] : i;
633+ *reinterpret_cast <Vector3*>(pWritePos) = positionView[vertexIndex];
634+ pWritePos += sizeof (Vector3);
635+
636+ if (computeFlatNormals) {
637+ // skip computed normal
638+ pWritePos += sizeof (Vector3);
639+ } else if (hasNormals) {
640+ *reinterpret_cast <Vector3*>(pWritePos) = normalView[vertexIndex];
616641 pWritePos += sizeof (Vector3);
642+ }
617643
618- if (hasNormals) {
619- *reinterpret_cast <Vector3*>(pWritePos) = normalView[i];
620- pWritePos += sizeof (Vector3);
621- }
644+ if (hasTangents) {
645+ Vector4 tangent = tangentView[vertexIndex];
646+ // *reinterpret_cast<Vector4*>(pWritePos) = tangentView[vertexIndex];
647+ // tangent.w *= -1;
648+ // if (flipMask & 1) {
649+ // tangent.x *= -1;
650+ // }
651+ // if (flipMask & 2) {
652+ // tangent.y *= -1;
653+ // }
654+ // if (flipMask & 4) {
655+ // tangent.z *= -1;
656+ // }
657+ // if (flipMask & 8) {
658+ // tangent.w *= -1;
659+ // }
660+
661+ *reinterpret_cast <Vector4*>(pWritePos) = tangent;
662+ pWritePos += sizeof (Vector4);
663+ }
622664
623- // Skip the slot allocated for vertex colors, we will fill them in
624- // bulk later.
625- if (hasVertexColors) {
626- pWritePos += sizeof (uint32_t );
627- }
665+ // Skip the slot allocated for vertex colors, we will fill them in
666+ // bulk later.
667+ if (hasVertexColors) {
668+ pWritePos += sizeof (uint32_t );
669+ }
628670
629- for (uint32_t texCoordIndex = 0 ; texCoordIndex < numTexCoords;
630- ++texCoordIndex) {
631- *reinterpret_cast <Vector2*>(pWritePos) =
632- texCoordViews[texCoordIndex][i];
633- pWritePos += sizeof (Vector2);
634- }
671+ for (uint32_t texCoordIndex = 0 ; texCoordIndex < numTexCoords;
672+ ++texCoordIndex) {
673+ *reinterpret_cast <Vector2*>(pWritePos) =
674+ texCoordViews[texCoordIndex][i];
675+ pWritePos += sizeof (Vector2);
635676 }
636677 }
637678
638679 // Fill in vertex colors separately, if they exist.
639680 if (hasVertexColors) {
640- // Color comes after position and normal.
681+ // Color comes after position, normal and tangent
641682 createAccessorView (
642683 gltf,
643684 colorAccessorIt->second ,
644685 CopyVertexColors<TIndex>{
645686 pBufferStart + colorByteOffset,
646687 stride,
647688 static_cast <size_t >(vertexCount),
648- computeFlatNormals ,
689+ duplicateVertices ,
649690 indices});
650691 }
651692
652- if (computeFlatNormals ) {
693+ if (duplicateVertices ) {
653694 // rewrite indices
654695 for (TIndex i = 0 ; i < indexCount; i++) {
655696 indices[i] = i;
0 commit comments