diff --git a/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp b/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp index e1036fd7b..d5ad8b3b4 100644 --- a/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp +++ b/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp @@ -1328,6 +1328,7 @@ getIndices(const TIndexAccessor& indicesView, int32 primitiveMode) { break; case CesiumGltf::MeshPrimitive::Mode::TRIANGLES: case CesiumGltf::MeshPrimitive::Mode::POINTS: + case CesiumGltf::MeshPrimitive::Mode::LINES: default: indices.SetNum(static_cast::SizeType>(indicesView.size())); for (int32 i = 0; i < indicesView.size(); ++i) { @@ -1360,6 +1361,7 @@ static void loadPrimitive( switch (primitive.mode) { case CesiumGltf::MeshPrimitive::Mode::POINTS: + case CesiumGltf::MeshPrimitive::Mode::LINES: case CesiumGltf::MeshPrimitive::Mode::TRIANGLES: case CesiumGltf::MeshPrimitive::Mode::TRIANGLE_STRIP: case CesiumGltf::MeshPrimitive::Mode::TRIANGLE_FAN: @@ -1540,8 +1542,10 @@ static void loadPrimitive( bool needToGenerateFlatNormals = normalsAreRequired && !hasNormals; bool needToGenerateTangents = needsTangents && !hasTangents; bool duplicateVertices = needToGenerateFlatNormals || needToGenerateTangents; - duplicateVertices = duplicateVertices && - primitive.mode != CesiumGltf::MeshPrimitive::Mode::POINTS; + duplicateVertices = + duplicateVertices && + primitive.mode != CesiumGltf::MeshPrimitive::Mode::POINTS && + primitive.mode != CesiumGltf::MeshPrimitive::Mode::LINES; uint32 numVertices = duplicateVertices ? uint32(indices.Num()) : uint32(positionView.size()); @@ -1759,7 +1763,8 @@ static void loadPrimitive( section.MinVertexIndex = 0; section.MaxVertexIndex = numVertices - 1; section.bEnableCollision = - primitive.mode != CesiumGltf::MeshPrimitive::Mode::POINTS; + primitive.mode != CesiumGltf::MeshPrimitive::Mode::POINTS && + primitive.mode != CesiumGltf::MeshPrimitive::Mode::LINES; section.bCastShadow = true; section.MaterialIndex = 0; @@ -1786,7 +1791,8 @@ static void loadPrimitive( #if ENGINE_VERSION_5_5_OR_HIGHER // UE 5.5 requires that we do this in order to avoid a crash when ray // tracing is enabled. - if (primitive.mode != CesiumGltf::MeshPrimitive::Mode::POINTS) { + if (primitive.mode != CesiumGltf::MeshPrimitive::Mode::POINTS && + primitive.mode != CesiumGltf::MeshPrimitive::Mode::LINES) { // UE 5.5 requires that we do this in order to avoid a crash when ray // tracing is enabled. RenderData->InitializeRayTracingRepresentationFromRenderingLODs(); @@ -1800,7 +1806,7 @@ static void loadPrimitive( primitiveResult.transform = transform * yInvertMatrix * scaleMatrix; - if (primitive.mode != CesiumGltf::MeshPrimitive::Mode::POINTS && + if (section.bEnableCollision && options.pMeshOptions->pNodeOptions->pModelOptions->createPhysicsMeshes) { if (numVertices != 0 && indices.Num() != 0) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::ChaosCook) @@ -3040,9 +3046,12 @@ static void loadPrimitiveGameThreadPart( UStaticMeshComponent* pMesh = nullptr; ICesiumPrimitive* pCesiumPrimitive = nullptr; - if (meshPrimitive.mode == CesiumGltf::MeshPrimitive::Mode::POINTS) { + if (meshPrimitive.mode == CesiumGltf::MeshPrimitive::Mode::POINTS || + meshPrimitive.mode == CesiumGltf::MeshPrimitive::Mode::LINES) { UCesiumGltfPointsComponent* pPointMesh = NewObject(pGltf, componentName); + pPointMesh->bLinesList = + (meshPrimitive.mode == CesiumGltf::MeshPrimitive::Mode::LINES); pPointMesh->UsesAdditiveRefinement = tile.getRefine() == Cesium3DTilesSelection::TileRefine::Add; pPointMesh->GeometricError = static_cast(tile.getGeometricError()); @@ -3114,7 +3123,8 @@ static void loadPrimitiveGameThreadPart( // sense, but if Unreal will crash trying to generate ray tracing // information for a static mesh without triangles. pStaticMesh->bSupportRayTracing = - meshPrimitive.mode != CesiumGltf::MeshPrimitive::Mode::POINTS; + meshPrimitive.mode != CesiumGltf::MeshPrimitive::Mode::POINTS && + meshPrimitive.mode != CesiumGltf::MeshPrimitive::Mode::LINES; pMesh->SetStaticMesh(pStaticMesh); pStaticMesh->SetFlags( diff --git a/Source/CesiumRuntime/Private/CesiumGltfPointsComponent.cpp b/Source/CesiumRuntime/Private/CesiumGltfPointsComponent.cpp index a7e9fec3f..87611064d 100644 --- a/Source/CesiumRuntime/Private/CesiumGltfPointsComponent.cpp +++ b/Source/CesiumRuntime/Private/CesiumGltfPointsComponent.cpp @@ -18,7 +18,7 @@ FPrimitiveSceneProxy* UCesiumGltfPointsComponent::CreateSceneProxy() { } FCesiumGltfPointsSceneProxy* Proxy = - new FCesiumGltfPointsSceneProxy(this, GetScene()->GetFeatureLevel()); + new FCesiumGltfPointsSceneProxy(this, GetScene()->GetFeatureLevel(), bLinesList); FCesiumGltfPointsSceneProxyTilesetData TilesetData; TilesetData.UpdateFromComponent(this); diff --git a/Source/CesiumRuntime/Private/CesiumGltfPointsComponent.h b/Source/CesiumRuntime/Private/CesiumGltfPointsComponent.h index 1feeb96d6..433fcc9f4 100644 --- a/Source/CesiumRuntime/Private/CesiumGltfPointsComponent.h +++ b/Source/CesiumRuntime/Private/CesiumGltfPointsComponent.h @@ -28,6 +28,8 @@ class UCesiumGltfPointsComponent : public UCesiumGltfPrimitiveComponent { // error. glm::vec3 Dimensions; + bool bLinesList = false; + // Override UPrimitiveComponent interface. virtual FPrimitiveSceneProxy* CreateSceneProxy() override; }; diff --git a/Source/CesiumRuntime/Private/CesiumGltfPointsSceneProxy.cpp b/Source/CesiumRuntime/Private/CesiumGltfPointsSceneProxy.cpp index f0aaa9379..e06e6447b 100644 --- a/Source/CesiumRuntime/Private/CesiumGltfPointsSceneProxy.cpp +++ b/Source/CesiumRuntime/Private/CesiumGltfPointsSceneProxy.cpp @@ -26,6 +26,7 @@ void FCesiumGltfPointsSceneProxyTilesetData::UpdateFromComponent( UsesAdditiveRefinement = Component->UsesAdditiveRefinement; GeometricError = Component->GeometricError; Dimensions = Component->Dimensions; + bLinesList = Component->bLinesList; } SIZE_T FCesiumGltfPointsSceneProxy::GetTypeHash() const { @@ -35,11 +36,12 @@ SIZE_T FCesiumGltfPointsSceneProxy::GetTypeHash() const { FCesiumGltfPointsSceneProxy::FCesiumGltfPointsSceneProxy( UCesiumGltfPointsComponent* InComponent, - ERHIFeatureLevel::Type InFeatureLevel) + ERHIFeatureLevel::Type InFeatureLevel, + bool bLinesList) : FPrimitiveSceneProxy(InComponent), RenderData(InComponent->GetStaticMesh()->GetRenderData()), NumPoints(RenderData->LODResources[0].IndexBuffer.GetNumIndices()), - bAttenuationSupported( + bAttenuationSupported(!bLinesList && RHISupportsManualVertexFetch(GetScene().GetShaderPlatform())), TilesetData(), AttenuationVertexFactory( @@ -116,6 +118,7 @@ uint32 FCesiumGltfPointsSceneProxy::GetMemoryFootprint(void) const { void FCesiumGltfPointsSceneProxy::UpdateTilesetData( const FCesiumGltfPointsSceneProxyTilesetData& InTilesetData) { TilesetData = InTilesetData; + ensure(!TilesetData.bLinesList || !bAttenuationSupported); // see ctor } float FCesiumGltfPointsSceneProxy::GetGeometricError() const { @@ -208,17 +211,22 @@ void FCesiumGltfPointsSceneProxy::CreateMesh(FMeshBatch& Mesh) const { Mesh.VertexFactory = &RenderData->LODVertexFactories[0].VertexFactory; Mesh.MaterialRenderProxy = Material->GetRenderProxy(); Mesh.ReverseCulling = IsLocalToWorldDeterminantNegative(); - Mesh.Type = PT_PointList; + Mesh.Type = TilesetData.bLinesList ? PT_LineList : PT_PointList; Mesh.DepthPriorityGroup = SDPG_World; Mesh.LODIndex = 0; Mesh.bCanApplyViewModeOverrides = false; Mesh.bUseAsOccluder = false; - Mesh.bWireframe = false; + Mesh.bWireframe = TilesetData.bLinesList; FMeshBatchElement& BatchElement = Mesh.Elements[0]; BatchElement.IndexBuffer = &RenderData->LODResources[0].IndexBuffer; - BatchElement.NumPrimitives = NumPoints; BatchElement.FirstIndex = 0; BatchElement.MinVertexIndex = 0; - BatchElement.MaxVertexIndex = BatchElement.NumPrimitives - 1; + BatchElement.MaxVertexIndex = NumPoints - 1; + if (TilesetData.bLinesList) { + ensure((NumPoints % 2) == 0); + BatchElement.NumPrimitives = NumPoints / 2; + } else { + BatchElement.NumPrimitives = NumPoints; + } } diff --git a/Source/CesiumRuntime/Private/CesiumGltfPointsSceneProxy.h b/Source/CesiumRuntime/Private/CesiumGltfPointsSceneProxy.h index 0b4295490..5df5482be 100644 --- a/Source/CesiumRuntime/Private/CesiumGltfPointsSceneProxy.h +++ b/Source/CesiumRuntime/Private/CesiumGltfPointsSceneProxy.h @@ -19,6 +19,7 @@ struct FCesiumGltfPointsSceneProxyTilesetData { bool UsesAdditiveRefinement; float GeometricError; glm::vec3 Dimensions; + bool bLinesList; FCesiumGltfPointsSceneProxyTilesetData(); @@ -36,7 +37,8 @@ class FCesiumGltfPointsSceneProxy final : public FPrimitiveSceneProxy { FCesiumGltfPointsSceneProxy( UCesiumGltfPointsComponent* InComponent, - ERHIFeatureLevel::Type InFeatureLevel); + ERHIFeatureLevel::Type InFeatureLevel, + bool bLinesList); virtual ~FCesiumGltfPointsSceneProxy();