Skip to content

Commit

Permalink
Upgrade to UINT32 indices when necessary.
Browse files Browse the repository at this point in the history
  • Loading branch information
kring committed Dec 23, 2024
1 parent 2d36729 commit 966a5e9
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 19 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
##### Fixes :wrench:

- Fixed a bug that could cause a crash or incorrect textures when multiple `Cesium3DTileset` tiles referenced the same image by URL.
- Fixed a bug that could cause incorrect colors in a model that did have vertex colors but did not have normals.
- Fixed a bug that could cause a hang when attempting to load a model with UINT16 indices where generating flat normals required more than 2^16 vertices.

## v1.14.0 - 2024-12-02

Expand Down
43 changes: 43 additions & 0 deletions Tests/TestCesium3DTileset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,4 +156,47 @@ public IEnumerator SampleHeightMostDetailedFailsIfTilesetFailsToLoad()

Assert.IsTrue(result.warnings[0].Contains("failed to load"));
}

[UnityTest]
public IEnumerator UpgradeToLargerIndexType()
{
// This tileset has no normals, so we need to generate flat normals for it.
// When we do that, an index buffer will need to change from uint16 to uint32.
GameObject goGeoreference = new GameObject();
goGeoreference.name = "Georeference";
CesiumGeoreference georeference = goGeoreference.AddComponent<CesiumGeoreference>();

GameObject goTileset = new GameObject();
goTileset.name = "Snowdon Towers No Normals";
goTileset.transform.parent = goGeoreference.transform;

Cesium3DTileset tileset = goTileset.AddComponent<Cesium3DTileset>();
CesiumCameraManager cameraManager = goTileset.AddComponent<CesiumCameraManager>();
tileset.ionAccessToken = Environment.GetEnvironmentVariable("CESIUM_ION_TOKEN_FOR_TESTS") ?? "";
tileset.ionAssetID = 2887128;

georeference.SetOriginLongitudeLatitudeHeight(-79.88602625, 40.02228799, 222.65);

GameObject goCamera = new GameObject();
goCamera.name = "Camera";
goCamera.transform.parent = goGeoreference.transform;

Camera camera = goCamera.AddComponent<Camera>();
CesiumGlobeAnchor cameraAnchor = goCamera.AddComponent<CesiumGlobeAnchor>();

cameraManager.useMainCamera = false;
cameraManager.useSceneViewCameraInEditor = false;
cameraManager.additionalCameras.Add(camera);

camera.pixelRect = new Rect(0, 0, 128, 96);
camera.fieldOfView = 60.0f;
cameraAnchor.longitudeLatitudeHeight = new double3(-79.88593359, 40.02255615, 242.0224);
camera.transform.LookAt(new Vector3(0.0f, 0.0f, 0.0f));

// Make sure we can load all tiles successfully.
while (tileset.ComputeLoadProgress() < 100.0f)
{
yield return null;
}
}
}
55 changes: 37 additions & 18 deletions native~/Runtime/src/UnityPrepareRendererResources.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,43 @@ void loadPrimitive(
return;
}

const CesiumGltf::Material* pMaterial =
Model::getSafe(&gltf.materials, primitive.material);

primitiveInfo.isUnlit =
pMaterial && pMaterial->hasExtension<ExtensionKhrMaterialsUnlit>();

bool hasNormals = false;
bool computeFlatNormals = false;
auto normalAccessorIt = primitive.attributes.find("NORMAL");
AccessorView<UnityEngine::Vector3> normalView;
if (normalAccessorIt != primitive.attributes.end()) {
normalView =
AccessorView<UnityEngine::Vector3>(gltf, normalAccessorIt->second);
hasNormals = normalView.status() == AccessorViewStatus::Valid;
} else if (
!primitiveInfo.isUnlit && primitive.mode != MeshPrimitive::Mode::POINTS) {
computeFlatNormals = hasNormals = true;
}

// Check if we need to upgrade to a large index type to accommodate the
// larger number of vertices we need for flat normals.
if (computeFlatNormals && indexFormat == IndexFormat::UInt16 &&
indexCount >= std::numeric_limits<uint16_t>::max()) {
loadPrimitive<uint32_t>(
meshData,
primitiveInfo,
gltf,
node,
mesh,
primitive,
transform,
indicesView,
IndexFormat::UInt32,
positionView);
return;
}

meshData.SetIndexBufferParams(indexCount, indexFormat);
const Unity::Collections::NativeArray1<TIndex>& dest =
meshData.GetIndexData<TIndex>();
Expand Down Expand Up @@ -399,25 +436,7 @@ void loadPrimitive(
descriptor[numberOfAttributes].stream = streamIndex;
++numberOfAttributes;

const CesiumGltf::Material* pMaterial =
Model::getSafe(&gltf.materials, primitive.material);

primitiveInfo.isUnlit =
pMaterial && pMaterial->hasExtension<ExtensionKhrMaterialsUnlit>();

// Add the NORMAL attribute, if it exists.
bool hasNormals = false;
bool computeFlatNormals = false;
auto normalAccessorIt = primitive.attributes.find("NORMAL");
AccessorView<UnityEngine::Vector3> normalView;
if (normalAccessorIt != primitive.attributes.end()) {
normalView =
AccessorView<UnityEngine::Vector3>(gltf, normalAccessorIt->second);
hasNormals = normalView.status() == AccessorViewStatus::Valid;
} else if (
!primitiveInfo.isUnlit && primitive.mode != MeshPrimitive::Mode::POINTS) {
computeFlatNormals = hasNormals = true;
}
if (hasNormals) {
assert(numberOfAttributes < MAX_ATTRIBUTES);
descriptor[numberOfAttributes].attribute = VertexAttribute::Normal;
Expand Down
2 changes: 1 addition & 1 deletion native~/extern/cesium-native
Submodule cesium-native updated 404 files

0 comments on commit 966a5e9

Please sign in to comment.